3

I have an Android app with an activity derived from NativeActivity like this:

public class MyNativeActivity extends android.app.NativeActivity 
{
    public native void TellNativeSide(int info);

    static {
        System.loadLibrary("MyNatAct");  // <--- is this necessary?
    }

    public int OtherMethods(...) ...
}

On the C/C++ side, I have

extern "C" void  
Java_mycom_nativity_MyNativeActivity_TellNativeSide(JNIEnv *env,
    jobjectactivityobj, jint info)
{
    ... do something
} // java native TellNativeSide() method //

extern "C" jint JNI_OnLoad(JavaVM *vm, void *)
{
    LOGI("***JNI_OnLoad called...");
}

The libMyNatAct.so library is loaded automatically by the NativeActivity class and indeed android_main() and everything runs correctly with or without the system.loadLibrary() line. However, JNI_OnLoad() would never be called and the TellNativeSide() method is also not available on the Java side unless the

system.loadLibrary("MyNatAct");

call is there in the static class init block.

So it seems that the native .so has to be loaded twice. Once in the init block to make available all the native methods and get JNI_OnLoad() called, and another time by the NativeActivity class but not through system.loadLibrary()?

Is this the correct behaviour?

Nibikibaba
  • 310
  • 2
  • 10

1 Answers1

2

That's right. You must explicitly call system.loadLibrary() to have the native Java methods bound to exported functions of the .so file

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • 1
    Thanks for the reply. What I do not understand is that since the Android side could load the native shared library even without any Java code at all why doesn't it initialize the native library properly (e.g. call the JNI_OnLoad() and make ready the function table etc.) instead of leaving developers to figure it out the hard way. At least document it properly. – Nibikibaba Apr 05 '15 at 15:54
  • If you look at the source code of [NativeActivity](https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/android/app/NativeActivity.java), you will find that it connects to the custom library (what they call `libraryFile`) at native level (inside `loadNativeCode` method) and not through `loadLibrary()` or her kin. – Alex Cohn Apr 07 '15 at 07:49
  • 1
    Your complaint is justified in my eyes, definitely regarding documentation. I should only remind you that extending `android.app.NativeActivity` is not documented and was not intended in the first place. It's a nice outcome of the Android platform architecture that such technique is possible. – Alex Cohn Apr 07 '15 at 07:55