Browse Source

Disable Engine::Exit() on iOS.
Disable Engine::SetAutoExit(false) on iOS and Android.
On Android, request activity finish from the Java side instead of directly exiting.

Lasse Öörni 12 years ago
parent
commit
554355ab63

+ 33 - 6
Source/Engine/Engine/Engine.cpp

@@ -66,6 +66,13 @@ typedef struct _CrtMemBlockHeader
 } _CrtMemBlockHeader;
 #endif
 
+#ifdef ANDROID
+extern "C"
+{
+    void Android_JNI_FinishActivity();
+}
+#endif
+
 namespace Urho3D
 {
 
@@ -396,16 +403,23 @@ void Engine::SetPauseMinimized(bool enable)
 
 void Engine::SetAutoExit(bool enable)
 {
+    // On mobile platforms exit is mandatory if requested by the platform itself and should not be attempted to be disabled
+#if defined(ANDROID) || defined(IOS)
+    enable = true;
+#endif
     autoExit_ = enable;
 }
 
 void Engine::Exit()
 {
-    Graphics* graphics = GetSubsystem<Graphics>();
-    if (graphics)
-        graphics->Close();
-    
-    exiting_ = true;
+#if defined(IOS)
+    // On iOS it's not legal for the application to exit on its own, instead it will be minimized with the home key
+#elif defined(ANDROID)
+    // On Android we request the Java activity to finish itself
+    Android_JNI_FinishActivity();
+#else
+    DoExit();
+#endif
 }
 
 void Engine::DumpProfiler()
@@ -675,7 +689,20 @@ const Variant& Engine::GetParameter(const VariantMap& parameters, const String&
 void Engine::HandleExitRequested(StringHash eventType, VariantMap& eventData)
 {
     if (autoExit_)
-        Exit();
+    {
+        // Do not call Exit() here, as it contains mobile platform -specific tests to not exit.
+        // If we do receive an exit request from the system on those platforms, we must comply
+        DoExit();
+    }
+}
+
+void Engine::DoExit()
+{
+    Graphics* graphics = GetSubsystem<Graphics>();
+    if (graphics)
+        graphics->Close();
+    
+    exiting_ = true;
 }
 
 }

+ 4 - 2
Source/Engine/Engine/Engine.h

@@ -60,7 +60,7 @@ public:
     void SetPauseMinimized(bool enable);
     /// Set whether to exit automatically on exit request (window close button.)
     void SetAutoExit(bool enable);
-    /// Close the application window and set the exit flag.
+    /// Close the graphics window and set the exit flag. No-op on iOS, as an iOS application can not legally exit.
     void Exit();
     /// Dump profiling information to the log.
     void DumpProfiler();
@@ -101,8 +101,10 @@ public:
     static const Variant& GetParameter(const VariantMap& parameters, const String& parameter, const Variant& defaultValue = Variant::EMPTY);
     
 private:
-    /// Handle exit requested event.
+    /// Handle exit requested event. Auto-exit if enabled.
     void HandleExitRequested(StringHash eventType, VariantMap& eventData);
+    /// Actually perform the exit actions.
+    void DoExit();
     
     /// Frame update timer.
     HiresTimer frameTimer_;

+ 14 - 0
Source/ThirdParty/SDL/src/core/android/SDL_android.c

@@ -243,6 +243,8 @@ void Java_org_libsdl_app_SDLActivity_nativeLowMemory(
 void Java_org_libsdl_app_SDLActivity_nativeQuit(
                                     JNIEnv* env, jclass cls)
 {
+    // Urho3D: added log print
+    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeQuit()");
     // Inject a SDL_QUIT event
     SDL_SendQuit();
     SDL_SendAppEvent(SDL_APP_TERMINATING);
@@ -435,6 +437,18 @@ SDL_bool Android_JNI_GetAccelerometerValues(float values[3])
     return retval;
 }
 
+// Urho3D: added function
+void Android_JNI_FinishActivity()
+{
+    // Terminating the SDL main thread on our own may cause crashes with extra threads, so request
+    // the activity to finish instead
+    jmethodID mid;
+    JNIEnv *mEnv = Android_JNI_GetEnv();
+    mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, "finishActivity","()V");
+    if (mid)
+        (*mEnv)->CallStaticVoidMethod(mEnv, mActivityClass, mid);
+}
+
 static void Android_JNI_ThreadDestroyed(void* value) {
     /* The thread is being destroyed, detach it from the Java VM and set the mThreadKey value to NULL as required */
     JNIEnv *env = (JNIEnv*) value;