PDA

View Full Version : Cannot get JNI to find my custom Java class from my Qt Android app



scottwild
1st October 2013, 23:03
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=%08x", (int)vm );
if( !vm )
return;

JavaVMAttachArgs args = { JNI_VERSION_1_6, NULL, NULL };
vm->AttachCurrentThread( &env, &args );

qDebug( "JniTest enter: env=%08x", (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=%08x gcls=%08x", 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
//************************************************** ************************************************** *

wysota
1st October 2013, 23:21
Please ask Java questions on some Java forum and not on a forum devoted to Qt. We're not Java specialists.

scottwild
1st October 2013, 23:32
This *is* a Qt question.

I have successfully been able to do this in a pure non-Qt Android app using the Android NDK.

Because:
* This forum is for Qt running on Embedded and Mobile devices (which I assume includes Android devices)
* The Qt designers needed to sprinkle a little Java into their implementation (due to Android's java-centricity)
* The Qt library source code actually uses the JNI interface

I was assuming that they (or someone else in this forum) might have some insight that I do not have.

wysota
2nd October 2013, 00:55
This *is* a Qt question.
All I can see is a Java class and some JNI code where the only relation to Qt is the use of qDebug().


Because:
* This forum is for Qt running on Embedded and Mobile devices (which I assume includes Android devices)
* The Qt designers needed to sprinkle a little Java into their implementation (due to Android's java-centricity)
* The Qt library source code actually uses the JNI interface

I was assuming that they (or someone else in this forum) might have some insight that I do not have.

I really think you'll get help quicker on some Java site. We're C++ programmers.

scottwild
9th October 2013, 23:09
I found the problem.

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