From efcf1dec4992bf7aab5bf1f0f4c0ee8c54030465 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Wed, 17 Feb 2016 14:37:50 +0200 Subject: Say hello to Android Services This changeset enables running a QCoreApplication from within an Android Service. The Android Application running can now have a QtActivity or a QtService, but having both in the same process is not supported. This patch was based on Cory Slep's patch [ChangeLog][Android] Qt can now be used to easily create Android Services. Task-number: QTBUG-37221 Change-Id: I0fd693daaa85b991940ffe9cc41c483022677199 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/kernel/qjnihelpers.cpp | 55 ++++++++++++++++++++++++++++++++++++-- src/corelib/kernel/qjnihelpers_p.h | 1 + 2 files changed, 54 insertions(+), 2 deletions(-) (limited to 'src/corelib/kernel') diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp index 2324a615d5..f576ed0d1c 100644 --- a/src/corelib/kernel/qjnihelpers.cpp +++ b/src/corelib/kernel/qjnihelpers.cpp @@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE static JavaVM *g_javaVM = Q_NULLPTR; static jobject g_jActivity = Q_NULLPTR; +static jobject g_jService = Q_NULLPTR; static jobject g_jClassLoader = Q_NULLPTR; static jint g_androidSdkVersion = 0; static jclass g_jNativeClass = Q_NULLPTR; @@ -239,6 +240,32 @@ static void setAndroidSdkVersion(JNIEnv *env) g_androidSdkVersion = env->GetStaticIntField(androidVersionClass, androidSDKFieldID); } +static void setNativeActivity(JNIEnv *env, jclass, jobject activity) +{ + if (g_jActivity != 0) + env->DeleteGlobalRef(g_jActivity); + + if (activity != 0) { + g_jActivity = env->NewGlobalRef(activity); + env->DeleteLocalRef(activity); + } else { + g_jActivity = 0; + } +} + +static void setNativeService(JNIEnv *env, jclass, jobject service) +{ + if (g_jService != 0) + env->DeleteGlobalRef(g_jService); + + if (service != 0) { + g_jService = env->NewGlobalRef(service); + env->DeleteLocalRef(service); + } else { + g_jService = 0; + } +} + jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env) { jclass jQtNative = env->FindClass("org/qtproject/qt5/android/QtNative"); @@ -254,10 +281,21 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env) return JNI_ERR; jobject activity = env->CallStaticObjectMethod(jQtNative, activityMethodID); + + if (exceptionCheck(env)) + return JNI_ERR; + + jmethodID serviceMethodID = env->GetStaticMethodID(jQtNative, + "service", + "()Landroid/app/Service;"); + if (exceptionCheck(env)) return JNI_ERR; + jobject service = env->CallStaticObjectMethod(jQtNative, serviceMethodID); + if (exceptionCheck(env)) + return JNI_ERR; jmethodID classLoaderMethodID = env->GetStaticMethodID(jQtNative, "classLoader", @@ -274,14 +312,22 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env) g_jClassLoader = env->NewGlobalRef(classLoader); env->DeleteLocalRef(classLoader); - g_jActivity = env->NewGlobalRef(activity); - env->DeleteLocalRef(activity); + if (activity) { + g_jActivity = env->NewGlobalRef(activity); + env->DeleteLocalRef(activity); + } + if (service) { + g_jService = env->NewGlobalRef(service); + env->DeleteLocalRef(service); + } g_javaVM = vm; static const JNINativeMethod methods[] = { {"runPendingCppRunnables", "()V", reinterpret_cast(runPendingCppRunnables)}, {"dispatchGenericMotionEvent", "(Landroid/view/MotionEvent;)Z", reinterpret_cast(dispatchGenericMotionEvent)}, {"dispatchKeyEvent", "(Landroid/view/KeyEvent;)Z", reinterpret_cast(dispatchKeyEvent)}, + {"setNativeActivity", "(Landroid/app/Activity;)V", reinterpret_cast(setNativeActivity)}, + {"setNativeService", "(Landroid/app/Service;)V", reinterpret_cast(setNativeService)} }; const bool regOk = (env->RegisterNatives(jQtNative, methods, sizeof(methods) / sizeof(methods[0])) == JNI_OK); @@ -305,6 +351,11 @@ jobject QtAndroidPrivate::activity() return g_jActivity; } +jobject QtAndroidPrivate::service() +{ + return g_jService; +} + JavaVM *QtAndroidPrivate::javaVM() { return g_javaVM; diff --git a/src/corelib/kernel/qjnihelpers_p.h b/src/corelib/kernel/qjnihelpers_p.h index 1bffd26e08..34bdbf6c80 100644 --- a/src/corelib/kernel/qjnihelpers_p.h +++ b/src/corelib/kernel/qjnihelpers_p.h @@ -100,6 +100,7 @@ namespace QtAndroidPrivate typedef std::function Runnable; Q_CORE_EXPORT jobject activity(); + Q_CORE_EXPORT jobject service(); Q_CORE_EXPORT JavaVM *javaVM(); Q_CORE_EXPORT jint initJNI(JavaVM *vm, JNIEnv *env); jobject classLoader(); -- cgit v1.2.3