Android: Use the application's class loader when loading Java classes.

Previously the system class loader was used, which meant only system
Java classes where available. With this change it's no longer necessary
to add a JNI_OnLoad() to get a handle to application specific classes.

Change-Id: Ic8fe35b4e525bfeb1d317d5ba6b496e39bf9bb30
Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
This commit is contained in:
Christian Strømme 2013-09-24 18:04:14 +02:00 committed by The Qt Project
parent 9a683bfb84
commit 1db9075482
3 changed files with 33 additions and 4 deletions

View File

@ -70,16 +70,24 @@ static jclass getCachedClass(JNIEnv *env, const char *className)
QString key = QLatin1String(className);
QHash<QString, jclass>::iterator it = cachedClasses->find(key);
if (it == cachedClasses->end()) {
jclass c = env->FindClass(className);
QJNIObjectPrivate classLoader = QtAndroidPrivate::classLoader();
if (!classLoader.isValid())
return 0;
QJNIObjectPrivate stringName = QJNIObjectPrivate::fromString(QLatin1String(className));
QJNIObjectPrivate classObject = classLoader.callObjectMethod("loadClass",
"(Ljava/lang/String;)Ljava/lang/Class;",
stringName.object());
if (env->ExceptionCheck()) {
c = 0;
#ifdef QT_DEBUG
env->ExceptionDescribe();
#endif // QT_DEBUG
env->ExceptionClear();
}
if (c)
clazz = static_cast<jclass>(env->NewGlobalRef(c));
if (classObject.isValid())
clazz = static_cast<jclass>(env->NewGlobalRef(classObject.object()));
cachedClasses->insert(key, clazz);
} else {
clazz = it.value();

View File

@ -45,6 +45,7 @@ QT_BEGIN_NAMESPACE
static JavaVM *g_javaVM = Q_NULLPTR;
static jobject g_jActivity = Q_NULLPTR;
static jobject g_jClassLoader = Q_NULLPTR;
static inline bool exceptionCheck(JNIEnv *env)
{
@ -79,6 +80,20 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env)
if (exceptionCheck(env))
return JNI_ERR;
jmethodID classLoaderMethodID = env->GetStaticMethodID(jQtNative,
"classLoader",
"()Ljava/lang/ClassLoader;");
if (exceptionCheck(env))
return JNI_ERR;
jobject classLoader = env->CallStaticObjectMethod(jQtNative, classLoaderMethodID);
if (exceptionCheck(env))
return JNI_ERR;
g_jClassLoader = env->NewGlobalRef(classLoader);
g_jActivity = env->NewGlobalRef(activity);
g_javaVM = vm;
@ -96,4 +111,9 @@ JavaVM *QtAndroidPrivate::javaVM()
return g_javaVM;
}
jobject QtAndroidPrivate::classLoader()
{
return g_jClassLoader;
}
QT_END_NAMESPACE

View File

@ -63,6 +63,7 @@ namespace QtAndroidPrivate
Q_CORE_EXPORT jobject activity();
Q_CORE_EXPORT JavaVM *javaVM();
Q_CORE_EXPORT jint initJNI(JavaVM *vm, JNIEnv *env);
jobject classLoader();
}
QT_END_NAMESPACE