¿Cómo puedo agregar recursos (imágenes, archivos de sonido, sombreadores, etc.) a un proyecto NDK con Gradle?

Aug 19 2020

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, filese 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 AAssetManagerfragmento anterior?


Alguna experimentación adicional:

Alteré el assets.srcDirscamino some/random/path/on/my/hdy 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 resourcescarpeta, no enumera nada). No tengo idea si eso es porque AAssetDir_getNextFileNameliteralmente solo obtiene archivos , o si gradle srcDirssolo copia archivos, o si todo el AAssetManagerecosistema 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.gradlearchivo, el siguiente fragmento:

  externalNativeBuild {
    cmake {
      version "3.18.1"
      path "../CMakeLists.txt"
      buildStagingDirectory buildDir
    }
  }

Respuestas

1 Phildo Aug 18 2020 at 23:23

Ok, entonces mi problema era triple:

  1. 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!)
  2. cuando configuro la carpeta resources, no da como resultado root/resources/{images,shaders}; resulta en root/{images,shaders}. (Si alguien sabe cómo especificar que en su lugar haga lo primero, ¡hágamelo saber!)
  3. AAssetDir_getNextFileName no enumera carpetas. (¡No hay nada que pueda hacer al respecto!)
1 AlexCohn Aug 24 2020 at 15:54
  1. Sugeriría simplemente usar en AAssetManager_open(aassman, "/images/blah0.png")lugar de fopen("resources/images/blah0.png", "r"), pero si es tan importante para usted, puede configurar assets.srcDirs 'build/cmake/release/arm64-v8ay excluir todo excepto "resources".

  2. 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.