¿Cómo puedo agregar recursos (imágenes, archivos de sonido, sombreadores, etc.) a un proyecto NDK con Gradle?
En la versión para PC de este código base, simplemente tengo la siguiente estructura de directorio:
- myApp.exe
- resources
- - images
- - - blah0.png
- - - blah1.png
- - shaders
- - - blahA.spv
- - - blahB.spv
Entonces, desde mi código C ++, simplemente puedo solicitar fopen("resources/images/blah0.png",...)
, por ejemplo.
Con Android, parece ser necesario
#include <android/native_activity.h>
...
AAsset* file = AAssetManager_open(aassman, "resources/images/blah0.png", AASSET_MODE_STREAMING);
size_t len = AAsset_getRemainingLength64(file);
char *buff = malloc(len);
size_t read = AAsset_read(file, buff, len);
AAsset_close(file);
Desafortunadamente, file
se acerca nullptr
, probablemente porque no puede encontrar ese árbol de recursos.
Mi script build.gradle tiene el siguiente fragmento:
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
assets.srcDirs 'build/cmake/release/arm64-v8a/resources'
}
}
^ Eso apunta al mismo directorio de recursos descrito en la parte superior de esta lista.
¿Qué debo hacer para asegurarme de que la jerarquía de recursos anterior se transfiera simplemente a mi .apk de modo que se pueda acceder a través del AAssetManager
fragmento anterior?
Alguna experimentación adicional:
Alteré el assets.srcDirs
camino some/random/path/on/my/hd
y luego corrí
AAssetDir *rootAssets = AAssetManager_openDir(aassman, "");
const char *f = AAssetDir_getNextFileName(rootAssets);
while(f)
{
print(f);
f = AAssetDir_getNextFileName(rootAssets);
}
AAssetDir_close(rootAssets);
que simplemente enumera los archivos encontrados en el directorio superior. Noté que enumeraba todos los archivos que estaban some/random/path/on/my/hd
, pero ninguno de los directorios . (Cuando lo apunto a mi resources
carpeta, no enumera nada). No tengo idea si eso es porque AAssetDir_getNextFileName
literalmente solo obtiene archivos , o si gradle srcDirs
solo copia archivos, o si todo el AAssetManager
ecosistema solo funciona en directorios planos, o qué.
Estoy asombrado de que no haya documentación clara que muestre el caso de uso de "incluir un directorio de recursos con su aplicación NDK", ya que parece algo muy normal.
editar: Me pidieron una aclaración sobre: "cómo se ejecuta cmake". Tengo como parte de mi build.gradle
archivo, el siguiente fragmento:
externalNativeBuild {
cmake {
version "3.18.1"
path "../CMakeLists.txt"
buildStagingDirectory buildDir
}
}
Respuestas
Ok, entonces mi problema era triple:
- gradle está a cargo de construir mi proyecto cmake que construye la carpeta de recursos. debido a que no existe una dependencia explícita entre el proceso de cmake y el empaquetado de activos, parecía haber estado extrayendo de esa carpeta en un momento impredecible (potencialmente antes de que finalice su construcción). (Si alguien sabe cómo especificar tal dependencia, ¡hágamelo saber!)
- cuando configuro la carpeta
resources
, no da como resultadoroot/resources/{images,shaders}
; resulta enroot/{images,shaders}
. (Si alguien sabe cómo especificar que en su lugar haga lo primero, ¡hágamelo saber!) AAssetDir_getNextFileName
no enumera carpetas. (¡No hay nada que pueda hacer al respecto!)
Sugeriría simplemente usar en
AAssetManager_open(aassman, "/images/blah0.png")
lugar defopen("resources/images/blah0.png", "r")
, pero si es tan importante para usted, puede configurarassets.srcDirs 'build/cmake/release/arm64-v8a
y excluir todo excepto"resources"
.Aquí hay un esquema de una solución de C ++ puro. Alternativamente, también puede llamar a la API de Java (como aquí ) a través de JNI.