diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index f5794335b74f4..668dda306bcef 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -212,7 +212,7 @@ public class FlutterActivity extends Activity implements FlutterActivityAndFragmentDelegate.Host, LifecycleOwner { private static final String TAG = "FlutterActivity"; - private boolean hasRegisteredBackCallback = false; + @VisibleForTesting boolean hasRegisteredBackCallback = false; /** * The ID of the {@code FlutterView} created by this activity. @@ -634,6 +634,12 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + if (savedInstanceState != null + && savedInstanceState.getBoolean( + FlutterActivityAndFragmentDelegate.ON_BACK_CALLBACK_ENABLED_KEY)) { + setFrameworkHandlesBack(true); + } + delegate = new FlutterActivityAndFragmentDelegate(this); delegate.onAttach(this); delegate.onRestoreInstanceState(savedInstanceState); @@ -1477,6 +1483,11 @@ public boolean attachToEngineAutomatically() { return true; } + @Override + public boolean getBackCallbackState() { + return hasRegisteredBackCallback; + } + @Override public boolean popSystemNavigator() { // Hook for subclass. No-op if returns false. diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java index c576eacda8c0c..630d3dff4f4c9 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java @@ -76,6 +76,7 @@ private static final String TAG = "FlutterActivityAndFragmentDelegate"; private static final String FRAMEWORK_RESTORATION_BUNDLE_KEY = "framework"; private static final String PLUGINS_RESTORATION_BUNDLE_KEY = "plugins"; + static final String ON_BACK_CALLBACK_ENABLED_KEY = "enableOnBackInvokedCallbackState"; private static final int FLUTTER_SPLASH_VIEW_FALLBACK_ID = 486947586; /** Factory to obtain a FlutterActivityAndFragmentDelegate instance. */ @@ -691,6 +692,12 @@ void onSaveInstanceState(@Nullable Bundle bundle) { flutterEngine.getActivityControlSurface().onSaveInstanceState(plugins); bundle.putBundle(PLUGINS_RESTORATION_BUNDLE_KEY, plugins); } + + // If using a cached engine, we need to save whether the framework or the system should handle + // backs. + if (host.getCachedEngineId() != null && !host.shouldDestroyEngineWithHost()) { + bundle.putBoolean(ON_BACK_CALLBACK_ENABLED_KEY, host.getBackCallbackState()); + } } @Override @@ -1297,5 +1304,7 @@ PlatformPlugin providePlatformPlugin( *
Defaults to {@code true}.
*/
boolean attachToEngineAutomatically();
+
+ boolean getBackCallbackState();
}
}
diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java
index e26d13e80f74a..c9727594b618e 100644
--- a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java
+++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java
@@ -1009,7 +1009,8 @@ public FlutterActivityAndFragmentDelegate createDelegate(
return new FlutterActivityAndFragmentDelegate(host);
}
- private final OnBackPressedCallback onBackPressedCallback =
+ @VisibleForTesting
+ final OnBackPressedCallback onBackPressedCallback =
new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
@@ -1071,6 +1072,11 @@ public void onAttach(@NonNull Context context) {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ if (savedInstanceState != null
+ && savedInstanceState.getBoolean(
+ FlutterActivityAndFragmentDelegate.ON_BACK_CALLBACK_ENABLED_KEY)) {
+ onBackPressedCallback.setEnabled(true);
+ }
delegate.onRestoreInstanceState(savedInstanceState);
}
@@ -1655,6 +1661,11 @@ public boolean attachToEngineAutomatically() {
return true;
}
+ @Override
+ public boolean getBackCallbackState() {
+ return onBackPressedCallback.isEnabled();
+ }
+
/**
* {@inheritDoc}
*
diff --git a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityTest.java b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityTest.java
index 8833b7a96dbe3..07babd12a79ec 100644
--- a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityTest.java
+++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityTest.java
@@ -5,6 +5,7 @@
package io.flutter.embedding.android;
import static io.flutter.Build.API_LEVELS;
+import static io.flutter.embedding.android.FlutterActivityLaunchConfigs.EXTRA_CACHED_ENGINE_ID;
import static io.flutter.embedding.android.FlutterActivityLaunchConfigs.HANDLE_DEEPLINKING_META_DATA_KEY;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -34,6 +35,7 @@
import androidx.annotation.RequiresApi;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
+import androidx.test.core.app.ActivityScenario;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import io.flutter.FlutterInjector;
@@ -94,6 +96,48 @@ public void flutterViewHasId() {
assertTrue(activity.findViewById(FlutterActivity.FLUTTER_VIEW_ID) instanceof FlutterView);
}
+ @Test
+ @Config(sdk = API_LEVELS.API_34)
+ @TargetApi(API_LEVELS.API_34)
+ public void whenUsingCachedEngine_predictiveBackStateIsSaved() {
+ FlutterLoader mockFlutterLoader = mock(FlutterLoader.class);
+ FlutterJNI mockFlutterJni = mock(FlutterJNI.class);
+ when(mockFlutterJni.isAttached()).thenReturn(true);
+ FlutterEngine cachedEngine = new FlutterEngine(ctx, mockFlutterLoader, mockFlutterJni);
+ FlutterEngineCache.getInstance().put("my_cached_engine", cachedEngine);
+
+ ActivityScenario