Como posso adicionar recursos (imagens, arquivos de som, shaders, etc…) a um projeto NDK com Gradle?

Aug 19 2020

Na versão para PC desta base de código, simplesmente tenho a seguinte estrutura de diretório:

 - myApp.exe
 - resources
 - - images
 - - - blah0.png
 - - - blah1.png
 - - shaders
 - - - blahA.spv
 - - - blahB.spv

Portanto, a partir do meu código C ++, posso simplesmente solicitar fopen("resources/images/blah0.png",...), por exemplo.

Com o Android, parece ser necessário

#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);

Infelizmente, fileestá chegando nullptr, provavelmente porque não consegue encontrar a árvore de recursos.

Meu script build.gradle tem o seguinte snippet:

  sourceSets {
    main {
      manifest.srcFile 'AndroidManifest.xml'
      assets.srcDirs 'build/cmake/release/arm64-v8a/resources'
    }
  }

^ Isso aponta para o mesmo diretório de recursos descrito no topo desta lista.


O que preciso fazer para garantir que a hierarquia de recursos acima seja simplesmente transferida para meu .apk de forma que possa ser acessada por meio do AAssetManagersnippet acima?


Alguma experimentação adicional:

Eu alterei o assets.srcDirscaminho para some/random/path/on/my/hd, e então corri

  AAssetDir *rootAssets = AAssetManager_openDir(aassman, "");
  const char *f = AAssetDir_getNextFileName(rootAssets);
  while(f)
  {
    print(f);
    f = AAssetDir_getNextFileName(rootAssets);
  }
  AAssetDir_close(rootAssets);

que simplesmente enumera os arquivos encontrados no diretório superior. Percebi que enumerou todos os arquivos que estavam some/random/path/on/my/hd, mas nenhum dos diretórios . (Quando eu aponto para minha resourcespasta, ele não enumera nada). Não tenho ideia se é porque AAssetDir_getNextFileNameliteralmente só obtém arquivos , ou se o gradle srcDirscopia arquivos, ou se todo o AAssetManagerecossistema só funciona em diretórios planos, ou o quê.

Estou surpreso que não haja uma documentação clara mostrando o caso de uso de "incluir um diretório de recursos com seu aplicativo NDK", pois isso parece uma coisa realmente normal de se fazer.


editar: Pediram-me esclarecimentos sobre: ​​"como o cmake é executado". Tenho como parte do meu build.gradlearquivo o seguinte snippet:

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

Respostas

1 Phildo Aug 18 2020 at 23:23

Ok, então meu problema era triplo:

  1. gradle é responsável por construir meu projeto cmake, que constrói a pasta de recursos. como não há dependência explícita dada entre o processo cmake e o empacotamento de ativos, parecia ter sido puxado dessa pasta em um momento imprevisível (potencialmente antes de sua construção ser concluída). (Se alguém souber como especificar essa dependência, por favor me avise!)
  2. quando eu defino a pasta para ser resources, isso não resulta em root/resources/{images,shaders}; isso resulta em root/{images,shaders}. (Se alguém souber como especificar, em vez disso, me avise!)
  3. AAssetDir_getNextFileName não enumera pastas. (Não há nada que eu possa fazer sobre isso!)
1 AlexCohn Aug 24 2020 at 15:54
  1. Eu sugeriria simplesmente usar em AAssetManager_open(aassman, "/images/blah0.png")vez de fopen("resources/images/blah0.png", "r"), mas se for tão importante para você, você pode definir assets.srcDirs 'build/cmake/release/arm64-v8ae excluir tudo, exceto "resources".

  2. Aqui está um esboço de uma solução C ++ puro. Alternativamente, você também pode chamar a API Java (como aqui ) via JNI.