From 874aa1708fad595addbec4276a623c0db3a7c7b4 Mon Sep 17 00:00:00 2001 From: Fredia Huya-Kouadio Date: Thu, 12 Aug 2021 12:01:28 -0700 Subject: [PATCH] Resolve issue where the Godot app remains stuck when resuming. This was caused by the fact that a new instance of Godot was created at resume while a previous instance already existed. The previous instance would then go through its cleanup lifecycle, and would thus attempt to close the entire app, leading to the system to restart the app, thus starting the cycle anew. The fix involves reusing the previous instance of Godot if one is available instead of creating a new one, as well as giving control to the host activity for how the process should be terminated. --- .../godotengine/godot/FullScreenGodotApp.java | 36 +++++++++++++++---- .../lib/src/org/godotengine/godot/Godot.java | 8 +++-- .../src/org/godotengine/godot/GodotHost.java | 5 +++ 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java index 89497d15269..ad7048cbf3a 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java +++ b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java @@ -32,11 +32,12 @@ package org.godotengine.godot; import android.content.Intent; import android.os.Bundle; -import android.view.KeyEvent; +import android.util.Log; import androidx.annotation.CallSuper; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; /** @@ -46,6 +47,8 @@ import androidx.fragment.app.FragmentActivity; * within an Android app. */ public abstract class FullScreenGodotApp extends FragmentActivity implements GodotHost { + private static final String TAG = FullScreenGodotApp.class.getSimpleName(); + @Nullable private Godot godotFragment; @@ -53,12 +56,33 @@ public abstract class FullScreenGodotApp extends FragmentActivity implements God public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.godot_app_layout); - godotFragment = initGodotInstance(); - if (godotFragment == null) { - throw new IllegalStateException("Godot instance must be non-null."); - } - getSupportFragmentManager().beginTransaction().replace(R.id.godot_fragment_container, godotFragment).setPrimaryNavigationFragment(godotFragment).commitNowAllowingStateLoss(); + Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.godot_fragment_container); + if (currentFragment instanceof Godot) { + Log.v(TAG, "Reusing existing Godot fragment instance."); + godotFragment = (Godot)currentFragment; + } else { + Log.v(TAG, "Creating new Godot fragment instance."); + godotFragment = initGodotInstance(); + if (godotFragment == null) { + throw new IllegalStateException("Godot instance must be non-null."); + } + + getSupportFragmentManager().beginTransaction().replace(R.id.godot_fragment_container, godotFragment).setPrimaryNavigationFragment(godotFragment).commitNowAllowingStateLoss(); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + onGodotForceQuit(godotFragment); + } + + @Override + public final void onGodotForceQuit(Godot instance) { + if (instance == godotFragment) { + System.exit(0); + } } @Override diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java index 70bcaaf8100..d1454d565cb 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java @@ -762,8 +762,6 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC super.onDestroy(); - // TODO: This is a temp solution. The proper fix will involve tracking down and properly shutting down each - // native Godot components that is started in Godot#onVideoInit. forceQuit(); } @@ -960,7 +958,11 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC } private void forceQuit() { - System.exit(0); + // TODO: This is a temp solution. The proper fix will involve tracking down and properly shutting down each + // native Godot components that is started in Godot#onVideoInit. + if (godotHost != null) { + godotHost.onGodotForceQuit(this); + } } private boolean obbIsCorrupted(String f, String main_pack_md5) { diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotHost.java b/platform/android/java/lib/src/org/godotengine/godot/GodotHost.java index 317fd135353..58e982c569e 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotHost.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotHost.java @@ -53,4 +53,9 @@ public interface GodotHost { * Invoked on the render thread when the Godot main loop has started. */ default void onGodotMainLoopStarted() {} + + /** + * Invoked on the UI thread as the last step of the Godot instance clean up phase. + */ + default void onGodotForceQuit(Godot instance) {} }