Utilisation de Qt / C ++ pour appeler le code Java via JNI. FindClass ne trouve pas de classe

Je suis nouveau sur JNI et c'est mon premier programme qui essaie d'appeler le code Java de C ++. J'utilise Qt 5.2 et j'écris une application Android.

Je ne peux pas trouver ma classe java et la charger dans mon programme C ++. J'ai lu beaucoup de messages ici sur le débordement de la pile et d'autres endroits et cela semble être un problème commun, mais je n'ai pas encore réussi à résoudre le problème …

  • NullPointerException depuis UsbManager
  • Article de centrage Android dans RecyclerView
  • La propriété personnalisée de mon objet graphique personnalisé n'est pas affichée dans la boîte de dialogue Partager
  • Android Intent.ACTION_CALL, Uri
  • Appliquez un plugin: 'android' ou appliquez un plugin: 'com.android.application'
  • Comment soutenir textView.setTextIsSelectable dans les versions Android plus faibles?
  • Je ne suis pas certain que la VM Java soit correctement configurée car la documentation Qt sur QAndroidJniEnvironment est minimale.

    Je cherche une solution pour trouver ma classe java. J'apprécie également les commentaires généraux sur d'autres sections du code (je suppose qu'il pourrait y avoir plus d'erreurs).

    Message d'erreur:

    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) 

    Classe Java:

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

    .profil:

     # 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's 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; } 

    Structure du projet:

    Entrez la description de l'image ici

    MODIFIER:

    J'ai également essayé une approche différente menant à la même erreur:

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

    En essayant de charger java / lang / String à la place, les deux méthodes ci-dessus trouvent la classe.

    MODIFIER:

    Journal d'erreurs:

     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 

    Commentaire: pourquoi cette question n'est pas un double (par Alex Cohn)

    Il ne fait aucun doute que le problème racine ici est le même que dans FindClass à partir de n'importe quel thread dans Android JNI , mais la question posée ici est une question très différente, l'OMI. L' auteur ne cherchait pas une manière générique d'accéder au ClassLoader à partir de threads natifs. Il (ou elle) cherchait un moyen simple et efficace d'accéder à un rappel Java à partir du code natif basé sur Qt. Par conséquent, toute discussion sur la façon dont le chargeur de classe fonctionne dans Android et comment cela peut être corrigé n'est pas pertinente pour lui. Si l'auteur pense autrement, je serai ravi de fermer cette question en double exemplaire

    Mise à jour: cette question n'est même pas liée aux threads JNI

    Veuillez considérer le commentaire précédent comme nul. Cette question n'a rien à voir avec le multithreading. Il s'agit de la façon de configurer une application Android Qt telle qu'elle puisse utiliser des classes Java personnalisées, semblables à celles de l' échantillon .

  • Démarrez le service gps Android
  • Comment puis-je envoyer une notification Firebase Cloud Messaging sans utiliser la console Firebase?
  • Dialogue étroit d'Android après 5 secondes?
  • Les éléments de menu ne s'affichent pas dans la barre d'action
  • Comment modifier la position d'une boîte de dialogue de progression?
  • Serveur Web pour Android
  • 4 Solutions collect form web for “Utilisation de Qt / C ++ pour appeler le code Java via JNI. FindClass ne trouve pas de classe”

    J'ai utilisé cet exemple http://www.gnuton.org/blog/2014/01/invoking-qtc-code-from-the-java-side-of-qt-for-android-application/

    C'est ainsi que je l'ai fait. Dans ma classe principale java, j'ai ajouté une méthode statique pour appeler la même activité (car elle doit être statique):

     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(); } } 

    Ensuite, dans mon fichier d'en-tête, j'ai ajouté ceci:

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

    Et dans mon fichier cpp, je viens d'appeler ma méthode java comme ceci:

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

    Votre répertoire source java est-il copié dans le répertoire android-build? Le dossier Android dans votre dossier source doit être répertorié dans la variable qmake ANDROID_PACKAGE_SOURCE_DIR voir: http://qt-project.org/doc/qt-5/deployment-android.html#qmake-variables

    Le moyen le plus simple d'obtenir FindClass au travail sera de l'appeler à partir de la fonction JNI_OnLoad. Cette fonction sera automatiquement appelée par JNI en temps de chargement dans le fil correct. L'ancienne version de l'exemple de notificationclient a utilisé cette méthode avant la validation # 6500083. Il s'agit d'un résumé de la partie pertinente du fichier androidjnibindings.cpp:

     #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; } 

    Ce n'est pas dans le code d'exemple 5.2 car cela n'est plus nécessaire pour appeler Java à partir du code C ++, mais je ne suis pas au courant d'un exemple QT5.2 montrant l'appel de C depuis Java.

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

    Au lieu de "android / src / org / app / test / JniMath", essayez de donner le nom du pack: "org / app / test / JniMath" et le mettre dans

     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); } 

    Quelque chose comme ça…

    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.