diff --git a/android/apps/interface/build.gradle b/android/apps/interface/build.gradle index 4163df03b7..4093f0ff0d 100644 --- a/android/apps/interface/build.gradle +++ b/android/apps/interface/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.3.0' } } diff --git a/android/apps/questInterface/src/main/AndroidManifest.xml b/android/apps/questInterface/src/main/AndroidManifest.xml index c23f14ee15..24bd643744 100644 --- a/android/apps/questInterface/src/main/AndroidManifest.xml +++ b/android/apps/questInterface/src/main/AndroidManifest.xml @@ -28,17 +28,12 @@ android:excludeFromRecents="true"> - + - diff --git a/android/apps/questInterface/src/main/cpp/native.cpp b/android/apps/questInterface/src/main/cpp/native.cpp index b7422b3b66..02b585203d 100644 --- a/android/apps/questInterface/src/main/cpp/native.cpp +++ b/android/apps/questInterface/src/main/cpp/native.cpp @@ -22,8 +22,8 @@ #include #include -#include -#include +//#include +//#include void initOculusPlatform(JNIEnv* env, jobject obj) { static std::once_flag once; @@ -38,49 +38,89 @@ void initOculusPlatform(JNIEnv* env, jobject obj) { } extern "C" { + JNIEXPORT void JNICALL + Java_io_highfidelity_questInterface_QuestActivity_nativeInitOculusPlatform(JNIEnv *env, jobject obj){ + initOculusPlatform(env, obj); + } -JNIEXPORT void JNICALL -Java_io_highfidelity_questInterface_MainActivity_nativeInitOculusPlatform(JNIEnv* env, jobject obj) { - initOculusPlatform(env, obj); -} +QAndroidJniObject __interfaceActivity; -JNIEXPORT void JNICALL -Java_io_highfidelity_questInterface_MainActivity_nativeOnCreate(JNIEnv* env, jobject obj) { - initOculusPlatform(env, obj); - qRegisterMetaType("QAndroidJniObject"); - QObject::connect(&AndroidHelper::instance(), &AndroidHelper::qtAppLoadComplete, []() { - qWarning() << "QQQ" << __FUNCTION__ << "scheduling onAppLoadedComplete"; - AndroidHelper::instance().moveToThread(qApp->thread()); - QtAndroid::androidActivity().callMethod("onAppLoadedComplete", "()V"); - QObject::disconnect(&AndroidHelper::instance(), &AndroidHelper::qtAppLoadComplete, nullptr, nullptr); - }); -} + JNIEXPORT void JNICALL + Java_io_highfidelity_questInterface_QuestActivity_nativeOnCreate(JNIEnv *env, jobject obj) { + initOculusPlatform(env, obj); + __interfaceActivity = QAndroidJniObject(obj); -JNIEXPORT void JNICALL -Java_io_highfidelity_questInterface_MainActivity_nativeOnDestroy(JNIEnv* env, jobject obj) { -} + if(qApp) { + QThread *thr = qApp->thread(); + } -JNIEXPORT void JNICALL -Java_io_highfidelity_questInterface_SplashActivity_registerLoadCompleteListener(JNIEnv *env, - jobject instance) { - -} - -JNIEXPORT void JNICALL -Java_io_highfidelity_questInterface_MainActivity_nativeOnPause(JNIEnv *env, jobject obj) { - AndroidHelper::instance().notifyEnterBackground(); -} - -JNIEXPORT void JNICALL -Java_io_highfidelity_questInterface_MainActivity_nativeOnResume(JNIEnv *env, jobject obj) { - AndroidHelper::instance().notifyEnterForeground(); -} - -JNIEXPORT void JNICALL -Java_io_highfidelity_questInterface_receiver_HeadsetStateReceiver_notifyHeadsetOn(JNIEnv *env, - jobject instance, - jboolean pluggedIn) { - AndroidHelper::instance().notifyHeadsetOn(pluggedIn); -} + AndroidHelper::instance().moveToThread(thr); + + + qRegisterMetaType("QAndroidJniObject"); + + JavaVM* jvm; + env->GetJavaVM(&jvm); + + QObject::connect(&AndroidHelper::instance(), &AndroidHelper::androidActivityRequested, [jvm](const QString& a, const bool backToScene, QMap args) { + JNIEnv* myNewEnv; + JavaVMAttachArgs jvmArgs; + jvmArgs.version = JNI_VERSION_1_6; // choose your JNI version + jvmArgs.name = NULL; // you might want to give the java thread a name + jvmArgs.group = NULL; // you might want to assign the java thread to a ThreadGroup + + int attachedHere = 0; // know if detaching at the end is necessary + jint res = jvm->GetEnv((void**)&myNewEnv, JNI_VERSION_1_6); // checks if current env needs attaching or it is already attached + if (JNI_OK != res) { + qDebug() << "[JCRASH] GetEnv env not attached yet, attaching now.."; + res = jvm->AttachCurrentThread(reinterpret_cast(&myNewEnv), &jvmArgs); + if (JNI_OK != res) { + qDebug() << "[JCRASH] Failed to AttachCurrentThread, ErrorCode = " << res; + return; + } else { + attachedHere = 1; + } + } + + QAndroidJniObject string = QAndroidJniObject::fromString(a); + jboolean jBackToScene = (jboolean) backToScene; + jclass hashMapClass = myNewEnv->FindClass("java/util/HashMap"); + jmethodID mapClassConstructor = myNewEnv->GetMethodID(hashMapClass, "", "()V"); + jobject hashmap = myNewEnv->NewObject(hashMapClass, mapClassConstructor); + jmethodID mapClassPut = myNewEnv->GetMethodID(hashMapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + QMap::iterator i; + for (i = args.begin(); i != args.end(); ++i) { + QAndroidJniObject jKey = QAndroidJniObject::fromString(i.key()); + QAndroidJniObject jValue = QAndroidJniObject::fromString(i.value()); + myNewEnv->CallObjectMethod(hashmap, mapClassPut, jKey.object(), jValue.object()); + } + __interfaceActivity.callMethod("openAndroidActivity", "(Ljava/lang/String;ZLjava/util/HashMap;)V", string.object(), jBackToScene, hashmap); + if (attachedHere) { + jvm->DetachCurrentThread(); + } + }); + + } + + JNIEXPORT void JNICALL + Java_io_highfidelity_questInterface_QuestActivity_nativeOnDestroy(JNIEnv *env, jobject obj) { + } + + JNIEXPORT void JNICALL + Java_io_highfidelity_questInterface_QuestActivity_nativeOnPause(JNIEnv *env, jobject obj) { + AndroidHelper::instance().notifyEnterBackground(); + } + + JNIEXPORT void JNICALL + Java_io_highfidelity_questInterface_QuestActivity_nativeOnResume(JNIEnv *env, jobject obj) { + AndroidHelper::instance().notifyEnterForeground(); + } + + JNIEXPORT void JNICALL + Java_io_highfidelity_questInterface_receiver_HeadsetStateReceiver_notifyHeadsetOn(JNIEnv *env, + jobject instance, + jboolean pluggedIn) { + AndroidHelper::instance().notifyHeadsetOn(pluggedIn); + } } diff --git a/android/apps/questInterface/src/main/java/io/highfidelity/questInterface/MainActivity.java b/android/apps/questInterface/src/main/java/io/highfidelity/questInterface/MainActivity.java index ce75c54f12..93aafa042b 100644 --- a/android/apps/questInterface/src/main/java/io/highfidelity/questInterface/MainActivity.java +++ b/android/apps/questInterface/src/main/java/io/highfidelity/questInterface/MainActivity.java @@ -11,6 +11,8 @@ package io.highfidelity.questInterface; +import android.app.Activity; +import android.app.Application; import android.content.Intent; import android.os.Bundle; import android.util.Log; @@ -29,10 +31,9 @@ public class MainActivity extends QtActivity { private native void nativeOnPause(); private native void nativeOnResume(); + private boolean isLoading; @Override public void onCreate(Bundle savedInstanceState) { - super.isLoading = true; - super.keepInterfaceRunning = true; super.onCreate(savedInstanceState); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); HifiUtils.upackAssets(getAssets(), getCacheDir().getAbsolutePath()); @@ -41,6 +42,7 @@ public class MainActivity extends QtActivity { public void onAppLoadedComplete() { + Log.w("QQQ", "Returning to quest activity"); runOnUiThread(()->{ startActivity(new Intent(MainActivity.this, QuestActivity.class)); @@ -51,9 +53,9 @@ public class MainActivity extends QtActivity { @Override protected void onPause() { super.onPause(); - if (!super.isLoading) { + nativeOnPause(); - } + } @Override diff --git a/android/apps/questInterface/src/main/java/io/highfidelity/questInterface/PermissionsChecker.java b/android/apps/questInterface/src/main/java/io/highfidelity/questInterface/PermissionsChecker.java index 91b5bdcdae..7d8ce383dc 100644 --- a/android/apps/questInterface/src/main/java/io/highfidelity/questInterface/PermissionsChecker.java +++ b/android/apps/questInterface/src/main/java/io/highfidelity/questInterface/PermissionsChecker.java @@ -45,7 +45,7 @@ public class PermissionsChecker extends Activity { private void launchActivityWithPermissions() { startActivity(new Intent(this, QuestActivity.class)); - finish(); + } @Override diff --git a/android/apps/questInterface/src/main/java/io/highfidelity/questInterface/QuestActivity.java b/android/apps/questInterface/src/main/java/io/highfidelity/questInterface/QuestActivity.java index 6887140de5..a7aa93dbb9 100644 --- a/android/apps/questInterface/src/main/java/io/highfidelity/questInterface/QuestActivity.java +++ b/android/apps/questInterface/src/main/java/io/highfidelity/questInterface/QuestActivity.java @@ -13,13 +13,44 @@ package io.highfidelity.questInterface; import android.content.Intent; import android.os.Bundle; +import android.view.WindowManager; import io.highfidelity.oculus.OculusMobileActivity; +import io.highfidelity.utils.HifiUtils; public class QuestActivity extends OculusMobileActivity { + private native void nativeOnCreate(); + private native void nativeOnDestroy(); + private native void nativeOnPause(); + private native void nativeOnResume(); + + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - startActivity(new Intent(this, MainActivity.class)); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + HifiUtils.upackAssets(getAssets(), getCacheDir().getAbsolutePath()); + nativeOnCreate(); } + + + @Override + protected void onPause() { + super.onPause(); + nativeOnPause(); + + } + + @Override + protected void onResume() { + super.onResume(); + nativeOnResume(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + nativeOnDestroy(); + } + } diff --git a/android/build.gradle b/android/build.gradle index 4affdf65cd..eebe7bdc27 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.3.0' } } diff --git a/android/libraries/oculus/build.gradle b/android/libraries/oculus/build.gradle index b072f99eb7..776c0c1e48 100644 --- a/android/libraries/oculus/build.gradle +++ b/android/libraries/oculus/build.gradle @@ -15,3 +15,7 @@ android { targetCompatibility JavaVersion.VERSION_1_8 } } + +dependencies { + compile project(path: ':qt') +} diff --git a/android/libraries/oculus/src/main/java/io/highfidelity/oculus/OculusMobileActivity.java b/android/libraries/oculus/src/main/java/io/highfidelity/oculus/OculusMobileActivity.java index 01d74ea94d..b06f850afc 100644 --- a/android/libraries/oculus/src/main/java/io/highfidelity/oculus/OculusMobileActivity.java +++ b/android/libraries/oculus/src/main/java/io/highfidelity/oculus/OculusMobileActivity.java @@ -16,11 +16,15 @@ import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.WindowManager; + + +import org.qtproject.qt5.android.bindings.QtActivity; + /** * Contains a native surface and forwards the activity lifecycle and surface lifecycle * events to the OculusMobileDisplayPlugin */ -public class OculusMobileActivity extends Activity implements SurfaceHolder.Callback { +public class OculusMobileActivity extends QtActivity implements SurfaceHolder.Callback { private static final String TAG = OculusMobileActivity.class.getSimpleName(); static { System.loadLibrary("oculusMobile"); } private native void nativeOnCreate(); @@ -32,7 +36,6 @@ public class OculusMobileActivity extends Activity implements SurfaceHolder.Call private SurfaceView mView; private SurfaceHolder mSurfaceHolder; - public static void launch(Activity activity) { if (activity != null) { activity.runOnUiThread(()->{ @@ -45,7 +48,9 @@ public class OculusMobileActivity extends Activity implements SurfaceHolder.Call public void onCreate(Bundle savedInstanceState) { Log.w(TAG, "QQQ onCreate"); super.onCreate(savedInstanceState); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + // Create a native surface for VR rendering (Qt GL surfaces are not suitable // because of the lack of fine control over the surface callbacks) mView = new SurfaceView(this); diff --git a/android/libraries/qt/src/main/java/org/qtproject/qt5/android/bindings/QtActivity.java b/android/libraries/qt/src/main/java/org/qtproject/qt5/android/bindings/QtActivity.java index 6a6688ac41..02597956e4 100644 --- a/android/libraries/qt/src/main/java/org/qtproject/qt5/android/bindings/QtActivity.java +++ b/android/libraries/qt/src/main/java/org/qtproject/qt5/android/bindings/QtActivity.java @@ -70,9 +70,6 @@ public class QtActivity extends Activity { public final String QT_ANDROID_DEFAULT_THEME = QT_ANDROID_THEMES[0]; // sets the default theme. private QtActivityLoader m_loader = new QtActivityLoader(this); - public boolean isLoading; - public boolean keepInterfaceRunning; - public QtActivity() { } @@ -229,10 +226,13 @@ public class QtActivity extends Activity { //--------------------------------------------------------------------------- protected void onCreateHook(Bundle savedInstanceState) { + m_loader.APPLICATION_PARAMETERS = APPLICATION_PARAMETERS; m_loader.ENVIRONMENT_VARIABLES = ENVIRONMENT_VARIABLES; m_loader.QT_ANDROID_THEMES = QT_ANDROID_THEMES; m_loader.QT_ANDROID_DEFAULT_THEME = QT_ANDROID_DEFAULT_THEME; + + m_loader.onCreate(savedInstanceState); } @@ -506,9 +506,7 @@ public class QtActivity extends Activity { super.onPause(); // GC: this trick allow us to show a splash activity until Qt app finishes // loading - if (!isLoading && !keepInterfaceRunning) { - QtApplication.invokeDelegate(); - } + QtApplication.invokeDelegate(); } //--------------------------------------------------------------------------- @@ -647,11 +645,7 @@ public class QtActivity extends Activity { @Override protected void onStop() { super.onStop(); - if (!keepInterfaceRunning) { - QtApplication.invokeDelegate(); - } - QtNative.terminateQt(); - QtNative.setActivity(null,null); + QtApplication.invokeDelegate(); } //--------------------------------------------------------------------------- diff --git a/android/libraries/qt/src/main/java/org/qtproject/qt5/android/bindings/QtActivityLoader.java b/android/libraries/qt/src/main/java/org/qtproject/qt5/android/bindings/QtActivityLoader.java index e3066a3bd9..5258c0fb88 100644 --- a/android/libraries/qt/src/main/java/org/qtproject/qt5/android/bindings/QtActivityLoader.java +++ b/android/libraries/qt/src/main/java/org/qtproject/qt5/android/bindings/QtActivityLoader.java @@ -79,6 +79,7 @@ public class QtActivityLoader { private static final String EXTRACT_STYLE_MINIMAL_KEY = "extract.android.style.option"; private static final int BUFFER_SIZE = 1024; + public boolean Created=false; String APPLICATION_PARAMETERS = null; // use this variable to pass any parameters to your application, String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_DIALOGS=1"; String[] QT_ANDROID_THEMES = null; @@ -497,6 +498,8 @@ public class QtActivityLoader { } startApp(); + + Created=true; } } } diff --git a/android/settings.gradle b/android/settings.gradle index 64eb246719..23e54b0457 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -12,8 +12,8 @@ project(':qt').projectDir = new File(settingsDir, 'libraries/qt') // Applications // -include ':interface' -project(':interface').projectDir = new File(settingsDir, 'apps/interface') +//include ':interface' +//project(':interface').projectDir = new File(settingsDir, 'apps/interface') include ':questInterface' project(':questInterface').projectDir = new File(settingsDir, 'apps/questInterface') @@ -22,8 +22,8 @@ project(':questInterface').projectDir = new File(settingsDir, 'apps/questInterfa // Test projects // -include ':framePlayer' -project(':framePlayer').projectDir = new File(settingsDir, 'apps/framePlayer') +//include ':framePlayer' +//project(':framePlayer').projectDir = new File(settingsDir, 'apps/framePlayer') -include ':questFramePlayer' -project(':questFramePlayer').projectDir = new File(settingsDir, 'apps/questFramePlayer') +//include ':questFramePlayer' +//project(':questFramePlayer').projectDir = new File(settingsDir, 'apps/questFramePlayer')