Comment puis-je ajouter des ressources (images, fichiers son, shaders, etc…) à un projet NDK avec Gradle?
Dans la version PC de cette base de code, j'ai simplement la structure de répertoires suivante:
- myApp.exe
- resources
- - images
- - - blah0.png
- - - blah1.png
- - shaders
- - - blahA.spv
- - - blahB.spv
Donc, à partir de mon code C ++, je peux simplement demander fopen("resources/images/blah0.png",...)
, par exemple.
Avec Android, il semble plutôt nécessaire de
#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);
Malheureusement, cela file
arrive nullptr
, probablement parce qu'il ne trouve pas cet arbre de ressources.
Mon script build.gradle contient l'extrait de code suivant:
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
assets.srcDirs 'build/cmake/release/arm64-v8a/resources'
}
}
^ Cela pointe vers le même répertoire de ressources décrit en haut de cette liste.
Que dois-je faire pour m'assurer que la hiérarchie des ressources ci-dessus est simplement transférée dans mon .apk de sorte qu'elle puisse être accessible via l' AAssetManager
extrait ci-dessus?
Quelques expérimentations supplémentaires:
J'ai changé le assets.srcDirs
chemin vers some/random/path/on/my/hd
, puis j'ai couru
AAssetDir *rootAssets = AAssetManager_openDir(aassman, "");
const char *f = AAssetDir_getNextFileName(rootAssets);
while(f)
{
print(f);
f = AAssetDir_getNextFileName(rootAssets);
}
AAssetDir_close(rootAssets);
qui énumère simplement les fichiers trouvés dans le répertoire supérieur. J'ai remarqué qu'il a énuméré tous les fichiers qui étaient dans some/random/path/on/my/hd
, mais aucun des répertoires . (Quand je le pointe vers mon resources
dossier, il n'énumère rien). Je n'ai aucune idée si c'est parce que AAssetDir_getNextFileName
littéralement ne reçoit que des fichiers , ou si gradle srcDirs
ne copie que des fichiers, ou si tout l' AAssetManager
écosystème ne fonctionne que sur des répertoires plats, ou quoi.
Je suis étonné qu'il n'y ait pas de documentation claire montrant le cas d'utilisation de "inclure un répertoire de ressources avec votre application NDK", car cela semble être une chose vraiment normale à faire.
edit: on m'a demandé des éclaircissements concernant "comment cmake est exécuté". J'ai dans mon build.gradle
fichier, l'extrait suivant:
externalNativeBuild {
cmake {
version "3.18.1"
path "../CMakeLists.txt"
buildStagingDirectory buildDir
}
}
Réponses
Ok donc mon problème était triple:
- gradle est en charge de la construction de mon projet cmake qui construit le dossier des ressources. comme il n'y a pas de dépendance explicite entre le processus cmake et le conditionnement des actifs, il semblait avoir été extrait de ce dossier à un moment imprévisible (potentiellement avant la fin de sa construction). (Si quelqu'un sait comment spécifier une telle dépendance, faites-le moi savoir!)
- quand je mis le dossier à
resources
, il ne résulte enroot/resources/{images,shaders}
; il en résulteroot/{images,shaders}
. (Si quelqu'un sait comment spécifier de faire le premier, merci de me le faire savoir!) AAssetDir_getNextFileName
n'énumère pas les dossiers. (Je ne peux rien y faire!)
Je suggérerais d'utiliser simplement à la
AAssetManager_open(aassman, "/images/blah0.png")
place defopen("resources/images/blah0.png", "r")
, mais si c'est si important pour vous, vous pouvez définirassets.srcDirs 'build/cmake/release/arm64-v8a
et exclure tout sauf"resources"
.Voici un aperçu d'une solution purement C ++. Vous pouvez également appeler l'API Java (comme ici ) via JNI.