Utilizar Qt / C ++ para llamar al código Java a través de JNI. FindClass no encuentra clase

Soy nuevo en JNI y este es mi primer programa tratando de llamar al código Java de C ++. Estoy usando Qt 5.2 y estoy escribiendo una aplicación de Android.

No puedo encontrar mi clase java y cargarla en mi programa C ++. He leído un montón de puestos aquí en desbordamiento de pila y otros lugares y parece ser un problema común, pero no he sido capaz de resolver la mía todavía ..

Tampoco estoy seguro de si la VM Java está configurada correctamente ya que la documentación de Qt en el QAndroidJniEnvironment es mínima.

Estoy buscando una solución sobre cómo ser capaz de encontrar mi clase de java. También estoy apreciando comentarios generales sobre otras secciones del código (supongo que podría haber más errores).

Error msg:

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) 

Clase Java:

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

Estructura del proyecto:

Introduzca aquí la descripción de la imagen

EDITAR:

También intenté un acercamiento diferente que conduce al mismo error:

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

Al intentar cargar java / lang / String en su lugar, ambos métodos anteriores encuentran la clase.

EDITAR:

Registro de errores:

 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 

Comentario: por qué esta pregunta no es un duplicado (por Alex Cohn)

No hay duda de que el problema de raíz aquí es el mismo que en FindClass de cualquier hilo en Android JNI , pero la pregunta aquí es una pregunta muy diferente, IMO. El autor no buscaba una forma genérica de acceder al ClassLoader desde los subprocesos nativos. Él (o ella) estaba buscando una manera fácil y eficiente de acceder a una devolución de llamada de Java a partir del código nativo basado en Qt. Por lo tanto, toda discusión sobre cómo funciona el cargador de clases en Android y cómo esto puede ser reparado es irrelevante para él. Si el autor piensa lo contrario, estaré de buen grado de acuerdo en cerrar esta pregunta como duplicado

Actualización: esta pregunta ni siquiera está relacionada con los hilos JNI

Considere el comentario anterior como nulo. Esta pregunta no tiene nada que ver con multithreading. Todo se trata de cómo configurar una aplicación Android Qt tal que podría utilizar clases Java personalizadas, similares a la muestra .

Utilicé este ejemplo http://www.gnuton.org/blog/2014/01/invoking-qtc-code-from-the-java-side-of-qt-for-android-application/

Así es como lo hice. En mi clase java principal agregué un método estático para llamar a la misma actividad (porque tiene que ser estática):

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

Luego en mi archivo de encabezado agregué esto:

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

Y en mi archivo cpp sólo llamé a mi método java como este:

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

¿Es su directorio de origen java copiado en el directorio android-build? La carpeta android de la carpeta de origen debe aparecer en la variable qmake ANDROID_PACKAGE_SOURCE_DIR ver: http://qt-project.org/doc/qt-5/deployment-android.html#qmake-variables

La forma más fácil de obtener FindClass para trabajar será para llamar desde dentro de la función JNI_OnLoad. Esta función será llamada automáticamente por JNI en el tiempo de carga en el hilo correcto. La versión antigua del ejemplo notifyclient usó este método antes de commit # 6500083. Este es un resumen de la parte relevante del archivo 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; } 

Esto no está en el código de ejemplo 5.2 ya que esto ya no es necesario para llamar a Java desde el código C ++, pero no estoy al tanto de un ejemplo de QT5.2 que muestra llamar a C desde Java.

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

En lugar de "android / src / org / app / test / JniMath" intenta dar el nombre de paquete: "org / app / test / JniMath" y ponerlo en

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

Algo como esto…

  • Qt versiones para arquitecturas mips, brazo, x86 faltan
  • ¿Cómo ejecutar una aplicación Qt en segundo plano en Android?
  • Botón General Share en Android en Qt Quick
  • Cómo utilizar la clase Qt Jni "QAndroidJniObject"
  • Qt para Andorid en OpenSuse 13.2
  • Qt Android bluetooth socket escribir problemas en Android 5.1.1 y 6.0
  • Aplicaciones multipágina en QML
  • Qt cómo conectar a un archivo SQLlite existente en el sistema operativo Android?
  • Qt Creator: No se han encontrado juegos válidos para Android
  • Qt Android: ¿Por qué se crea QtApp-debug.apk para una versión de Release?
  • Portar la aplicación iphone. Si tuviera que iniciar su aplicación de nuevo desde cero, ¿qué haría de manera diferente?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.