Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Get access to AssetManager on C++ side

Discussion in 'Android' started by AlmightyRick, Mar 28, 2016.

  1. AlmightyRick

    AlmightyRick

    Joined:
    Dec 11, 2015
    Posts:
    8
    Hi guys,

    I am trying, without success, to get access to AssetManager on the C++ side.

    Here's the snippet I'm using:

    Code (CSharp):
    1. jint JNI_OnLoad(JavaVM* vm, void* reserved)
    2. {
    3.     vm->GetEnv((void**) &gJavaEnv, JNI_VERSION_1_6);
    4.     jclass cls_Activity = gJavaEnv->FindClass("com/unity3d/player/UnityPlayer");
    5.     jfieldID fid_Activity = gJavaEnv->GetStaticFieldID(cls_Activity, "currentActivity","Landroid/app/Activity;");
    6.     jobject obj_Activity = gJavaEnv->GetStaticObjectField(cls_Activity, fid_Activity);
    7.     AAssetManager*  assetManager = AAssetManager_fromJava(    gJavaEnv, obj_Activity );
    8.     return JNI_VERSION_1_6;
    9. }
    On logcat when I call the AAssetManager_fromJava(...) method it throws me the error
    JNI DETECTED ERROR IN APPLICATION: jfieldID long android.content.res.AssetManager.mObject not valid for an object of class com.unity3d.player.UnityPlayerActivity


    I also took a look at the example on http://docs.unity3d.com/Manual/PluginsForAndroid.html and tried to access the constructor and create a java object from there

    Code (CSharp):
    1. jint JNI_OnLoad(JavaVM* vm, void* reserved)
    2. {
    3.     vm->GetEnv((void**) &gJavaEnv, JNI_VERSION_1_6);
    4.     jclass cls_JavaClass = gJavaEnv->FindClass("com/unity3d/player/UnityPlayer");
    5.     jmethodID mid_JavaClass = gJavaEnv->GetMethodID (cls_JavaClass, "<init>", "()V");
    6.     jobject newObj = gJavaEnv->NewGlobalRef(obj_JavaClass);
    7.     AAssetManager*  assetManager = AAssetManager_fromJava(    gJavaEnv, newObj );
    8.     return JNI_VERSION_1_6;
    9. }
    but this way I can't even access the method id via the gJavaEnv->GetMethodID(...) and throws the following error
    JNI DETECTED ERROR IN APPLICATION: JNI NewObjectV called with pending exception java.lang.NoSuchMethodError: no non-static method "Lcom/unity3d/player/UnityPlayer;.<init>()V"

    I'm kinda lost on how to proceed. Is what I'm doing completely wrong?
    Can someone give me some pointers/help?
     
  2. bitter

    bitter

    Unity Technologies

    Joined:
    Jan 11, 2012
    Posts:
    530
    Yes, you are doing things completely wrong :)

    First of all you can't pass an Activity to AAssetManager_fromJava(), you have to pass a java object reference to the java AssetManager. You can look at the NDK sample native-audio. Secondly the second code sample does make _any_ sense at all, there are so many errors I don't even know where to start :) JNI can be quite difficult to use and there are a lot of pitfalls. If you are going to write JNI code you have to read up on the spec. The most important part is probably the one about references and how to make sure you don't leak memory or use stale references. Another thing that I find a lot of people are doing wrong when writing JNI code is they completely ignore checking for exceptions an error states.

    https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html

    Some hints as to why the second code sample doesn't work:
    You can't create more than one instance of UnityPlayer
    UnityPlayer does not have an empty constructor
    NewGlobalRef does not create a new object, NewObject does
    You can't pass a UnityPlayer object to AAssetManager_fromJava, it has to be an instance of AssetManager
    There is no error handling
    You need to track the global reference to AssetManager and release it properly on teardown.
     
  3. AlmightyRick

    AlmightyRick

    Joined:
    Dec 11, 2015
    Posts:
    8

    Thank you so much for your reply!
    Yes, I must admit I'm quite confused. I'll definitely take a look at that sample and continue on reading the documentation.