Class 尝试在 QT 项目中调用 Java 代码时未发现异常
Class not found exception while trying to call Java code in a QT project
我正在尝试在 Android 应用程序的 QT Creator 项目中使用一些用 Java 编写的代码。我的最终目标是在此项目中使用通过 Android Studio 创建的 classes 和方法。
为了测试我是否理解 QT Java 包装器 class 我从 Android Studio 创建了一个 Java class:
文件>>新建模块>>Android库>>完成
在这个库中我创建了一个 class 如下:
package com.example.testclass;
public class MyJavaClass {
public static int fibonacci (int n){
if (n <2)
return n;
return fibonacci(n-1) + fibonacci(n-2);
}
}
然后'Build>>Make module'
在我的 QT 项目 .pro 文件中,我添加了:QT += androidextras 并复制了 .aar 文件(也尝试解压缩和复制.jar 文件同样尝试将 ...\testclass\src\main 复制到 javalib\ 目录在我的项目文件中。
现在,在这一点上,我尝试了很多方法来使这个文件对我的项目可见。我通过添加编辑 .pro 文件:
OTHER_FILES += \
javalib/java/com/example/testclass/MyJavaClass.java \
javalib/AndroidManifest.xml
我试图通过 gradle 文件添加项目中已经存在的文件以及其他一些我不记得的东西。
但仍然遵循从 'MyJavaClass';
调用 'fibonacci' 方法的代码
void MainWindow::on_javaButton_clicked()
{
int fibo = QAndroidJniObject::callStaticMethod<jint>("com/example/testclass/MyJavaClass", "fibonacci", "(I)I", 5);
qDebug() << "JAVA OUTPUT: " << fibo << endl;
}
在 运行 时间抛出 class 未找到异常:
W System.err: java.lang.ClassNotFoundException: Didn't find class "com.example.testclass.MyJavaClass" on path: DexPathList[[],nativeLibraryDirectories=[/system/lib64, /system/vendor/lib64]]
W System.err: at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:93)
W System.err: at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
W System.err: at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
W System.err: at org.qtproject.qt5.android.QtNative.startQtApplication(Native Method)
W System.err: at org.qtproject.qt5.android.QtNative.run(QtNative.java:390)
W System.err: at org.qtproject.qt5.android.QtThread.run(QtThread.java:61)
W System.err: at java.lang.Thread.run(Thread.java:764)
D libBlueToothTest.so: JAVA OUTPUT: 0
我尝试使用来自 QT 站点和其他来源的文档,例如 https://www.qtdeveloperdays.com/sites/default/files/BogdanVatra_Extending_Qt_Android_Apps_with_JNI.pdf。
我是 QT 新手,Android 和 Java。 尽管有文档和示例,但我仍在努力解决这个问题,我将不胜感激。
我现在的 .pro 文件:
QT += core gui bluetooth androidextras
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
BlueTooth/BlueToothManager.cpp \
BlueTooth/bluetoothclient.cpp \
BlueTooth/bluetoothserver.cpp \
main.cpp \
mainwindow.cpp \
HEADERS += \
BlueTooth/BlueToothManager.h \
BlueTooth/bluetoothclient.h \
BlueTooth/bluetoothserver.h \
mainwindow.h \
FORMS += \
mainwindow.ui
OTHER_FILES += \
javalib/java/com/example/testclass/MyJavaClass.java \
javalib/AndroidManifest.xml
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
DISTFILES += \
android/AndroidManifest.xml \
android/build.gradle \
android/gradle/wrapper/gradle-wrapper.jar \
android/gradle/wrapper/gradle-wrapper.properties \
android/gradlew \
android/gradlew.bat \
android/res/values/libs.xml
contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
ANDROID_PACKAGE_SOURCE_DIR = \
$$PWD/android
}
我的 gradle 文件截至目前:
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.0'
}
}
repositories {
google()
jcenter()
}
apply plugin: 'com.android.application'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
}
android {
/*******************************************************
* The following variables:
* - androidBuildToolsVersion,
* - androidCompileSdkVersion
* - qt5AndroidDir - holds the path to qt android files
* needed to build any Qt application
* on Android.
*
* are defined in gradle.properties file. This file is
* updated by QtCreator and androiddeployqt tools.
* Changing them manually might break the compilation!
*******************************************************/
compileSdkVersion androidCompileSdkVersion.toInteger()
buildToolsVersion androidBuildToolsVersion
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java']
aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl']
res.srcDirs = [qt5AndroidDir + '/res', 'res']
resources.srcDirs = ['src']
renderscript.srcDirs = ['src']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
}
}
lintOptions {
abortOnError false
}
}
好的,我在这方面工作的时间太长了。经过大量的反复试验,我终于找到了解决这个问题的方法。 Java 的代码和 C++ 端都没有任何问题。问题出在 gradle 或 Android 清单文件中。
-我复制了 ...\AndroidStudioProjects\qtTest\testclass\src\main\java 文件(包含根据 Java 代码中的 'package' 关键字连接的文件夹以及 .java 源文件)到我的 Android 包目录,在我的例子中是 android\(见下一步)
-要从 QT 项目调用 Java 方法和 类,您需要将 android 包目录添加到 .pro 文件(我已经在底部有一个,它只是指向到我的项目目录中的 "android" 文件夹)。我不确切知道该文件一开始包含什么。我假设它是关于包装 C++ 代码来为 Android 构建程序。无论如何...
-下一步是为程序准备一个正确的模板。 项目>>构建步骤>>构建 Android APK>>创建模板 将您带到模板向导,其中已经有一个从 .pro 文件中获取的包源目录。我没有删除 "Copy the Gradle files to Android directory" 的勾号,但是我不知道它是否有任何不同。
-覆盖向导要求的所有内容。
在代码正常运行后,瞧瞧一个干净的构建!
我正在尝试在 Android 应用程序的 QT Creator 项目中使用一些用 Java 编写的代码。我的最终目标是在此项目中使用通过 Android Studio 创建的 classes 和方法。
为了测试我是否理解 QT Java 包装器 class 我从 Android Studio 创建了一个 Java class:
文件>>新建模块>>Android库>>完成
在这个库中我创建了一个 class 如下:
package com.example.testclass;
public class MyJavaClass {
public static int fibonacci (int n){
if (n <2)
return n;
return fibonacci(n-1) + fibonacci(n-2);
}
}
然后'Build>>Make module'
在我的 QT 项目 .pro 文件中,我添加了:QT += androidextras 并复制了 .aar 文件(也尝试解压缩和复制.jar 文件同样尝试将 ...\testclass\src\main 复制到 javalib\ 目录在我的项目文件中。 现在,在这一点上,我尝试了很多方法来使这个文件对我的项目可见。我通过添加编辑 .pro 文件:
OTHER_FILES += \
javalib/java/com/example/testclass/MyJavaClass.java \
javalib/AndroidManifest.xml
我试图通过 gradle 文件添加项目中已经存在的文件以及其他一些我不记得的东西。
但仍然遵循从 'MyJavaClass';
调用 'fibonacci' 方法的代码void MainWindow::on_javaButton_clicked()
{
int fibo = QAndroidJniObject::callStaticMethod<jint>("com/example/testclass/MyJavaClass", "fibonacci", "(I)I", 5);
qDebug() << "JAVA OUTPUT: " << fibo << endl;
}
在 运行 时间抛出 class 未找到异常:
W System.err: java.lang.ClassNotFoundException: Didn't find class "com.example.testclass.MyJavaClass" on path: DexPathList[[],nativeLibraryDirectories=[/system/lib64, /system/vendor/lib64]]
W System.err: at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:93)
W System.err: at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
W System.err: at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
W System.err: at org.qtproject.qt5.android.QtNative.startQtApplication(Native Method)
W System.err: at org.qtproject.qt5.android.QtNative.run(QtNative.java:390)
W System.err: at org.qtproject.qt5.android.QtThread.run(QtThread.java:61)
W System.err: at java.lang.Thread.run(Thread.java:764)
D libBlueToothTest.so: JAVA OUTPUT: 0
我尝试使用来自 QT 站点和其他来源的文档,例如 https://www.qtdeveloperdays.com/sites/default/files/BogdanVatra_Extending_Qt_Android_Apps_with_JNI.pdf。
我是 QT 新手,Android 和 Java。 尽管有文档和示例,但我仍在努力解决这个问题,我将不胜感激。
我现在的 .pro 文件:
QT += core gui bluetooth androidextras
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
BlueTooth/BlueToothManager.cpp \
BlueTooth/bluetoothclient.cpp \
BlueTooth/bluetoothserver.cpp \
main.cpp \
mainwindow.cpp \
HEADERS += \
BlueTooth/BlueToothManager.h \
BlueTooth/bluetoothclient.h \
BlueTooth/bluetoothserver.h \
mainwindow.h \
FORMS += \
mainwindow.ui
OTHER_FILES += \
javalib/java/com/example/testclass/MyJavaClass.java \
javalib/AndroidManifest.xml
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
DISTFILES += \
android/AndroidManifest.xml \
android/build.gradle \
android/gradle/wrapper/gradle-wrapper.jar \
android/gradle/wrapper/gradle-wrapper.properties \
android/gradlew \
android/gradlew.bat \
android/res/values/libs.xml
contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
ANDROID_PACKAGE_SOURCE_DIR = \
$$PWD/android
}
我的 gradle 文件截至目前:
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.0'
}
}
repositories {
google()
jcenter()
}
apply plugin: 'com.android.application'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
}
android {
/*******************************************************
* The following variables:
* - androidBuildToolsVersion,
* - androidCompileSdkVersion
* - qt5AndroidDir - holds the path to qt android files
* needed to build any Qt application
* on Android.
*
* are defined in gradle.properties file. This file is
* updated by QtCreator and androiddeployqt tools.
* Changing them manually might break the compilation!
*******************************************************/
compileSdkVersion androidCompileSdkVersion.toInteger()
buildToolsVersion androidBuildToolsVersion
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java']
aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl']
res.srcDirs = [qt5AndroidDir + '/res', 'res']
resources.srcDirs = ['src']
renderscript.srcDirs = ['src']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
}
}
lintOptions {
abortOnError false
}
}
好的,我在这方面工作的时间太长了。经过大量的反复试验,我终于找到了解决这个问题的方法。 Java 的代码和 C++ 端都没有任何问题。问题出在 gradle 或 Android 清单文件中。
-我复制了 ...\AndroidStudioProjects\qtTest\testclass\src\main\java 文件(包含根据 Java 代码中的 'package' 关键字连接的文件夹以及 .java 源文件)到我的 Android 包目录,在我的例子中是 android\(见下一步)
-要从 QT 项目调用 Java 方法和 类,您需要将 android 包目录添加到 .pro 文件(我已经在底部有一个,它只是指向到我的项目目录中的 "android" 文件夹)。我不确切知道该文件一开始包含什么。我假设它是关于包装 C++ 代码来为 Android 构建程序。无论如何...
-下一步是为程序准备一个正确的模板。 项目>>构建步骤>>构建 Android APK>>创建模板 将您带到模板向导,其中已经有一个从 .pro 文件中获取的包源目录。我没有删除 "Copy the Gradle files to Android directory" 的勾号,但是我不知道它是否有任何不同。
-覆盖向导要求的所有内容。
在代码正常运行后,瞧瞧一个干净的构建!