Cannot get JNI to find my custom Java class from my Qt Android app



  • Hello

    I am trying to use JNI from my Android Qt C++ app so that I can access the Android Bluetooth functionality via a simple Java class that I wrote.

    While I am able to successfully use FindClass() to get the standard Android and Java classes (e.g. android/bluetooth/BluetoothDevice, java/lang/String, etc...), I cannot seem to get it to find my Java class.

    Does anybody out there have any idea what I’m doing wrong?

    Any help would be greatly appreciated
    Thank you
    Scott

    Here is some simple test code that demonstrates my problem:

    I place my Java test class in the same source folder and package (i.e. <proj>/android/src/org/qtproject/qt5/android/bindings ) as QtApplication.java and QtActivity.java. It appears to be properly compiled, dex’ed, and placed in the package before being sent up to the device to be executed.

    @//****************** Here is my Java class that I want to talk to from my Qt app: *********************
    package org.qtproject.qt5.android.bindings;

    public class JniTest
    {
    public int GetNum( )
    {
    return 5;
    }
    }
    //*****************************************************************************************************

    //***************** Here is my C++ code that attempts to find my Java class **********************
    #include <jni.h>
    #include <android/log.h>
    #include <QtGlobal>

    #define dbprintf(...) __android_log_print(ANDROID_LOG_VERBOSE, "JniTest", VA_ARGS)

    JavaVM *vm = NULL;
    JNIEnv *env = NULL;

    //*******************************
    jint JNI_OnLoad(JavaVM *vmIn, void *reserved)
    {
    dbprintf( "JNI_OnLoad: enter" );
    vm = vmIn;
    return JNI_VERSION_1_6;
    }

    //*******************************
    void JniTest( )
    {
    qDebug( "JniTest enter: jvm=x", (int)vm );
    if( !vm )
    return;

    JavaVMAttachArgs args = { JNI_VERSION_1_6, NULL, NULL };
    vm->AttachCurrentThread( &env, &args );
    
    qDebug( "JniTest enter: env=x", (int)env );
    if( !env )
        return;
    
    // Getting a standard Java class succeeds
    CreateClass( "java/lang/String" );
    
    // Getting my Java class fails
    CreateClass( "org/qtproject/qt5/android/bindings/JniTest" );
    
    // Getting known Qt java classes also fail
    CreateClass( "org/qtproject/qt5/android/QtNative" );
    CreateClass( "org/qtproject/qt5/android/bindings/QtActivity" );
    

    }

    //*******************************
    jclass CreateClass( const char *name )
    {
    jclass cls = env->FindClass( name );
    jclass gcls = NULL; //cls ? (jclass)env->NewGlobalRef( cls ) : NULL;
    qDebug( "JniTest CreateClass: name=%s, cls=x gcls=x", name, (int)cls, (int)gcls );
    return gcls;
    }

    //*****************************************************************************************************
    @
    //*********************** Here is the resulting output from my test code ******************************
    I/Qt ( 5276): qt start
    D/dalvikvm( 5276): Trying to load lib /data/app-lib/com.pasco.QtAndroidJniTest-1/libQtAndroidJniTest.so 0x42094680
    D/dalvikvm( 5276): Added shared lib /data/app-lib/com.pasco.QtAndroidJniTest-1/libQtAndroidJniTest.so 0x42094680
    V/JniTest ( 5276): JNI_OnLoad: enter
    W/Qt ( 5276): ..\src\androidjnimain.cpp:449 (jboolean startQtApplication(JNIEnv*, jobject, jstring, jstring)): Can't set environment ""
    W/Qt ( 5276): kernel\qcoreapplication.cpp:412 (QCoreApplicationPrivate::QCoreApplicationPrivate(int&, char**, uint)): WARNING: QApplication was not created in the main() thread.
    W/dalvikvm( 5276): dvmFindClassByName rejecting 'org/qtproject/qt5/android/QtNativeInputConnection'
    W/dalvikvm( 5276): dvmFindClassByName rejecting 'org/qtproject/qt5/android/QtExtractedText'
    D/Qt ( 5276): ..\QtAndroidJniTest\mainwindow.cpp:60 (void JniTest()): JniTest enter: jvm=41aa40c0
    D/Qt ( 5276): ..\QtAndroidJniTest\mainwindow.cpp:67 (void JniTest()): JniTest enter: env=5bbba0e0
    D/Qt ( 5276): ..\QtAndroidJniTest\mainwindow.cpp:53 (_jclass* CreateClass(const char*)): JniTest CreateClass: name=java/lang/String, cls=1d200001 gcls=00000000
    D/Qt ( 5276): ..\QtAndroidJniTest\mainwindow.cpp:53 (_jclass* CreateClass(const char*)): JniTest CreateClass: name=org/qtproject/qt5/android/bindings/JniTest, cls=00000000 gcls=00000000
    D/Qt ( 5276): ..\QtAndroidJniTest\mainwindow.cpp:53 (_jclass* CreateClass(const char*)): JniTest CreateClass: name=org/qtproject/qt5/android/QtNative, cls=00000000 gcls=00000000
    D/Qt ( 5276): ..\QtAndroidJniTest\mainwindow.cpp:53 (_jclass* CreateClass(const char*)): JniTest CreateClass: name=org/qtproject/qt5/android/bindings/QtActivity, cls=00000000 gcls=00000000
    //*****************************************************************************************************





  • I found the problem.

    I need to call FindClass from within JNI_OnLoad instead of from the context of my button press handler.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.