Como posso adicionar recursos (imagens, arquivos de som, shaders, etc…) a um projeto NDK com Gradle?
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, file
está 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 AAssetManager
snippet acima?
Alguma experimentação adicional:
Eu alterei o assets.srcDirs
caminho 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 resources
pasta, ele não enumera nada). Não tenho ideia se é porque AAssetDir_getNextFileName
literalmente só obtém arquivos , ou se o gradle srcDirs
só copia arquivos, ou se todo o AAssetManager
ecossistema 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.gradle
arquivo o seguinte snippet:
externalNativeBuild {
cmake {
version "3.18.1"
path "../CMakeLists.txt"
buildStagingDirectory buildDir
}
}
Respostas
Ok, então meu problema era triplo:
- 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!)
- quando eu defino a pasta para ser
resources
, isso não resulta emroot/resources/{images,shaders}
; isso resulta emroot/{images,shaders}
. (Se alguém souber como especificar, em vez disso, me avise!) AAssetDir_getNextFileName
não enumera pastas. (Não há nada que eu possa fazer sobre isso!)
Eu sugeriria simplesmente usar em
AAssetManager_open(aassman, "/images/blah0.png")
vez defopen("resources/images/blah0.png", "r")
, mas se for tão importante para você, você pode definirassets.srcDirs 'build/cmake/release/arm64-v8a
e excluir tudo, exceto"resources"
.Aqui está um esboço de uma solução C ++ puro. Alternativamente, você também pode chamar a API Java (como aqui ) via JNI.