在这个代码库的PC版本中,我只拥有以下目录结构:
- 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应用程序的资源目录";,因为这似乎是一件非常正常的事情需要做
编辑:我被要求澄清:";如何运行cmake";。作为build.gradle
文件的一部分,我有以下片段:
externalNativeBuild {
cmake {
version "3.18.1"
path "../CMakeLists.txt"
buildStagingDirectory buildDir
}
}
好的,所以我的问题有三个:
- gradle负责构建我的cmake项目,该项目构建资源文件夹。由于cmake过程和资产打包之间没有明确的依赖关系,它似乎是在一个不可预测的时间(可能在构建完成之前(从该文件夹中提取的。(如果有人知道如何指定这样的依赖项,请告诉我!(
- 当我将文件夹设置为
resources
时,不会导致root/resources/{images,shaders}
;得到CCD_ 15。(如果有人知道如何指定使用前者,请告诉我!( AAssetDir_getNextFileName
不枚举文件夹。(对此我无能为力!(
-
我建议简单地使用
AAssetManager_open(aassman, "/images/blah0.png")
而不是fopen("resources/images/blah0.png", "r")
,但如果它对您非常重要,您可以设置assets.srcDirs 'build/cmake/release/arm64-v8a
并排除除"resources"
之外的所有内容。 -
以下是一个纯C++解决方案的概要。或者,您也可以通过JNI调用Java API(如这里所示(。
目前,转移资源的入口可以正常化。目前,我只能想到AAssetManager。所以这个问题的本质是:如果在cmake中,将资源复制到"assets.srcDirs"中?
但不幸的是,在当前的NDK cmake中没有相对稳定的输出路径。因此,我们无法直接为"assets.srcDirs"设置稳定的路径。
但我在CMAKE中找到了"CMAKE_ANDROID_ASSETS_DIRECTORIES"。根据标准,此宏定义将指向"assets.srcDirs"。
要做到这一点,我们只需要在cmake中编写一个复制脚本(如下所示(,并在每次编译后将资源复制到"cmake_ANDROID_ASSETS_DIRECTORIES"目录中。
此外,cmake的执行阶段将早于android工作室中的"AssetPack"。因此,cmake复制的资源最终会正确进入android apk。
当然,前线是一个理想的情况"CMAKE_ANDROID_ASSETS_DIRECTORIES"未包含在ANDROID studio NDK脚本标准中。为此,我们需要手动将"CMAKE_ANDROID_ASSETS_DIRECTORIES"定义添加到build.gradle文件和CMAKE编译参数中。特定的脚本可以在build.gradle文件中添加以下定义:
android {
defaultConfig {
externalNativeBuild {
cmake {
arguments "-DCMAKE_ANDROID_ASSETS_DIRECTORIES=${android.sourceSets.main.assets.srcDirs[0]}"
}
}
}
}
关于cmake如何复制资源,可以参考以下内容:
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${RES_BASE_PATH}/${FNAME}"
"${CMAKE_ANDROID_ASSETS_DIRECTORIES}/${FNAME}"
COMMENT "Copy ${FNAME}"
)
请将"${target}"更改为"add_target"中显示的名称${RES_BASE_PATH}'是资源的根路径。请将"${FNAME}"设置为您的相对目录路径"${RES_BASE_PATH}"。