Come posso aggiungere risorse (immagini, file audio, shader, ecc ...) a un progetto NDK con Gradle?
Nella versione per PC di questo codice base, ho semplicemente la seguente struttura di directory:
- myApp.exe
- resources
- - images
- - - blah0.png
- - - blah1.png
- - shaders
- - - blahA.spv
- - - blahB.spv
Quindi, dal mio codice C ++, posso semplicemente richiedere fopen("resources/images/blah0.png",...)
, ad esempio.
Con Android, sembra invece essere necessario
#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);
Sfortunatamente, file
sta arrivando nullptr
, probabilmente perché non riesce a trovare l'albero delle risorse.
Il mio script build.gradle ha il seguente frammento:
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
assets.srcDirs 'build/cmake/release/arm64-v8a/resources'
}
}
^ Questo punta alla stessa directory delle risorse delineata all'inizio di questo elenco.
Cosa devo fare per assicurarmi che la gerarchia delle risorse di cui sopra venga semplicemente trasferita nel mio .apk in modo tale da potervi accedere tramite lo AAssetManager
snippet sopra?
Qualche ulteriore sperimentazione:
Ho modificato il assets.srcDirs
percorso in some/random/path/on/my/hd
e poi sono corso
AAssetDir *rootAssets = AAssetManager_openDir(aassman, "");
const char *f = AAssetDir_getNextFileName(rootAssets);
while(f)
{
print(f);
f = AAssetDir_getNextFileName(rootAssets);
}
AAssetDir_close(rootAssets);
che enumera semplicemente i file trovati nella directory principale. Ho notato che enumerava tutti i file che erano dentro some/random/path/on/my/hd
, ma nessuna delle directory . (Quando lo indico alla mia resources
cartella, non enumera nulla). Non ho idea se è perché AAssetDir_getNextFileName
letteralmente ottiene solo file , o se gradle copiasrcDirs
solo file, o se l'intero ecosistema funziona solo su directory flat, o cosa.AAssetManager
Sono sbalordito che non ci sia una documentazione chiara che mostri il caso d'uso di "includere una directory di risorse con la tua app NDK", poiché sembra una cosa davvero normale da fare.
modifica: mi è stato chiesto un chiarimento riguardo a: "come viene eseguito cmake". Ho come parte del mio build.gradle
file, il seguente frammento:
externalNativeBuild {
cmake {
version "3.18.1"
path "../CMakeLists.txt"
buildStagingDirectory buildDir
}
}
Risposte
Ok, quindi il mio problema era triplice:
- gradle è incaricato di costruire il mio progetto cmake che costruisce la cartella delle risorse. poiché non esiste una dipendenza esplicita data tra il processo cmake e l'imballaggio delle risorse, sembrava che fosse stato estratto da quella cartella in un momento imprevedibile (potenzialmente prima che la sua costruzione fosse terminata). (Se qualcuno sa come specificare tale dipendenza, per favore fatemelo sapere!)
- quando imposto la cartella in modo che sia
resources
, non risultaroot/resources/{images,shaders}
; risulta inroot/{images,shaders}
. (Se qualcuno sa come specificare di fare invece il primo, per favore fatemelo sapere!) AAssetDir_getNextFileName
non enumera le cartelle. (Non posso farci niente!)
Suggerirei di usare semplicemente al
AAssetManager_open(aassman, "/images/blah0.png")
posto difopen("resources/images/blah0.png", "r")
, ma se è così importante per te, puoi impostareassets.srcDirs 'build/cmake/release/arm64-v8a
ed escludere tutto tranne"resources"
.Ecco una descrizione di una soluzione in C ++ puro. In alternativa, puoi anche chiamare l'API Java (come qui ) tramite JNI.