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

Qt on Android, QAndroidJniObject::callStaticMethod problem



  • Hi all,
    I'm doing some tests on android using Qt.

    The first test is a simple Qt App for Android where I have the following code:

    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
            jint a = 2;
            jint b = 4;
            jint max = QAndroidJniObject::callStaticMethod<jint>("java/lang/Math", "max", "(II)I", a, b);
            qDebug() << "********** max " << max;
    ...
    ...
    

    and I get the right output.

    Now I'm trying to use a simple custom Qt library "testjni.so" from an Android Studio project.
    The library is created with QtCreator and has the following code:

    static void test1(JNIEnv *env, jobject obj, jint n)
    {
        qDebug() << "****************** test1 " << n;
    }
    static int square(JNIEnv */*env*/, jobject /*obj*/, jint n)
    {
        qDebug() << "****************** square " << n;
        return Testjni::square(n);
    }
    static JNINativeMethod methods[] = {
        { "test1", 
            "(I)V", 
            (void *)test1 },
        { "square",
            "(I)I", 
            (void *)square }
    };
    JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/)
    {
        qDebug() << "****************** JNI_OnLoad *************************";
    jint a = 2;
            jint b = 4;
            jint max = QAndroidJniObject::callStaticMethod<jint>("java/lang/Math", "max", "(II)I", a, b);
            qDebug() << "********** max " << max;
    
        JNIEnv* env;
        if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6)
               != JNI_OK) {
            return JNI_ERR;
        }
        jclass javaClass = env->FindClass("com/my/package/testjniandroid/MyJavaNatives");
        if (!javaClass) {
            return JNI_ERR;
        }
        if (env->RegisterNatives(javaClass, methods,
                                sizeof(methods) / sizeof(methods[0])) < 0) {
            return JNI_ERR;
        }
        return JNI_VERSION_1_6;
    }
    
    Testjni::Testjni()
    {
    
    }
    
    int Testjni::square(int val)
    {
        qDebug() << "****************** Testjni::square " << val;
        return val*val;
    }
    
    

    and the Android part is:

    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            System.loadLibrary("testjni");
        }
    

    Now when I start the Android application it load the native library and call JNI_OnLoad but when it execute QAndroidJniObject::callStaticMethod it crash without useful messages.

    Where do I wrong?

    Thanks

    Luca


  • Qt Champions 2016

    I am not an expert in JNI. But I have written an Android unit test program to execute Qt code. Java code send message to C++ code via JNI and vice versa. It is working fine.

    My code:
    quickandroid/ExampleActivityTest.java at DEV · benlau/quickandroid

    However, I use ActivityInstrumentationTestCase2 which depend on an existing .apk. C++ code is launched by QtActivity.java instead of calling System.loadLibrary manually. May be the QtActivity has setup something for getting JNI to load Java class correctly?



  • @benlau
    Thanks,
    it probably depend on QtActivity that set something as you said but can't find the solution...