Using Qt / C ++ to invoke Java code through JNI. FindClass does not find class

I am new to JNI and this is my first program trying to call Java code from C ++. I am using Qt 5.2 and I am writing an Android application.

I cannot find my java class and load it into my C ++ program. I read a lot of posts here about stack overflows and other places, and this seems to be a common problem, but I have not been able to solve my problem yet.

I'm also not sure if the Java virtual machine is installed correctly, since the Qt documentation in QAndroidJniEnvironment is minimal.

I am looking for a solution on how to find my java class. I also evaluate general feedback on other sections of the code (I assume there may be more errors).

Msg error:

Starting remote process.D/dalvikvm(24911): GC_CONCURRENT freed 384K, 5% free 9180K/9596K, paused 1ms+2ms, total 15ms D/dalvikvm(24911): Trying to load lib /data/data/org.qtproject.example.AndroidTest/lib/libgnustl_shared.so 0x428b2360 D/dalvikvm(24911): Added shared lib /data/data/org.qtproject.example.AndroidTest/lib/libgnustl_shared.so 0x428b2360 D/dalvikvm(24911): No JNI_OnLoad found in /data/data/org.qtproject.example.AndroidTest/lib/libgnustl_shared.so 0x428b2360, skipping init D/dalvikvm(24911): Trying to load lib /data/data/org.qtproject.example.AndroidTest/lib/libQt5Core.so 0x428b2360 D/dalvikvm(24911): Added shared lib /data/data/org.qtproject.example.AndroidTest/lib/libQt5Core.so 0x428b2360 D/dalvikvm(24911): Trying to load lib /data/data/org.qtproject.example.AndroidTest/lib/libQt5Network.so 0x428b2360 D/dalvikvm(24911): Added shared lib /data/data/org.qtproject.example.AndroidTest/lib/libQt5Network.so 0x428b2360 I/Qt (24911): Network start D/dalvikvm(24911): Trying to load lib /data/data/org.qtproject.example.AndroidTest/lib/libQt5Qml.so 0x428b2360 D/dalvikvm(24911): Added shared lib /data/data/org.qtproject.example.AndroidTest/lib/libQt5Qml.so 0x428b2360 D/dalvikvm(24911): No JNI_OnLoad found in /data/data/org.qtproject.example.AndroidTest/lib/libQt5Qml.so 0x428b2360, skipping init D/dalvikvm(24911): Trying to load lib /data/data/org.qtproject.example.AndroidTest/lib/libQt5Gui.so 0x428b2360 D/dalvikvm(24911): Added shared lib /data/data/org.qtproject.example.AndroidTest/lib/libQt5Gui.so 0x428b2360 D/dalvikvm(24911): No JNI_OnLoad found in /data/data/org.qtproject.example.AndroidTest/lib/libQt5Gui.so 0x428b2360, skipping init D/dalvikvm(24911): Trying to load lib /data/data/org.qtproject.example.AndroidTest/lib/libQt5Quick.so 0x428b2360 D/dalvikvm(24911): Added shared lib /data/data/org.qtproject.example.AndroidTest/lib/libQt5Quick.so 0x428b2360 D/dalvikvm(24911): No JNI_OnLoad found in /data/data/org.qtproject.example.AndroidTest/lib/libQt5Quick.so 0x428b2360, skipping init D/dalvikvm(24911): Trying to load lib /data/data/org.qtproject.example.AndroidTest/lib/libQt5QuickParticles.so 0x428b2360 D/dalvikvm(24911): Added shared lib /data/data/org.qtproject.example.AndroidTest/lib/libQt5QuickParticles.so 0x428b2360 D/dalvikvm(24911): No JNI_OnLoad found in /data/data/org.qtproject.example.AndroidTest/lib/libQt5QuickParticles.so 0x428b2360, skipping init D/dalvikvm(24911): Trying to load lib /data/data/org.qtproject.example.AndroidTest/lib/libQt5AndroidExtras.so 0x428b2360 D/dalvikvm(24911): Added shared lib /data/data/org.qtproject.example.AndroidTest/lib/libQt5AndroidExtras.so 0x428b2360 D/dalvikvm(24911): No JNI_OnLoad found in /data/data/org.qtproject.example.AndroidTest/lib/libQt5AndroidExtras.so 0x428b2360, skipping init D/dalvikvm(24911): Trying to load lib /data/data/org.qtproject.example.AndroidTest/plugins/platforms/android/libqtforandroidGL.so 0x428b2360 D/dalvikvm(24911): Added shared lib /data/data/org.qtproject.example.AndroidTest/plugins/platforms/android/libqtforandroidGL.so 0x428b2360 I/Qt (24911): qt start W/dalvikvm(24911): dvmFindClassByName rejecting 'org/qtproject/qt5/android/QtMessageDialogHelper' D/dalvikvm(24911): Trying to load lib /data/data/org.qtproject.example.AndroidTest/lib/libQt5QuickParticles.so 0x428b2360 D/dalvikvm(24911): Shared lib '/data/data/org.qtproject.example.AndroidTest/lib/libQt5QuickParticles.so' already loaded in same CL 0x428b2360 D/dalvikvm(24911): Trying to load lib /data/app-lib/org.qtproject.example.AndroidTest-1/libAndroidTest.so 0x428b2360 D/Qt (24911): qml\qqmlengine.cpp:1451 (QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool)): QML debugging is enabled. Only use this in a safe environment. D/dalvikvm(24911): Added shared lib /data/app-lib/org.qtproject.example.AndroidTest-1/libAndroidTest.so 0x428b2360 D/dalvikvm(24911): No JNI_OnLoad found in /data/app-lib/org.qtproject.example.AndroidTest-1/libAndroidTest.so 0x428b2360, skipping init W/Qt (24911): kernel\qcoreapplication.cpp:416 (QCoreApplicationPrivate::QCoreApplicationPrivate(int&, char**, uint)): WARNING: QApplication was not created in the main() thread. W/dalvikvm(24911): dvmFindClassByName rejecting 'org/qtproject/qt5/android/QtNativeInputConnection' W/dalvikvm(24911): dvmFindClassByName rejecting 'org/qtproject/qt5/android/QtExtractedText' I/Adreno-EGL(24911): <qeglDrvAPI_eglInitialize:320>: EGL 1.4 QUALCOMM Build: I0404c4692afb8623f95c43aeb6d5e13ed4b30ddbDate: 11/06/13 D/Qt (24911): fontdatabases\basic\qbasicfontdatabase.cpp:246 (static QStringList QBasicFontDatabase::addTTFile(const QByteArray&, const QByteArray&)): FT_New_Face failed with index 0 : 90 D/Qt (24911): ..\AndroidTest\jnimathcppwrapper.cpp:18 (jniMathCppWrapper::jniMathCppWrapper()): JniMath class not found D/Qt (24911): ..\AndroidTest\jnimathcppwrapper.cpp:43 (int jniMathCppWrapper::eleven()): Enter eleven F/libc (24911): Fatal signal 11 (SIGSEGV) at 0x0000002c (code=1), thread 24933 (ple.AndroidTest) 

