Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Android register Java native methods



  • Hello,

    I am trying to figure out how to call c++ methods from java side. Studying QAndroidJniObject documentation
    https://doc.qt.io/qt-5/qandroidjniobject.html#details

    I can see that there is some kind of example provided.
    What is not clear to me is where should void registerNativeMethods() be called?

    void registerNativeMethods() {
        JNINativeMethod methods[] {{"callNativeOne", "(I)V", reinterpret_cast<void *>(fromJavaOne)},
                                   {"callNativeTwo", "(I)V", reinterpret_cast<void *>(fromJavaTwo)}};
    
        QAndroidJniObject javaClass("my/java/project/FooJavaClass");
        QAndroidJniEnvironment env;
        jclass objectClass = env->GetObjectClass(javaClass.object<jobject>());
        env->RegisterNatives(objectClass,
                             methods,
                             sizeof(methods) / sizeof(methods[0]));
        env->DeleteLocalRef(objectClass);
    }
    

  • Moderators

    @Eligijus said in Android register Java native methods:

    What is not clear to me is where should void registerNativeMethods() be called?

    as early as possible.
    If you have to, you can let your java code know that the methods have been registered by calling a Java method at the end of registerNativeMethods() method. Before that point no calls to native methods are allowed.
    But note that Qt runs in a different thread than the Android UI thread, and so are the calls executed in this thread.



  • @raven-worx

    But note that Qt runs in a different thread than the Android UI thread, and so are the calls executed in this thread.

    I guess that is exactly my problem because I get this error:

    F project.exampl: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: JNI GetObjectClass called with pending exception java.lang.RuntimeException: Can't create handler inside thread Thread[qtMainLoopThread,5,main] that has not called Looper.prepare()
    

    And I tried to run registerNativeMethods() before creating QGuiApplication after creating it and in qml Component.onCompleted signal handler. Not sure what to do about this.



  • I have found a solution:
    If my java class is
    public class Bar
    then calling registerNativeMethods() somewhere in main works as expected.
    But if my java class extends from QtActivity public class Bar extends org.qtproject.qt5.android.bindings.QtActivity then I have to register it in JNI_OnLoad.
    Example from https://www.kdab.com/qt-android-episode-5/ :

    // define our native method
    static void fibonaciResult(JNIEnv */*env*/, jobject /*obj*/, jint n)
    {
        qDebug() << "Computed fibonacci is:" << n;
    }
     
    // step 2
    // create a vector with all our JNINativeMethod(s)
    static JNINativeMethod methods[] = {
        { "sendFibonaciResult", // const char* function name;
            "(I)V", // const char* function signature
            (void *)fibonaciResult // function pointer
        }
    };
     
    // step 1
    // this method is called automatically by Java VM
    // after the .so file is loaded
    JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/)
    {
        JNIEnv* env;
        // get the JNIEnv pointer.
        if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6)
               != JNI_OK) {
            return JNI_ERR;
        }
     
        // step 3
        // search for Java class which declares the native methods
        jclass javaClass = env->FindClass("com/kdab/training/MyJavaNatives");
        if (!javaClass)
            return JNI_ERR;
     
        // step 4
        // register our native methods
        if (env->RegisterNatives(javaClass, methods,
                                sizeof(methods) / sizeof(methods[0])) < 0) {
            return JNI_ERR;
        }
        return JNI_VERSION_1_6;
    }
    

    Not sure why it has to be done this way maybe someone with more knowledge could provide more information?


Log in to reply