我正在将Qt应用程序移植到Android,并与系统的某些部分进行通信,它使用随应用程序打包的自定义Java库。问题是我找不到加载我需要调用的Java类的地方。
通常我会在JNI_OnLoad中执行此操作,但Qt 5.3会将其隐藏在自己的内部代码中。这意味着我必须在Qt应用程序启动时从本机线程加载类,因为QApplication是在自己的线程中启动的。系统类加载器可以从这个上下文中获得,但不能在我的APK中找到类。
另一种选择是获取可以找到本地类的类加载器。通过Qt代码浏览,我看到它在启动时抓住了类加载器,但同样在Qt私有代码中也是如此。无法从应用程序访问它。
我认为在Qt Android应用程序中这是一个相当普遍的事情,我很惊讶它给我带来了这样的悲伤。我希望我遗漏一些明显的东西。
有没有人知道在Qt 5.3应用程序中使用JNI检索java类实例的正确位置?
忽略错误检查,下面的代码片段是我尝试做的。我已验证该类已包含在具有预期名称的dex文件中,但从未找到该类(抛出java.lang.NoClassDefFoundError)。
// Given a JNIEnv, find MyClass, and cache it away for later use
jclass localClass = env->FindClass("my/class/in/apk/MyClass");
j_MyClass = reinterpret_cast<jclass>(env->NewGlobalRef(localClass));
env->DeleteLocalRef(localClass);
答案 0 :(得分:0)
事实证明我并不接受Qt方式。我自己无法缓存jclass,但使用Qt类QAndroidJniObject可以达到同样的效果。在引擎盖下,Qt缓存引用的引用的jclass和jmethod。在Qt实现中有一些额外的开销而不是自己做,但在我的情况下这不是问题。从好的方面来说,它显着简化了JNI代码。
总之,只需使用QAndroidJniObject类,忘掉自己缓存jclass / jmethod引用。
作为一个没有错误检查的狡猾的例子:
void JNICALL Java_my_java_class_MyClass_myNativeMethod
(JNIEnv* env, jobject, jobjectArray objectArray)
{
QAndroidJniObject obj(env->GetObjectArrayElement(objectArray, 0));
QAndroidJniObject jstr = obj.callObjectMethod<jstring>("getString");
QString qtstr = jstr.toString();
}
回想起来,这一切都非常明显:)