Android NDK - 在本地代码中使用AssetManager

6

我需要在C/C++代码中使用我的资产文件夹中的资产。像这样缓存AAssetManager指针是否安全:

AAssetManager* assetMgr = NULL; 

void Java_com_example_createAssetManager(JNIEnv* env, jclass clazz, jobject assetManager)
{
  AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);
  assert(NULL != mgr);
  assetMgr = mgr;    
}

我希望你能帮我翻译一下,在it技术方面,如何在需要时使用createAssetManager? createAssetManager在主Activity的Java onCreate方法中被调用(UI线程),但在C / C ++中的使用是在本地处理渲染和游戏时钟时从GLSurfaceView实现的本地方法中调用的。

1)在整个应用程序的生命周期内,assetMgr指针会指向有效对象吗? 在Java端(在Activity类中)也像静态变量一样创建它是否足够,以便垃圾收集器不会将其销毁?

2)我会遇到一些线程问题吗?

谢谢,汤姆·亚当


为了保险起见,不要缓存。AAssetManager_fromJava()非常快。 - Seva Alekseyev
谢谢你的回复。我之所以想要缓存它,是因为我不知道如何在方法调用中获取指针而不需要“jobject assetManager”。所以,我必须在每次从Java到C/C++的tick调用中添加这个参数,以防我在tick期间需要它吗?还是有一种方法可以查询Java以在需要时获得对象(请求AssetManager,然后调用AAssetManager_fromJava,然后使用它...)? - Tom Atom
2个回答

3
保持资产管理器的缓存稍微更安全的一种方法是在C端保存对底层Java对象的全局引用以及缓存的AAssetManager指针。至少这样你可以知道C对象背后/周围的Java对象不会被垃圾收集。

要做到这一点,请调用env->NewGlobalRef(assetManager)

跨线程访问资产管理器会相当疯狂,我认为这是一个非常强的设计限制 - 除非明确记录,否则不能默认假设线程安全性。


2
值得一提的是,AAssetManager的文档明确指出本地AAssetManager句柄可以在多个线程之间共享。查看源代码,可以看到有一个互斥锁和一条注释说明它是线程安全的。 - Neil Roberts

2

我写了一个NDK模块,Assetbridge,你可能也会觉得有用。它将项目assets文件夹中的内容(文件和目录)导出到临时目录,然后设置一个环境变量到该路径,这样你的本地代码就可以chdir()到临时目录并使用普通的标准库文件IO例程。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接