Java class:

 package org.app.test; public class JniMath { public JniMath() { } public int eleven() { return 11; } } 

.pro file:

 # Add more folders to ship with the application, here folder_01.source = qml/AndroidTest folder_01.target = qml DEPLOYMENTFOLDERS = folder_01 # Additional import path used to resolve QML modules in Creator code model QML_IMPORT_PATH = # The .cpp file which was generated for your project. Feel free to hack it. SOURCES += main.cpp #\ # jnimathcppwrapper.cpp # Installation path # target.path = # Please do not modify the following two lines. Required for deployment. include(qtquick2applicationviewer/qtquick2applicationviewer.pri) qtcAddDeployment() RESOURCES += \ resources.qrc QT += androidextras OTHER_FILES += \ android/src/org/app/test/JniMath.java HEADERS += #\ # jnimathcppwrapper.h android { SOURCES += jnimathcppwrapper.cpp HEADERS += jnimathcppwrapper.h } 

main.cpp:

 #include <QtGui/QGuiApplication> #include "qtquick2applicationviewer.h" #include "jnimathcppwrapper.h" #include <QDebug> #include <QString> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QtQuick2ApplicationViewer viewer; viewer.setMainQmlFile(QStringLiteral("qml/AndroidTest/main.qml")); viewer.showExpanded(); jniMathCppWrapper *test = new jniMathCppWrapper(); qDebug() << QString::number(test->eleven()); return app.exec(); } 

jnimathcppwrapper.h:

 #ifndef JNIMATHCPPWRAPPER_H #define JNIMATHCPPWRAPPER_H #include <QtAndroidExtras> class jniMathCppWrapper { public: jniMathCppWrapper(); int eleven(); private: jobject jniMathObject; }; #endif // JNIMATHCPPWRAPPER_H 

