Come posso aggiungere risorse (immagini, file audio, shader, ecc ...) a un progetto NDK con Gradle?

Aug 19 2020

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, filesta 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 AAssetManagersnippet sopra?


Qualche ulteriore sperimentazione:

Ho modificato il assets.srcDirspercorso in some/random/path/on/my/hde 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 resourcescartella, non enumera nulla). Non ho idea se è perché AAssetDir_getNextFileNameletteralmente 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.gradlefile, il seguente frammento:

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

Risposte

1 Phildo Aug 18 2020 at 23:23

Ok, quindi il mio problema era triplice:

  1. 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!)
  2. quando imposto la cartella in modo che sia resources, non risulta root/resources/{images,shaders}; risulta in root/{images,shaders}. (Se qualcuno sa come specificare di fare invece il primo, per favore fatemelo sapere!)
  3. AAssetDir_getNextFileName non enumera le cartelle. (Non posso farci niente!)
1 AlexCohn Aug 24 2020 at 15:54
  1. Suggerirei di usare semplicemente al AAssetManager_open(aassman, "/images/blah0.png")posto di fopen("resources/images/blah0.png", "r"), ma se è così importante per te, puoi impostare assets.srcDirs 'build/cmake/release/arm64-v8aed escludere tutto tranne "resources".

  2. Ecco una descrizione di una soluzione in C ++ puro. In alternativa, puoi anche chiamare l'API Java (come qui ) tramite JNI.