6

I need to work with assets in my assets folder from within C/C++ code. Is it safe to cache pointer to AAssetManager like this...:

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;    
}

... and then to use it whenever I need it? The createAssetManager is called from Java onCreate method of main Activity (UI thread) but the usage in C/C++ is when nativly processing rendering and game tick called from native methods in GLSurfaceView implementation.

1) will the assetMgr pointer point to valid object durin whole app lifetime? Is it enough to create it also like static variable on Java side (in Activity class) so garbage collector will not destroy it?

2) is there some danger I will run into some problems with threads?

Thanks, Tom Atom

Tom Atom
  • 139
  • 1
  • 11
  • Err on the safe side and don't cache. `AAssetManager_fromJava()` is very fast. – Seva Alekseyev Jun 19 '12 at 15:08
  • Thank you for reply. The reason why I wanted to cache it was that I do not know how to get the pointer without having "jobject assetManager" in method call. So, do I have to add this parameter into every tick call from Java to C/C++ just for case I will need it during the tick? Or is there some way how I can query Java for the object in time when I need it (ask Java for AssetManager, then call AAssetManager_fromJava, then use it...) – Tom Atom Jun 19 '12 at 15:17

2 Answers2

3

One marginally safer way to cache the asset manager would be to hold a global reference to the underlying Java object on the C side along with the cached AAssetManager pointer. At least with that you'd know that the Java object behind/around the C object won't be garbage collected.

To do that, call env->NewGlobalRef(assetManager).

And accessing the asset manager across thread boundary would be rather crazy, IMHO. That's a very strong design constraint - unless documented explicitly, thread safety can never be assumed by default.

Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • 2
    For what it’s worth, the documentation for [AAssetManager](https://developer.android.com/ndk/reference/group/asset#aassetmanager) explicitly states that a native AAssetManager handle can be shared between multiple threads. Looking at the [source code](https://android.googlesource.com/platform/frameworks/base/+/master/libs/androidfw/include/androidfw/AssetManager.h#18) there is a mutex and a comment saying it is thread safe. – Neil Roberts Oct 23 '21 at 10:15
2

I've written an NDK module, Assetbridge, that you might also find useful. It exports the contents of your project's assets/ folder (files and directories) to a temporary directory, and then sets an environment variable to that path, so your native code can chdir() to the temp directory and you can use the regular old standard library file IO routines.

Steve H.
  • 21
  • 2