jnimathcppwrapper.cpp:

 #include "jnimathcppwrapper.h" #include <QtAndroidExtras> #include <QDebug> #include <jni.h> static jclass jniMathClassID = 0; static jmethodID jniMathConstructorMethodID = 0; static jmethodID jniMathElevenMethodID = 0; jniMathCppWrapper::jniMathCppWrapper() { QAndroidJniEnvironment qjniEnv; //Get JniMath class ID. jniMathClassID = qjniEnv->FindClass("android/src/org/app/test/JniMath"); if(jniMathClassID == NULL) { qDebug() << "JniMath class not found"; return; } //Get constructor method ID jniMathConstructorMethodID = qjniEnv->GetMethodID(jniMathClassID, "<init>", "void(V)"); if(jniMathConstructorMethodID == NULL) { qDebug() << "JniMath constructor not found"; return; } //Create new Java object and calling the selected constructor. jniMathObject = qjniEnv->NewObject(jniMathClassID, jniMathConstructorMethodID); if(jniMathObject == NULL) { qDebug() << "JniMath Java object could not be constructed"; return; } } int jniMathCppWrapper::eleven() { QAndroidJniEnvironment qjniEnv; qDebug() << "Enter eleven"; //Get eleven method ID jniMathElevenMethodID = qjniEnv->GetMethodID(jniMathClassID, "eleven", "void(V)"); if(jniMathElevenMethodID == NULL) { qDebug() << "JniMath class, eleven method not found"; return 9; } jint res = qjniEnv->CallIntMethod(jniMathObject, jniMathElevenMethodID); return (int) res; } 

Project Structure:

enter image description here

EDIT:

I also tried a different approach that led to the same error:

 QAndroidJniObject *myJavaClass = new QAndroidJniObject("android/src/org/app/test/JniMath"); if(myJavaClass->isValid()) { qDebug() << "Class found!"; } else { qDebug() << "Class NOT found!"; } 

When trying to load java / lang / String, both methods above will find the class.

EDIT:

Error Log:

 D/Qt ( 3385): qml\qqmlengine.cpp:1451 (QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool)): QML debugging is enabled. Only use this in a safe environment. D/dalvikvm( 3385): Added shared lib /data/app-lib/org.qtproject.example.AndroidTest-1/libAndroidTest.so 0x428b67f8 D/Qt ( 3385): ..\AndroidTest\jnimathcppwrapper.cpp:68 (jint JNI_OnLoad(JavaVM*, void*)): Class NOT found D/AndroidRuntime( 3385): Shutting down VM W/dalvikvm( 3385): threadid=1: thread exiting with uncaught exception (group=0x41fecba8) E/AndroidRuntime( 3385): FATAL EXCEPTION: main E/AndroidRuntime( 3385): Process: org.qtproject.example.AndroidTest, PID: 3385 E/AndroidRuntime( 3385): java.lang.NoClassDefFoundError: org/app/test/JniMath E/AndroidRuntime( 3385): at java.lang.Runtime.nativeLoad(Native Method) E/AndroidRuntime( 3385): at java.lang.Runtime.doLoad(Runtime.java:421) E/AndroidRuntime( 3385): at java.lang.Runtime.loadLibrary(Runtime.java:362) E/AndroidRuntime( 3385): at java.lang.System.loadLibrary(System.java:526) E/AndroidRuntime( 3385): at org.qtproject.qt5.android.bindings.QtActivity.loadApplication(QtActivity.java:235) E/AndroidRuntime( 3385): at org.qtproject.qt5.android.bindings.QtActivity.startApp(QtActivity.java:522) E/AndroidRuntime( 3385): at org.qtproject.qt5.android.bindings.QtActivity.onCreate(QtActivity.java:744) E/AndroidRuntime( 3385): at android.app.Activity.performCreate(Activity.java:5231) W/dalvikvm( 3385): threadid=1: thread exiting with uncaught exception (group=0x41fecba8) E/AndroidRuntime( 3385): FATAL EXCEPTION: main E/AndroidRuntime( 3385): Process: org.qtproject.example.AndroidTest, PID: 3385 E/AndroidRuntime( 3385): java.lang.NoClassDefFoundError: org/app/test/JniMath E/AndroidRuntime( 3385): at java.lang.Runtime.nativeLoad(Native Method) E/AndroidRuntime( 3385): at java.lang.Runtime.doLoad(Runtime.java:421) E/AndroidRuntime( 3385): at java.lang.Runtime.loadLibrary(Runtime.java:362) E/AndroidRuntime( 3385): at java.lang.System.loadLibrary(System.java:526) E/AndroidRuntime( 3385): at org.qtproject.qt5.android.bindings.QtActivity.loadApplication(QtActivity.java:235) E/AndroidRuntime( 3385): at org.qtproject.qt5.android.bindings.QtActivity.startApp(QtActivity.java:522) E/AndroidRuntime( 3385): at org.qtproject.qt5.android.bindings.QtActivity.onCreate(QtActivity.java:744) E/AndroidRuntime( 3385): at android.app.Activity.performCreate(Activity.java:5231) E/AndroidRuntime( 3385): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) E/AndroidRuntime( 3385): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159) E/AndroidRuntime( 3385): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245) E/AndroidRuntime( 3385): at android.app.ActivityThread.access$800(ActivityThread.java:135) E/AndroidRuntime( 3385): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196) E/AndroidRuntime( 3385): at android.os.Handler.dispatchMessage(Handler.java:102) E/AndroidRuntime( 3385): at android.os.Looper.loop(Looper.java:136) E/AndroidRuntime( 3385): at android.app.ActivityThread.main(ActivityThread.java:5017) E/AndroidRuntime( 3385): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime( 3385): at java.lang.reflect.Method.invoke(Method.java:515) E/AndroidRuntime( 3385): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779) E/AndroidRuntime( 3385): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595) E/AndroidRuntime( 3385): at dalvik.system.NativeStart.main(Native Method) E/AndroidRuntime( 3385): Caused by: java.lang.ClassNotFoundException: Didn't find class "org.app.test.JniMath" on path: DexPathList[[zip file "/data/app/org.qtproject.example.AndroidTest-1.apk"],nativeLibraryDirectories=[/data/app-lib/org.qtproject.example.AndroidTest-1, /vendor/lib, /system/lib]] E/AndroidRuntime( 3385): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) E/AndroidRuntime( 3385): at java.lang.ClassLoader.loadClass(ClassLoader.java:497) E/AndroidRuntime( 3385): at java.lang.ClassLoader.loadClass(ClassLoader.java:457) E/AndroidRuntime( 3385): ... 21 more 

