Как я могу добавить ресурсы (изображения, звуковые файлы, шейдеры и т. Д.) В проект NDK с помощью Gradle?

Aug 19 2020

В версии этой кодовой базы для ПК у меня просто следующая структура каталогов:

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

Итак, из моего кода на C ++ я могу fopen("resources/images/blah0.png",...), например, просто запросить .

В Android вместо этого требуется

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

К сожалению, fileон появляется nullptr, вероятно, потому, что не может найти это дерево ресурсов.

В моем скрипте build.gradle есть следующий фрагмент:

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

^ Это указывает на тот же каталог ресурсов, указанный в верхней части этого списка.


Что мне нужно сделать, чтобы указанная выше иерархия ресурсов была просто перенесена в мой .apk, чтобы к ней можно было получить доступ через приведенный AAssetManagerвыше фрагмент?


Некоторые дополнительные эксперименты:

Я изменил assets.srcDirsпуть some/random/path/on/my/hdи побежал

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

который просто перечисляет найденные файлы в верхнем каталоге. Я заметил , что он перечислил все файлы , которые были в some/random/path/on/my/hd, но ни один из каталогов . (Когда я указываю его на свою resourcesпапку, он ничего не перечисляет). Я понятия не имею, потому что AAssetDir_getNextFileNameбуквально только получает файлы , или если gradle srcDirsтолько копирует файлы, или вся AAssetManagerэкосистема работает только с плоскими каталогами, или что-то еще.

Я удивлен, что нет четкой документации, показывающей вариант использования «включение каталога ресурсов в ваше приложение NDK», поскольку это кажется действительно нормальным делом.


edit: Меня попросили пояснить, как запускается cmake. В моем build.gradleфайле есть следующий фрагмент:

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

Ответы

1 Phildo Aug 18 2020 at 23:23

Итак, моя проблема была трехкратной:

  1. gradle отвечает за создание моего проекта cmake, который создает папку ресурсов. поскольку нет явной зависимости между процессом cmake и упаковкой ресурсов, казалось, что он извлекался из этой папки в непредсказуемое время (возможно, до того, как его построение было завершено). (Если кто-то знает, как указать такую ​​зависимость, дайте мне знать!)
  2. когда я устанавливаю папку resources, это не приводит к root/resources/{images,shaders}; это приводит к root/{images,shaders}. (Если кто-то знает, как указать первое, пожалуйста, дайте мне знать!)
  3. AAssetDir_getNextFileName не перечисляет папки. (Я ничего не могу с этим поделать!)
1 AlexCohn Aug 24 2020 at 15:54
  1. Я бы предложил просто использовать AAssetManager_open(aassman, "/images/blah0.png")вместо fopen("resources/images/blah0.png", "r"), но если это так важно для вас, вы можете установить assets.srcDirs 'build/cmake/release/arm64-v8aи исключить все, кроме "resources".

  2. Вот схема решения на чистом C ++. Кроме того, вы также можете вызвать Java API (как здесь ) через JNI.