Comment: why this question is not a duplicate (by Alex Cohn)

There is no doubt that the root problem here is the same as in FindClass from any thread in Android JNI , but the question asked here is a completely different question - IMO. The author did not look for a general way to access ClassLoader from their own threads. He (or she) was looking for a simple and efficient way to access Java callbacks from native Qt-based code. Therefore, all the discussions about how the class loader works in Android and how this can be fixed does not matter to him. If the author thinks otherwise, I would be happy to agree to close this question as a duplicate

Update: this question is not even related to JNI threads

Please review the previous void comment. This question has nothing to do with multithreading. It's all about how to set up a Qt application for Android so that it can use custom Java classes similar to the sample .

+8
java c ++ android qt jni
source share
4 answers

I used this example http://www.gnuton.org/blog/2014/01/invoking-qtc-code-from-the-java-side-of-qt-for-android-application/

Here is how I did it. In my main java class, I added a static method to invoke the same action (because it must be static):

 static public void startFacebookActivity() { String msgTag = "FACEBOOK_APP"; try { Log.v(msgTag, "starting activity"); Activity mother = QtNative.activity(); Log.v(msgTag, mother.toString()); Log.v(msgTag, MainActivity.class.getName()); Intent intent = new Intent(mother, MainActivity.class); mother.startActivity(intent); } catch (Exception e) { Log.e(msgTag, e.toString()); e.printStackTrace(); } } 

Then in my header file, I added the following:

  class FacebookAndroid : public QObject { Q_OBJECT public: FacebookAndroid(QObject *parent = 0); public slots: void startAndroidFacebook(); }; 

and in my cpp file, I just called my Java method as follows:

 void FacebookAndroid::startAndroidFacebook() { QAndroidJniObject::callStaticMethod<void>("org.qtproject.example.MainActivity", "startFacebookActivity", "()V"); 
+1
source share

Is your java source directory copied to the android build directory? The Android folder in the source folder must be specified in the qmake ANDROID_PACKAGE_SOURCE_DIR variable: http://qt-project.org/doc/qt-5/deployment-android.html#qmake-variables

0
source share

The easiest way to get FindClass to work is to call it from the JNI_OnLoad function. This function will be automatically called by JNI at boot time in the correct thread. In the old version of the notificationclient example, this method was used before commit # 6500083. This is a summary of the corresponding part of the androidjnibindings.cpp file:

 #include <QtAndroidExtras/QJNIObject> jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { JNIEnv *env; if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_4) != JNI_OK) { qFatal("Couldn't initialize environment!"); return -1; } jclass clazz = env->FindClass("org/qtproject/example/notification/NotificationClient"); if (clazz == 0) { // } return JNI_VERSION_1_4; } 

This is not in the 5.2 code example, since it is no longer necessary to call Java from C ++ code, but I do not know the QT5.2 example showing a C call from Java.

0
source share

jniMathClassID = qjniEnv-> FindClass ("android / src / org / app / test / JniMath");

Instead of "android / src / org / app / test / JniMath" try specifying the package_name: "org / app / test / JniMath" and put it in

 jint JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv* env; if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { qCritical()<<"Can't get the enviroument"; return -1; } s_javaVM = vm; // cache the JavaVM pointer jclass clazz= env->FindClass("org/app/test/JniMath"); jniMathClassID = (jclass)env->NewGlobalRef(tmp); } 

Something like that...

0
source share

All Articles