From 9b25e716d253be3af50b11beb564dc5ded87f862 Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Thu, 26 Jan 2023 16:37:18 -0800 Subject: [PATCH 01/18] Log everywhere I see onBackPressed... And it doesn't log anything! --- shell/platform/android/io/flutter/app/FlutterActivity.java | 2 ++ .../android/io/flutter/app/FlutterActivityDelegate.java | 1 + .../android/io/flutter/app/FlutterFragmentActivity.java | 2 ++ .../android/io/flutter/embedding/android/FlutterActivity.java | 1 + .../embedding/android/FlutterActivityAndFragmentDelegate.java | 1 + .../android/io/flutter/embedding/android/FlutterFragment.java | 3 +++ .../io/flutter/embedding/android/FlutterFragmentActivity.java | 1 + .../android/io/flutter/plugin/platform/PlatformPlugin.java | 1 + 8 files changed, 12 insertions(+) diff --git a/shell/platform/android/io/flutter/app/FlutterActivity.java b/shell/platform/android/io/flutter/app/FlutterActivity.java index a28176b0f799b..ba1f884c671f6 100644 --- a/shell/platform/android/io/flutter/app/FlutterActivity.java +++ b/shell/platform/android/io/flutter/app/FlutterActivity.java @@ -11,6 +11,7 @@ import android.os.Bundle; import androidx.annotation.NonNull; import io.flutter.app.FlutterActivityDelegate.ViewFactory; +import io.flutter.Log; import io.flutter.plugin.common.PluginRegistry; import io.flutter.view.FlutterNativeView; import io.flutter.view.FlutterView; @@ -111,6 +112,7 @@ protected void onDestroy() { @Override public void onBackPressed() { + Log.v("justin", "onBackPressed in FlutterActivity"); if (!eventDelegate.onBackPressed()) { super.onBackPressed(); } diff --git a/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java b/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java index 21a9443228156..1787fa0f17e21 100644 --- a/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java +++ b/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java @@ -248,6 +248,7 @@ public void onDestroy() { @Override public boolean onBackPressed() { + Log.v("justin", "onBackPressed in FlutterActivityDelegate"); if (flutterView != null) { flutterView.popRoute(); return true; diff --git a/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java b/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java index bf8935e8bb161..18df240c99df9 100644 --- a/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java +++ b/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java @@ -13,6 +13,7 @@ import io.flutter.plugin.common.PluginRegistry; import io.flutter.view.FlutterNativeView; import io.flutter.view.FlutterView; +import io.flutter.Log; /** * Deprecated class for activities that use Flutter who also require the use of the Android v4 @@ -101,6 +102,7 @@ protected void onDestroy() { @Override public void onBackPressed() { + Log.v("justin", "onBackPressed ok in FlutterFragmentActivity"); if (!eventDelegate.onBackPressed()) { super.onBackPressed(); } diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index ef8b87dbc92b9..b93aed02b95ae 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -693,6 +693,7 @@ public void unregisterOnBackInvokedCallback() { @SuppressWarnings("Override") @Override public void onBackInvoked() { + Log.v("justin", "calling onBackPressed in onBackInvokedCallback in FlutterActivity (embedder)"); onBackPressed(); } } diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java index 56db871f1ef72..939e7a150ce0e 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java @@ -778,6 +778,7 @@ void onDetach() { *

This method instructs Flutter's navigation system to "pop route". */ void onBackPressed() { + Log.v("justin", "onBackPressed in FlutterFragmentAndFragmentDelegate"); ensureAlive(); if (flutterEngine != null) { Log.v(TAG, "Forwarding onBackPressed() to FlutterEngine."); diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java index 0ef5d872358d9..b5d471e5bc707 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java @@ -1003,6 +1003,7 @@ public FlutterActivityAndFragmentDelegate createDelegate( new OnBackPressedCallback(true) { @Override public void handleOnBackPressed() { + Log.v("justin", "calling onBackPressed in onBackPressedCallback in FlutterFragment (embedder)"); onBackPressed(); } }; @@ -1200,6 +1201,7 @@ public void onNewIntent(@NonNull Intent intent) { */ @ActivityCallThrough public void onBackPressed() { + Log.v("justin", "onBackPressed in FlutterFragment (embedder)"); if (stillAttachedForEvent("onBackPressed")) { delegate.onBackPressed(); } @@ -1643,6 +1645,7 @@ public boolean popSystemNavigator() { // Unless we disable the callback, the dispatcher call will trigger it. This will then // trigger the fragment's onBackPressed() implementation, which will call through to the // dart side and likely call back through to this method, creating an infinite call loop. + Log.v("justin", "changine enabled on onBackPressedCallback"); onBackPressedCallback.setEnabled(false); activity.getOnBackPressedDispatcher().onBackPressed(); onBackPressedCallback.setEnabled(true); diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java index d5e7fcad325df..085a62f00c981 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java @@ -663,6 +663,7 @@ protected void onNewIntent(@NonNull Intent intent) { @Override public void onBackPressed() { + Log.v("justin", "onBackPressed in FlutterFragmentActivity (embedder)"); flutterFragment.onBackPressed(); } diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 55af0485bf1e6..293bebf26b757 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -482,6 +482,7 @@ private void popSystemNavigator() { } if (activity instanceof OnBackPressedDispatcherOwner) { + Log.v("justin", "calling onBackPressed in popSystemNavigator in PlatformPlugin"); ((OnBackPressedDispatcherOwner) activity).getOnBackPressedDispatcher().onBackPressed(); } else { activity.finish(); From b10efe389707d9560da99c0a1b6963f6d83a0817 Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Fri, 27 Jan 2023 11:42:26 -0800 Subject: [PATCH 02/18] Just hackily remove all usage of onBack, and predictive back does work now --- .../io/flutter/app/FlutterActivity.java | 2 + .../flutter/app/FlutterActivityDelegate.java | 2 + .../io/flutter/app/FlutterActivityEvents.java | 2 + .../flutter/app/FlutterFragmentActivity.java | 2 + .../embedding/android/FlutterActivity.java | 17 +++++-- .../FlutterActivityAndFragmentDelegate.java | 2 + .../embedding/android/FlutterFragment.java | 45 ++++++++----------- .../android/FlutterFragmentActivity.java | 2 + .../plugin/platform/PlatformPlugin.java | 5 ++- 9 files changed, 48 insertions(+), 31 deletions(-) diff --git a/shell/platform/android/io/flutter/app/FlutterActivity.java b/shell/platform/android/io/flutter/app/FlutterActivity.java index ba1f884c671f6..8af19bb59650f 100644 --- a/shell/platform/android/io/flutter/app/FlutterActivity.java +++ b/shell/platform/android/io/flutter/app/FlutterActivity.java @@ -110,6 +110,7 @@ protected void onDestroy() { super.onDestroy(); } + /* @Override public void onBackPressed() { Log.v("justin", "onBackPressed in FlutterActivity"); @@ -117,6 +118,7 @@ public void onBackPressed() { super.onBackPressed(); } } + */ @Override protected void onStop() { diff --git a/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java b/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java index 1787fa0f17e21..61407afec363d 100644 --- a/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java +++ b/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java @@ -246,6 +246,7 @@ public void onDestroy() { } } + /* @Override public boolean onBackPressed() { Log.v("justin", "onBackPressed in FlutterActivityDelegate"); @@ -255,6 +256,7 @@ public boolean onBackPressed() { } return false; } + */ @Override public void onUserLeaveHint() { diff --git a/shell/platform/android/io/flutter/app/FlutterActivityEvents.java b/shell/platform/android/io/flutter/app/FlutterActivityEvents.java index 9340adb405394..06c879086fd88 100644 --- a/shell/platform/android/io/flutter/app/FlutterActivityEvents.java +++ b/shell/platform/android/io/flutter/app/FlutterActivityEvents.java @@ -60,7 +60,9 @@ public interface FlutterActivityEvents * continue with its default back button handling. * @see android.app.Activity#onBackPressed() */ + /* boolean onBackPressed(); + */ /** @see android.app.Activity#onUserLeaveHint() */ void onUserLeaveHint(); diff --git a/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java b/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java index 18df240c99df9..a440e14344b0e 100644 --- a/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java +++ b/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java @@ -100,6 +100,7 @@ protected void onDestroy() { super.onDestroy(); } + /* @Override public void onBackPressed() { Log.v("justin", "onBackPressed ok in FlutterFragmentActivity"); @@ -107,6 +108,7 @@ public void onBackPressed() { super.onBackPressed(); } } + */ @Override protected void onStart() { diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index b93aed02b95ae..af485b3e463e7 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -37,8 +37,8 @@ import android.view.View; import android.view.Window; import android.view.WindowManager; -import android.window.OnBackInvokedCallback; -import android.window.OnBackInvokedDispatcher; +//import android.window.OnBackInvokedCallback; +//import android.window.OnBackInvokedDispatcher; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -643,7 +643,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE); - registerOnBackInvokedCallback(); + //registerOnBackInvokedCallback(); configureWindowForTransparency(); @@ -662,6 +662,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { *

The callback must be unregistered in order to prevent unpredictable behavior once outside * the Flutter app. */ + /* @VisibleForTesting public void registerOnBackInvokedCallback() { if (Build.VERSION.SDK_INT >= 33) { @@ -670,6 +671,7 @@ public void registerOnBackInvokedCallback() { OnBackInvokedDispatcher.PRIORITY_DEFAULT, onBackInvokedCallback); } } + */ /** * Unregisters the callback from OnBackInvokedDispatcher. @@ -677,13 +679,16 @@ public void registerOnBackInvokedCallback() { *

This should be called when the activity is no longer in use to prevent unpredictable * behavior such as being stuck and unable to press back. */ + /* @VisibleForTesting public void unregisterOnBackInvokedCallback() { if (Build.VERSION.SDK_INT >= 33) { getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(onBackInvokedCallback); } } + */ + /* private final OnBackInvokedCallback onBackInvokedCallback = Build.VERSION.SDK_INT >= 33 ? new OnBackInvokedCallback() { @@ -698,6 +703,7 @@ public void onBackInvoked() { } } : null; + */ /** * Switches themes for this {@code Activity} from the theme used to launch this {@code Activity} @@ -879,7 +885,7 @@ protected void onSaveInstanceState(Bundle outState) { */ @VisibleForTesting public void release() { - unregisterOnBackInvokedCallback(); + //unregisterOnBackInvokedCallback(); if (delegate != null) { delegate.release(); delegate = null; @@ -928,12 +934,15 @@ protected void onNewIntent(@NonNull Intent intent) { } } + /* @Override public void onBackPressed() { + Log.v("justin", "onBackPressed in FlutterActivity (embedder)"); if (stillAttachedForEvent("onBackPressed")) { delegate.onBackPressed(); } } + */ @Override public void onRequestPermissionsResult( diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java index 939e7a150ce0e..fde38d0c54c2e 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java @@ -777,6 +777,7 @@ void onDetach() { * *

This method instructs Flutter's navigation system to "pop route". */ +/* void onBackPressed() { Log.v("justin", "onBackPressed in FlutterFragmentAndFragmentDelegate"); ensureAlive(); @@ -787,6 +788,7 @@ void onBackPressed() { Log.w(TAG, "Invoked onBackPressed() before FlutterFragment was attached to an Activity."); } } + */ /** * Invoke this from {@link android.app.Activity#onRequestPermissionsResult(int, String[], int[])} diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java index b5d471e5bc707..3194fa18b57c7 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java @@ -12,7 +12,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import androidx.activity.OnBackPressedCallback; +//import androidx.activity.OnBackPressedCallback; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -36,14 +36,11 @@ * *

    *
  1. {@link #onPostResume()} - *
  2. {@link #onBackPressed()} *
  3. {@link #onRequestPermissionsResult(int, String[], int[])} *
  4. {@link #onNewIntent(Intent)} *
  5. {@link #onUserLeaveHint()} *
* - * {@link #onBackPressed()} does not need to be called through if the fragment is constructed by one - * of the builders with {@code shouldAutomaticallyHandleOnBackPressed(true)}. * *

Additionally, when starting an {@code Activity} for a result from this {@code Fragment}, be * sure to invoke {@link Fragment#startActivityForResult(Intent, int)} rather than {@link @@ -161,7 +158,6 @@ public class FlutterFragment extends Fragment */ protected static final String ARG_ENABLE_STATE_RESTORATION = "enable_state_restoration"; /** - * True if the fragment should receive {@link #onBackPressed()} events automatically, without * requiring an explicit activity call through. */ protected static final String ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED = @@ -391,13 +387,10 @@ public NewEngineFragmentBuilder shouldAttachEngineToActivity( } /** - * Whether or not this {@code FlutterFragment} should automatically receive {@link - * #onBackPressed()} events, rather than requiring an explicit activity call through. Disabled + * Whether or not this {@code FlutterFragment} should automatically receive @link * by default. * *

When enabled, the activity will automatically dispatch back-press events to the fragment's - * {@link OnBackPressedCallback}, instead of requiring the activity to manually call {@link - * #onBackPressed()} in client code. If enabled, do not invoke {@link #onBackPressed()} * manually. * *

This behavior relies on the implementation of {@link #popSystemNavigator()}. It's not @@ -408,7 +401,8 @@ public NewEngineFragmentBuilder shouldAttachEngineToActivity( @NonNull public NewEngineFragmentBuilder shouldAutomaticallyHandleOnBackPressed( boolean shouldAutomaticallyHandleOnBackPressed) { - this.shouldAutomaticallyHandleOnBackPressed = shouldAutomaticallyHandleOnBackPressed; + //this.shouldAutomaticallyHandleOnBackPressed = shouldAutomaticallyHandleOnBackPressed; + this.shouldAutomaticallyHandleOnBackPressed = false;//shouldAutomaticallyHandleOnBackPressed; return this; } @@ -648,13 +642,9 @@ public CachedEngineFragmentBuilder shouldAttachEngineToActivity( } /** - * Whether or not this {@code FlutterFragment} should automatically receive {@link - * #onBackPressed()} events, rather than requiring an explicit activity call through. Disabled * by default. * *

When enabled, the activity will automatically dispatch back-press events to the fragment's - * {@link OnBackPressedCallback}, instead of requiring the activity to manually call {@link - * #onBackPressed()} in client code. If enabled, do not invoke {@link #onBackPressed()} * manually. * *

Enabling this behavior relies on explicit behavior in {@link #popSystemNavigator()}. It's @@ -665,7 +655,8 @@ public CachedEngineFragmentBuilder shouldAttachEngineToActivity( @NonNull public CachedEngineFragmentBuilder shouldAutomaticallyHandleOnBackPressed( boolean shouldAutomaticallyHandleOnBackPressed) { - this.shouldAutomaticallyHandleOnBackPressed = shouldAutomaticallyHandleOnBackPressed; + //this.shouldAutomaticallyHandleOnBackPressed = shouldAutomaticallyHandleOnBackPressed; + this.shouldAutomaticallyHandleOnBackPressed = false;//shouldAutomaticallyHandleOnBackPressed; return this; } @@ -899,14 +890,7 @@ public NewEngineInGroupFragmentBuilder shouldAttachEngineToActivity( } /** - * Whether or not this {@code FlutterFragment} should automatically receive {@link - * #onBackPressed()} events, rather than requiring an explicit activity call through. Disabled - * by default. - * - *

When enabled, the activity will automatically dispatch back-press events to the fragment's - * {@link OnBackPressedCallback}, instead of requiring the activity to manually call {@link - * #onBackPressed()} in client code. If enabled, do not invoke {@link #onBackPressed()} - * manually. + * Whether or not this {@code FlutterFragment} should automatically receive * *

This behavior relies on the implementation of {@link #popSystemNavigator()}. It's not * recommended to override that method when enabling this attribute, but if you do, you should @@ -916,7 +900,8 @@ public NewEngineInGroupFragmentBuilder shouldAttachEngineToActivity( @NonNull public NewEngineInGroupFragmentBuilder shouldAutomaticallyHandleOnBackPressed( boolean shouldAutomaticallyHandleOnBackPressed) { - this.shouldAutomaticallyHandleOnBackPressed = shouldAutomaticallyHandleOnBackPressed; + //this.shouldAutomaticallyHandleOnBackPressed = shouldAutomaticallyHandleOnBackPressed; + this.shouldAutomaticallyHandleOnBackPressed = false; return this; } @@ -999,6 +984,7 @@ public FlutterActivityAndFragmentDelegate createDelegate( return new FlutterActivityAndFragmentDelegate(host); } + /* private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(true) { @Override @@ -1007,6 +993,7 @@ public void handleOnBackPressed() { onBackPressed(); } }; + */ public FlutterFragment() { // Ensure that we at least have an empty Bundle of arguments so that we don't @@ -1046,7 +1033,10 @@ public void onAttach(@NonNull Context context) { delegate = delegateFactory.createDelegate(this); delegate.onAttach(context); if (getArguments().getBoolean(ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED, false)) { + /* + Log.v("justin", "onBackPressedDispatcher addCallback in FlutterFragment"); requireActivity().getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback); + */ } context.registerComponentCallbacks(this); } @@ -1197,8 +1187,8 @@ public void onNewIntent(@NonNull Intent intent) { *

If the fragment uses {@code shouldAutomaticallyHandleOnBackPressed(true)}, this method * should not be called through. It will be called automatically instead. * - *

See {@link android.app.Activity#onBackPressed()} */ + /* @ActivityCallThrough public void onBackPressed() { Log.v("justin", "onBackPressed in FlutterFragment (embedder)"); @@ -1206,6 +1196,7 @@ public void onBackPressed() { delegate.onBackPressed(); } } + */ /** * A result has been returned after an invocation of {@link @@ -1635,7 +1626,7 @@ public boolean shouldDispatchAppLifecycleState() { *

Avoid overriding this method when using {@code * shouldAutomaticallyHandleOnBackPressed(true)}. If you do, you must always {@code return * super.popSystemNavigator()} rather than {@code return false}. Otherwise the navigation behavior - * will recurse infinitely between this method and {@link #onBackPressed()}, breaking navigation. + * will recurse infinitely between this method and @link #onBackPressed()}, breaking navigation. */ @Override public boolean popSystemNavigator() { @@ -1645,10 +1636,12 @@ public boolean popSystemNavigator() { // Unless we disable the callback, the dispatcher call will trigger it. This will then // trigger the fragment's onBackPressed() implementation, which will call through to the // dart side and likely call back through to this method, creating an infinite call loop. + /* Log.v("justin", "changine enabled on onBackPressedCallback"); onBackPressedCallback.setEnabled(false); activity.getOnBackPressedDispatcher().onBackPressed(); onBackPressedCallback.setEnabled(true); + */ return true; } } diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java index 085a62f00c981..ab519594a239c 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java @@ -661,11 +661,13 @@ protected void onNewIntent(@NonNull Intent intent) { super.onNewIntent(intent); } + /* @Override public void onBackPressed() { Log.v("justin", "onBackPressed in FlutterFragmentActivity (embedder)"); flutterFragment.onBackPressed(); } + */ @Override public void onRequestPermissionsResult( diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 293bebf26b757..a45fd31af65ed 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -17,7 +17,7 @@ import android.view.View; import android.view.Window; import android.view.WindowManager; -import androidx.activity.OnBackPressedDispatcherOwner; +//import androidx.activity.OnBackPressedDispatcherOwner; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -481,12 +481,15 @@ private void popSystemNavigator() { return; } + /* if (activity instanceof OnBackPressedDispatcherOwner) { Log.v("justin", "calling onBackPressed in popSystemNavigator in PlatformPlugin"); ((OnBackPressedDispatcherOwner) activity).getOnBackPressedDispatcher().onBackPressed(); } else { activity.finish(); } + */ + activity.finish(); } private CharSequence getClipboardData(PlatformChannel.ClipboardContentFormat format) { From 75d8e3838824f62c0e475b7524580218e5a6e2a6 Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Fri, 27 Jan 2023 13:43:21 -0800 Subject: [PATCH 03/18] Undid all of the commenting and deleting and located the one call that blocks the root pback animation --- .../io/flutter/app/FlutterActivity.java | 4 +- .../flutter/app/FlutterActivityDelegate.java | 2 - .../io/flutter/app/FlutterActivityEvents.java | 2 - .../flutter/app/FlutterFragmentActivity.java | 4 +- .../embedding/android/FlutterActivity.java | 24 ++++----- .../FlutterActivityAndFragmentDelegate.java | 2 - .../embedding/android/FlutterFragment.java | 52 ++++++++++++------- .../android/FlutterFragmentActivity.java | 2 - .../plugin/platform/PlatformPlugin.java | 7 ++- 9 files changed, 48 insertions(+), 51 deletions(-) diff --git a/shell/platform/android/io/flutter/app/FlutterActivity.java b/shell/platform/android/io/flutter/app/FlutterActivity.java index 8af19bb59650f..9e3207baff55a 100644 --- a/shell/platform/android/io/flutter/app/FlutterActivity.java +++ b/shell/platform/android/io/flutter/app/FlutterActivity.java @@ -10,8 +10,8 @@ import android.content.res.Configuration; import android.os.Bundle; import androidx.annotation.NonNull; -import io.flutter.app.FlutterActivityDelegate.ViewFactory; import io.flutter.Log; +import io.flutter.app.FlutterActivityDelegate.ViewFactory; import io.flutter.plugin.common.PluginRegistry; import io.flutter.view.FlutterNativeView; import io.flutter.view.FlutterView; @@ -110,7 +110,6 @@ protected void onDestroy() { super.onDestroy(); } - /* @Override public void onBackPressed() { Log.v("justin", "onBackPressed in FlutterActivity"); @@ -118,7 +117,6 @@ public void onBackPressed() { super.onBackPressed(); } } - */ @Override protected void onStop() { diff --git a/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java b/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java index 61407afec363d..1787fa0f17e21 100644 --- a/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java +++ b/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java @@ -246,7 +246,6 @@ public void onDestroy() { } } - /* @Override public boolean onBackPressed() { Log.v("justin", "onBackPressed in FlutterActivityDelegate"); @@ -256,7 +255,6 @@ public boolean onBackPressed() { } return false; } - */ @Override public void onUserLeaveHint() { diff --git a/shell/platform/android/io/flutter/app/FlutterActivityEvents.java b/shell/platform/android/io/flutter/app/FlutterActivityEvents.java index 06c879086fd88..9340adb405394 100644 --- a/shell/platform/android/io/flutter/app/FlutterActivityEvents.java +++ b/shell/platform/android/io/flutter/app/FlutterActivityEvents.java @@ -60,9 +60,7 @@ public interface FlutterActivityEvents * continue with its default back button handling. * @see android.app.Activity#onBackPressed() */ - /* boolean onBackPressed(); - */ /** @see android.app.Activity#onUserLeaveHint() */ void onUserLeaveHint(); diff --git a/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java b/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java index a440e14344b0e..4aa7739bf7bbd 100644 --- a/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java +++ b/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java @@ -9,11 +9,11 @@ import android.content.res.Configuration; import android.os.Bundle; import androidx.fragment.app.FragmentActivity; +import io.flutter.Log; import io.flutter.app.FlutterActivityDelegate.ViewFactory; import io.flutter.plugin.common.PluginRegistry; import io.flutter.view.FlutterNativeView; import io.flutter.view.FlutterView; -import io.flutter.Log; /** * Deprecated class for activities that use Flutter who also require the use of the Android v4 @@ -100,7 +100,6 @@ protected void onDestroy() { super.onDestroy(); } - /* @Override public void onBackPressed() { Log.v("justin", "onBackPressed ok in FlutterFragmentActivity"); @@ -108,7 +107,6 @@ public void onBackPressed() { super.onBackPressed(); } } - */ @Override protected void onStart() { diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index af485b3e463e7..37d19400008c7 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -37,8 +37,8 @@ import android.view.View; import android.view.Window; import android.view.WindowManager; -//import android.window.OnBackInvokedCallback; -//import android.window.OnBackInvokedDispatcher; +import android.window.OnBackInvokedCallback; +import android.window.OnBackInvokedDispatcher; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -643,7 +643,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE); - //registerOnBackInvokedCallback(); + registerOnBackInvokedCallback(); configureWindowForTransparency(); @@ -662,16 +662,16 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { *

The callback must be unregistered in order to prevent unpredictable behavior once outside * the Flutter app. */ - /* @VisibleForTesting public void registerOnBackInvokedCallback() { if (Build.VERSION.SDK_INT >= 33) { + // TODO(justinmc): This is really the one and only thing that stops root + // pback for me. getOnBackInvokedDispatcher() .registerOnBackInvokedCallback( OnBackInvokedDispatcher.PRIORITY_DEFAULT, onBackInvokedCallback); } } - */ /** * Unregisters the callback from OnBackInvokedDispatcher. @@ -679,16 +679,13 @@ public void registerOnBackInvokedCallback() { *

This should be called when the activity is no longer in use to prevent unpredictable * behavior such as being stuck and unable to press back. */ - /* @VisibleForTesting public void unregisterOnBackInvokedCallback() { if (Build.VERSION.SDK_INT >= 33) { getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(onBackInvokedCallback); } } - */ - /* private final OnBackInvokedCallback onBackInvokedCallback = Build.VERSION.SDK_INT >= 33 ? new OnBackInvokedCallback() { @@ -698,12 +695,13 @@ public void unregisterOnBackInvokedCallback() { @SuppressWarnings("Override") @Override public void onBackInvoked() { - Log.v("justin", "calling onBackPressed in onBackInvokedCallback in FlutterActivity (embedder)"); + Log.v( + "justin", + "calling onBackPressed in onBackInvokedCallback in FlutterActivity (embedder)"); onBackPressed(); } } : null; - */ /** * Switches themes for this {@code Activity} from the theme used to launch this {@code Activity} @@ -885,7 +883,7 @@ protected void onSaveInstanceState(Bundle outState) { */ @VisibleForTesting public void release() { - //unregisterOnBackInvokedCallback(); + unregisterOnBackInvokedCallback(); if (delegate != null) { delegate.release(); delegate = null; @@ -934,7 +932,8 @@ protected void onNewIntent(@NonNull Intent intent) { } } - /* + // TODO(justinmc): Do I need to get rid of this? Or use it for old Android + // versions? Or it's just written by us and doesn't affect pback? @Override public void onBackPressed() { Log.v("justin", "onBackPressed in FlutterActivity (embedder)"); @@ -942,7 +941,6 @@ public void onBackPressed() { delegate.onBackPressed(); } } - */ @Override public void onRequestPermissionsResult( diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java index fde38d0c54c2e..939e7a150ce0e 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java @@ -777,7 +777,6 @@ void onDetach() { * *

This method instructs Flutter's navigation system to "pop route". */ -/* void onBackPressed() { Log.v("justin", "onBackPressed in FlutterFragmentAndFragmentDelegate"); ensureAlive(); @@ -788,7 +787,6 @@ void onBackPressed() { Log.w(TAG, "Invoked onBackPressed() before FlutterFragment was attached to an Activity."); } } - */ /** * Invoke this from {@link android.app.Activity#onRequestPermissionsResult(int, String[], int[])} diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java index 3194fa18b57c7..e54ec0183452a 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java @@ -12,7 +12,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -//import androidx.activity.OnBackPressedCallback; +import androidx.activity.OnBackPressedCallback; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -36,11 +36,14 @@ * *

    *
  1. {@link #onPostResume()} + *
  2. {@link #onBackPressed()} *
  3. {@link #onRequestPermissionsResult(int, String[], int[])} *
  4. {@link #onNewIntent(Intent)} *
  5. {@link #onUserLeaveHint()} *
* + * {@link #onBackPressed()} does not need to be called through if the fragment is constructed by one + * of the builders with {@code shouldAutomaticallyHandleOnBackPressed(true)}. * *

Additionally, when starting an {@code Activity} for a result from this {@code Fragment}, be * sure to invoke {@link Fragment#startActivityForResult(Intent, int)} rather than {@link @@ -158,6 +161,7 @@ public class FlutterFragment extends Fragment */ protected static final String ARG_ENABLE_STATE_RESTORATION = "enable_state_restoration"; /** + * True if the fragment should receive {@link #onBackPressed()} events automatically, without * requiring an explicit activity call through. */ protected static final String ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED = @@ -387,10 +391,13 @@ public NewEngineFragmentBuilder shouldAttachEngineToActivity( } /** - * Whether or not this {@code FlutterFragment} should automatically receive @link + * Whether or not this {@code FlutterFragment} should automatically receive {@link + * #onBackPressed()} events, rather than requiring an explicit activity call through. Disabled * by default. * *

When enabled, the activity will automatically dispatch back-press events to the fragment's + * {@link OnBackPressedCallback}, instead of requiring the activity to manually call {@link + * #onBackPressed()} in client code. If enabled, do not invoke {@link #onBackPressed()} * manually. * *

This behavior relies on the implementation of {@link #popSystemNavigator()}. It's not @@ -401,8 +408,7 @@ public NewEngineFragmentBuilder shouldAttachEngineToActivity( @NonNull public NewEngineFragmentBuilder shouldAutomaticallyHandleOnBackPressed( boolean shouldAutomaticallyHandleOnBackPressed) { - //this.shouldAutomaticallyHandleOnBackPressed = shouldAutomaticallyHandleOnBackPressed; - this.shouldAutomaticallyHandleOnBackPressed = false;//shouldAutomaticallyHandleOnBackPressed; + this.shouldAutomaticallyHandleOnBackPressed = shouldAutomaticallyHandleOnBackPressed; return this; } @@ -642,9 +648,13 @@ public CachedEngineFragmentBuilder shouldAttachEngineToActivity( } /** + * Whether or not this {@code FlutterFragment} should automatically receive {@link + * #onBackPressed()} events, rather than requiring an explicit activity call through. Disabled * by default. * *

When enabled, the activity will automatically dispatch back-press events to the fragment's + * {@link OnBackPressedCallback}, instead of requiring the activity to manually call {@link + * #onBackPressed()} in client code. If enabled, do not invoke {@link #onBackPressed()} * manually. * *

Enabling this behavior relies on explicit behavior in {@link #popSystemNavigator()}. It's @@ -655,8 +665,7 @@ public CachedEngineFragmentBuilder shouldAttachEngineToActivity( @NonNull public CachedEngineFragmentBuilder shouldAutomaticallyHandleOnBackPressed( boolean shouldAutomaticallyHandleOnBackPressed) { - //this.shouldAutomaticallyHandleOnBackPressed = shouldAutomaticallyHandleOnBackPressed; - this.shouldAutomaticallyHandleOnBackPressed = false;//shouldAutomaticallyHandleOnBackPressed; + this.shouldAutomaticallyHandleOnBackPressed = shouldAutomaticallyHandleOnBackPressed; return this; } @@ -890,7 +899,14 @@ public NewEngineInGroupFragmentBuilder shouldAttachEngineToActivity( } /** - * Whether or not this {@code FlutterFragment} should automatically receive + * Whether or not this {@code FlutterFragment} should automatically receive {@link + * #onBackPressed()} events, rather than requiring an explicit activity call through. Disabled + * by default. + * + *

When enabled, the activity will automatically dispatch back-press events to the fragment's + * {@link OnBackPressedCallback}, instead of requiring the activity to manually call {@link + * #onBackPressed()} in client code. If enabled, do not invoke {@link #onBackPressed()} + * manually. * *

This behavior relies on the implementation of {@link #popSystemNavigator()}. It's not * recommended to override that method when enabling this attribute, but if you do, you should @@ -900,8 +916,7 @@ public NewEngineInGroupFragmentBuilder shouldAttachEngineToActivity( @NonNull public NewEngineInGroupFragmentBuilder shouldAutomaticallyHandleOnBackPressed( boolean shouldAutomaticallyHandleOnBackPressed) { - //this.shouldAutomaticallyHandleOnBackPressed = shouldAutomaticallyHandleOnBackPressed; - this.shouldAutomaticallyHandleOnBackPressed = false; + this.shouldAutomaticallyHandleOnBackPressed = shouldAutomaticallyHandleOnBackPressed; return this; } @@ -984,16 +999,16 @@ public FlutterActivityAndFragmentDelegate createDelegate( return new FlutterActivityAndFragmentDelegate(host); } - /* private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(true) { @Override public void handleOnBackPressed() { - Log.v("justin", "calling onBackPressed in onBackPressedCallback in FlutterFragment (embedder)"); + Log.v( + "justin", + "calling onBackPressed in onBackPressedCallback in FlutterFragment (embedder)"); onBackPressed(); } }; - */ public FlutterFragment() { // Ensure that we at least have an empty Bundle of arguments so that we don't @@ -1033,10 +1048,10 @@ public void onAttach(@NonNull Context context) { delegate = delegateFactory.createDelegate(this); delegate.onAttach(context); if (getArguments().getBoolean(ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED, false)) { - /* - Log.v("justin", "onBackPressedDispatcher addCallback in FlutterFragment"); + // TODO(justinmc): This is highly suspicious, but it's not blocking the + // pback gesture. Maybe it's only in some cases. + Log.v("justin", "onAttach in FlutterFragment (embedding) adding a callback"); requireActivity().getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback); - */ } context.registerComponentCallbacks(this); } @@ -1187,8 +1202,8 @@ public void onNewIntent(@NonNull Intent intent) { *

If the fragment uses {@code shouldAutomaticallyHandleOnBackPressed(true)}, this method * should not be called through. It will be called automatically instead. * + *

See {@link android.app.Activity#onBackPressed()} */ - /* @ActivityCallThrough public void onBackPressed() { Log.v("justin", "onBackPressed in FlutterFragment (embedder)"); @@ -1196,7 +1211,6 @@ public void onBackPressed() { delegate.onBackPressed(); } } - */ /** * A result has been returned after an invocation of {@link @@ -1626,7 +1640,7 @@ public boolean shouldDispatchAppLifecycleState() { *

Avoid overriding this method when using {@code * shouldAutomaticallyHandleOnBackPressed(true)}. If you do, you must always {@code return * super.popSystemNavigator()} rather than {@code return false}. Otherwise the navigation behavior - * will recurse infinitely between this method and @link #onBackPressed()}, breaking navigation. + * will recurse infinitely between this method and {@link #onBackPressed()}, breaking navigation. */ @Override public boolean popSystemNavigator() { @@ -1636,12 +1650,10 @@ public boolean popSystemNavigator() { // Unless we disable the callback, the dispatcher call will trigger it. This will then // trigger the fragment's onBackPressed() implementation, which will call through to the // dart side and likely call back through to this method, creating an infinite call loop. - /* Log.v("justin", "changine enabled on onBackPressedCallback"); onBackPressedCallback.setEnabled(false); activity.getOnBackPressedDispatcher().onBackPressed(); onBackPressedCallback.setEnabled(true); - */ return true; } } diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java index ab519594a239c..085a62f00c981 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java @@ -661,13 +661,11 @@ protected void onNewIntent(@NonNull Intent intent) { super.onNewIntent(intent); } - /* @Override public void onBackPressed() { Log.v("justin", "onBackPressed in FlutterFragmentActivity (embedder)"); flutterFragment.onBackPressed(); } - */ @Override public void onRequestPermissionsResult( diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index a45fd31af65ed..56f7a82ea9d9f 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -17,7 +17,7 @@ import android.view.View; import android.view.Window; import android.view.WindowManager; -//import androidx.activity.OnBackPressedDispatcherOwner; +import androidx.activity.OnBackPressedDispatcherOwner; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -481,15 +481,14 @@ private void popSystemNavigator() { return; } - /* + // TODO(justinmc): This is another use of backpresseddispatcher that is not + // blocking the pback gesture for me. if (activity instanceof OnBackPressedDispatcherOwner) { Log.v("justin", "calling onBackPressed in popSystemNavigator in PlatformPlugin"); ((OnBackPressedDispatcherOwner) activity).getOnBackPressedDispatcher().onBackPressed(); } else { activity.finish(); } - */ - activity.finish(); } private CharSequence getClipboardData(PlatformChannel.ClipboardContentFormat format) { From e8a51302c35801077436bd2889189d476c91efc9 Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Fri, 27 Jan 2023 14:00:55 -0800 Subject: [PATCH 04/18] No logging verbose --- .../platform/android/io/flutter/app/FlutterActivity.java | 2 +- .../android/io/flutter/app/FlutterActivityDelegate.java | 2 +- .../android/io/flutter/app/FlutterFragmentActivity.java | 2 +- .../io/flutter/embedding/android/FlutterActivity.java | 5 +++-- .../android/FlutterActivityAndFragmentDelegate.java | 2 +- .../io/flutter/embedding/android/FlutterFragment.java | 8 ++++---- .../embedding/android/FlutterFragmentActivity.java | 2 +- .../io/flutter/plugin/platform/PlatformPlugin.java | 2 +- 8 files changed, 13 insertions(+), 12 deletions(-) diff --git a/shell/platform/android/io/flutter/app/FlutterActivity.java b/shell/platform/android/io/flutter/app/FlutterActivity.java index 9e3207baff55a..8d5d0cabdbddd 100644 --- a/shell/platform/android/io/flutter/app/FlutterActivity.java +++ b/shell/platform/android/io/flutter/app/FlutterActivity.java @@ -112,7 +112,7 @@ protected void onDestroy() { @Override public void onBackPressed() { - Log.v("justin", "onBackPressed in FlutterActivity"); + Log.e("justin", "onBackPressed in FlutterActivity"); if (!eventDelegate.onBackPressed()) { super.onBackPressed(); } diff --git a/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java b/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java index 1787fa0f17e21..033b7d863a687 100644 --- a/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java +++ b/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java @@ -248,7 +248,7 @@ public void onDestroy() { @Override public boolean onBackPressed() { - Log.v("justin", "onBackPressed in FlutterActivityDelegate"); + Log.e("justin", "onBackPressed in FlutterActivityDelegate"); if (flutterView != null) { flutterView.popRoute(); return true; diff --git a/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java b/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java index 4aa7739bf7bbd..bcbfa5ac8b623 100644 --- a/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java +++ b/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java @@ -102,7 +102,7 @@ protected void onDestroy() { @Override public void onBackPressed() { - Log.v("justin", "onBackPressed ok in FlutterFragmentActivity"); + Log.e("justin", "onBackPressed ok in FlutterFragmentActivity"); if (!eventDelegate.onBackPressed()) { super.onBackPressed(); } diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index 37d19400008c7..a94c266dde14b 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -667,6 +667,7 @@ public void registerOnBackInvokedCallback() { if (Build.VERSION.SDK_INT >= 33) { // TODO(justinmc): This is really the one and only thing that stops root // pback for me. + Log.e("justin", "registerOnBackInvokedCallback"); getOnBackInvokedDispatcher() .registerOnBackInvokedCallback( OnBackInvokedDispatcher.PRIORITY_DEFAULT, onBackInvokedCallback); @@ -695,7 +696,7 @@ public void unregisterOnBackInvokedCallback() { @SuppressWarnings("Override") @Override public void onBackInvoked() { - Log.v( + Log.e( "justin", "calling onBackPressed in onBackInvokedCallback in FlutterActivity (embedder)"); onBackPressed(); @@ -936,7 +937,7 @@ protected void onNewIntent(@NonNull Intent intent) { // versions? Or it's just written by us and doesn't affect pback? @Override public void onBackPressed() { - Log.v("justin", "onBackPressed in FlutterActivity (embedder)"); + Log.e("justin", "onBackPressed in FlutterActivity (embedder)"); if (stillAttachedForEvent("onBackPressed")) { delegate.onBackPressed(); } diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java index 939e7a150ce0e..bdbc974598112 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java @@ -778,7 +778,7 @@ void onDetach() { *

This method instructs Flutter's navigation system to "pop route". */ void onBackPressed() { - Log.v("justin", "onBackPressed in FlutterFragmentAndFragmentDelegate"); + Log.e("justin", "onBackPressed in FlutterFragmentAndFragmentDelegate"); ensureAlive(); if (flutterEngine != null) { Log.v(TAG, "Forwarding onBackPressed() to FlutterEngine."); diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java index e54ec0183452a..483b5ec0f52fe 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java @@ -1003,7 +1003,7 @@ public FlutterActivityAndFragmentDelegate createDelegate( new OnBackPressedCallback(true) { @Override public void handleOnBackPressed() { - Log.v( + Log.e( "justin", "calling onBackPressed in onBackPressedCallback in FlutterFragment (embedder)"); onBackPressed(); @@ -1050,7 +1050,7 @@ public void onAttach(@NonNull Context context) { if (getArguments().getBoolean(ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED, false)) { // TODO(justinmc): This is highly suspicious, but it's not blocking the // pback gesture. Maybe it's only in some cases. - Log.v("justin", "onAttach in FlutterFragment (embedding) adding a callback"); + Log.e("justin", "onAttach in FlutterFragment (embedding) adding a callback"); requireActivity().getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback); } context.registerComponentCallbacks(this); @@ -1206,7 +1206,7 @@ public void onNewIntent(@NonNull Intent intent) { */ @ActivityCallThrough public void onBackPressed() { - Log.v("justin", "onBackPressed in FlutterFragment (embedder)"); + Log.e("justin", "onBackPressed in FlutterFragment (embedder)"); if (stillAttachedForEvent("onBackPressed")) { delegate.onBackPressed(); } @@ -1650,7 +1650,7 @@ public boolean popSystemNavigator() { // Unless we disable the callback, the dispatcher call will trigger it. This will then // trigger the fragment's onBackPressed() implementation, which will call through to the // dart side and likely call back through to this method, creating an infinite call loop. - Log.v("justin", "changine enabled on onBackPressedCallback"); + Log.e("justin", "changine enabled on onBackPressedCallback"); onBackPressedCallback.setEnabled(false); activity.getOnBackPressedDispatcher().onBackPressed(); onBackPressedCallback.setEnabled(true); diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java index 085a62f00c981..531d5bf43fd24 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java @@ -663,7 +663,7 @@ protected void onNewIntent(@NonNull Intent intent) { @Override public void onBackPressed() { - Log.v("justin", "onBackPressed in FlutterFragmentActivity (embedder)"); + Log.e("justin", "onBackPressed in FlutterFragmentActivity (embedder)"); flutterFragment.onBackPressed(); } diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 56f7a82ea9d9f..6efd038d444f7 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -484,7 +484,7 @@ private void popSystemNavigator() { // TODO(justinmc): This is another use of backpresseddispatcher that is not // blocking the pback gesture for me. if (activity instanceof OnBackPressedDispatcherOwner) { - Log.v("justin", "calling onBackPressed in popSystemNavigator in PlatformPlugin"); + Log.e("justin", "calling onBackPressed in popSystemNavigator in PlatformPlugin"); ((OnBackPressedDispatcherOwner) activity).getOnBackPressedDispatcher().onBackPressed(); } else { activity.finish(); From 9c0e7ccbc12ba15e2b743c50a4b33f713fba954e Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Fri, 27 Jan 2023 16:22:12 -0800 Subject: [PATCH 05/18] WIP A platform channel API to declare that the nav stack is empty --- .../engine/systemchannels/PlatformChannel.java | 6 ++++++ .../flutter/plugin/platform/PlatformPlugin.java | 17 ++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index da08e499f1bb6..2b274b0128abb 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -136,6 +136,10 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result.error("error", exception.getMessage(), null); } break; + case "SystemNavigator.isEmpty": + platformMessageHandler.navigatorIsEmpty(); + result.success(null); + break; case "SystemNavigator.pop": platformMessageHandler.popSystemNavigator(); result.success(null); @@ -509,6 +513,8 @@ public interface PlatformMessageHandler { */ void setSystemUiOverlayStyle(@NonNull SystemChromeStyle systemUiOverlayStyle); + void navigatorIsEmpty(); + /** * The Flutter application would like to pop the top item off of the Android app's navigation * back stack. diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 6efd038d444f7..02b61cebdb6ff 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -109,6 +109,11 @@ public void setSystemUiOverlayStyle( setSystemChromeSystemUIOverlayStyle(systemUiOverlayStyle); } + @Override + public void navigatorIsEmpty() { + PlatformPlugin.this.navigatorIsEmpty(); + } + @Override public void popSystemNavigator() { PlatformPlugin.this.popSystemNavigator(); @@ -475,6 +480,12 @@ private void setSystemChromeSystemUIOverlayStyle( currentTheme = systemChromeStyle; } + private void navigatorIsEmpty() { + Log.e("justin", "navigatorIsEmpty in PlatformPlugin"); + // TODO(justinmc): Can't quite call it like this, need FlutterActivity. + // activity.unregisterOnBackInvokedCallback(); + } + private void popSystemNavigator() { if (platformPluginDelegate != null && platformPluginDelegate.popSystemNavigator()) { // A custom behavior was executed by the delegate. Don't execute default behavior. @@ -482,11 +493,15 @@ private void popSystemNavigator() { } // TODO(justinmc): This is another use of backpresseddispatcher that is not - // blocking the pback gesture for me. + // blocking the pback gesture for me. It seems like this if is false, so the + // app exits here. if (activity instanceof OnBackPressedDispatcherOwner) { Log.e("justin", "calling onBackPressed in popSystemNavigator in PlatformPlugin"); ((OnBackPressedDispatcherOwner) activity).getOnBackPressedDispatcher().onBackPressed(); } else { + Log.e( + "justin", + "popSystemNavigator in PlatformPlugin finishing the activity because it's not an OnBackPressedDispatcherOwner"); activity.finish(); } } From 205d1e53397591594e400b79e16280d62b84f922 Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Wed, 1 Feb 2023 11:41:06 -0800 Subject: [PATCH 06/18] navigationStackIsEmpty method to enable predictive back --- .../io/flutter/embedding/android/FlutterActivity.java | 9 ++++++++- .../io/flutter/embedding/android/FlutterFragment.java | 7 +++++++ .../io/flutter/plugin/platform/PlatformPlugin.java | 6 ++++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index a94c266dde14b..ebf92d77d2168 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -666,7 +666,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { public void registerOnBackInvokedCallback() { if (Build.VERSION.SDK_INT >= 33) { // TODO(justinmc): This is really the one and only thing that stops root - // pback for me. + // pback for me. There are probably other places you need to mess with + // this for other embedding strategies! Log.e("justin", "registerOnBackInvokedCallback"); getOnBackInvokedDispatcher() .registerOnBackInvokedCallback( @@ -674,6 +675,12 @@ public void registerOnBackInvokedCallback() { } } + @Override + public void navigatorIsEmpty() { + Log.e("justin", "navigatorIsEmpty in embedding FlutterActivity"); + unregisterOnBackInvokedCallback(); + } + /** * Unregisters the callback from OnBackInvokedDispatcher. * diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java index 483b5ec0f52fe..ad581197802a9 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java @@ -1661,6 +1661,13 @@ public boolean popSystemNavigator() { return false; } + @Override + public void navigatorIsEmpty() { + // TODO(justinmc): Implement. Implementing in FlutterActivity first. + // unregisterOnBackInvokedCallback(); + Log.e("justin", "navigatorIsEmpty in embedding FlutterFragment"); + } + @VisibleForTesting @NonNull boolean shouldDelayFirstAndroidViewDraw() { diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 02b61cebdb6ff..a2eec420e2325 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -56,6 +56,8 @@ public interface PlatformPluginDelegate { * androidx.activity.OnBackPressedDispatcher} will be executed. */ boolean popSystemNavigator(); + + void navigatorIsEmpty(); } @VisibleForTesting @@ -111,6 +113,7 @@ public void setSystemUiOverlayStyle( @Override public void navigatorIsEmpty() { + Log.e("justin", "navigatorIsEmpty in PlatformHandler.PlatformMessageChannel."); PlatformPlugin.this.navigatorIsEmpty(); } @@ -482,8 +485,7 @@ private void setSystemChromeSystemUIOverlayStyle( private void navigatorIsEmpty() { Log.e("justin", "navigatorIsEmpty in PlatformPlugin"); - // TODO(justinmc): Can't quite call it like this, need FlutterActivity. - // activity.unregisterOnBackInvokedCallback(); + platformPluginDelegate.navigatorIsEmpty(); } private void popSystemNavigator() { From 66d1f846f28673ef05dcff3427110a462fec871a Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Thu, 9 Feb 2023 10:57:35 -0800 Subject: [PATCH 07/18] Migrate to updateNavigationStackStatus, works for inner routes --- .../embedding/android/FlutterActivity.java | 21 ++++++++++++++----- .../embedding/android/FlutterFragment.java | 4 ++-- .../systemchannels/PlatformChannel.java | 13 +++++++----- .../plugin/platform/PlatformPlugin.java | 14 ++++++------- 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index ebf92d77d2168..bb85029437106 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -217,6 +217,8 @@ public class FlutterActivity extends Activity implements FlutterActivityAndFragmentDelegate.Host, LifecycleOwner { private static final String TAG = "FlutterActivity"; + private boolean hasRegisteredCallback = false; + /** * The ID of the {@code FlutterView} created by this activity. * @@ -643,8 +645,6 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE); - registerOnBackInvokedCallback(); - configureWindowForTransparency(); setContentView(createFlutterView()); @@ -672,13 +672,23 @@ public void registerOnBackInvokedCallback() { getOnBackInvokedDispatcher() .registerOnBackInvokedCallback( OnBackInvokedDispatcher.PRIORITY_DEFAULT, onBackInvokedCallback); + hasRegisteredCallback = true; } } @Override - public void navigatorIsEmpty() { - Log.e("justin", "navigatorIsEmpty in embedding FlutterActivity"); - unregisterOnBackInvokedCallback(); + public void updateNavigationStackStatus(boolean hasMultiple) { + Log.e( + "justin", + "updateNavigationStackStatus in embedding FlutterActivity. hasMultiple: " + + Boolean.toString(hasMultiple) + + " hasRegisteredCallback: " + + Boolean.toString(hasRegisteredCallback)); + if (hasMultiple && !hasRegisteredCallback) { + registerOnBackInvokedCallback(); + } else if (!hasMultiple && hasRegisteredCallback) { + unregisterOnBackInvokedCallback(); + } } /** @@ -691,6 +701,7 @@ public void navigatorIsEmpty() { public void unregisterOnBackInvokedCallback() { if (Build.VERSION.SDK_INT >= 33) { getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(onBackInvokedCallback); + hasRegisteredCallback = false; } } diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java index ad581197802a9..1d694c72b696b 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java @@ -1662,10 +1662,10 @@ public boolean popSystemNavigator() { } @Override - public void navigatorIsEmpty() { + public void updateNavigationStackStatus(boolean hasMultiple) { // TODO(justinmc): Implement. Implementing in FlutterActivity first. // unregisterOnBackInvokedCallback(); - Log.e("justin", "navigatorIsEmpty in embedding FlutterFragment"); + Log.e("justin", "updateNavigationStackStatus in embedding FlutterFragment"); } @VisibleForTesting diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index 2b274b0128abb..80440464d15cb 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -136,10 +136,13 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result.error("error", exception.getMessage(), null); } break; - case "SystemNavigator.isEmpty": - platformMessageHandler.navigatorIsEmpty(); - result.success(null); - break; + case "SystemNavigator.updateNavigationStackStatus": + { + boolean hasMultiple = (boolean) arguments; + platformMessageHandler.updateNavigationStackStatus(hasMultiple); + result.success(null); + break; + } case "SystemNavigator.pop": platformMessageHandler.popSystemNavigator(); result.success(null); @@ -513,7 +516,7 @@ public interface PlatformMessageHandler { */ void setSystemUiOverlayStyle(@NonNull SystemChromeStyle systemUiOverlayStyle); - void navigatorIsEmpty(); + void updateNavigationStackStatus(boolean hasMultiple); /** * The Flutter application would like to pop the top item off of the Android app's navigation diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index a2eec420e2325..4d83421c8d59f 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -57,7 +57,7 @@ public interface PlatformPluginDelegate { */ boolean popSystemNavigator(); - void navigatorIsEmpty(); + void updateNavigationStackStatus(boolean hasMultiple); } @VisibleForTesting @@ -112,9 +112,9 @@ public void setSystemUiOverlayStyle( } @Override - public void navigatorIsEmpty() { - Log.e("justin", "navigatorIsEmpty in PlatformHandler.PlatformMessageChannel."); - PlatformPlugin.this.navigatorIsEmpty(); + public void updateNavigationStackStatus(boolean hasMultiple) { + Log.e("justin", "updateNavigationStackStatus in PlatformHandler.PlatformMessageChannel."); + PlatformPlugin.this.updateNavigationStackStatus(hasMultiple); } @Override @@ -483,9 +483,9 @@ private void setSystemChromeSystemUIOverlayStyle( currentTheme = systemChromeStyle; } - private void navigatorIsEmpty() { - Log.e("justin", "navigatorIsEmpty in PlatformPlugin"); - platformPluginDelegate.navigatorIsEmpty(); + private void updateNavigationStackStatus(boolean hasMultiple) { + Log.e("justin", "updateNavigationStackStatus in PlatformPlugin"); + platformPluginDelegate.updateNavigationStackStatus(hasMultiple); } private void popSystemNavigator() { From 9e8e230bf8c626c67de8ebdd7423eef67f7e19d6 Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Thu, 9 Feb 2023 11:48:29 -0800 Subject: [PATCH 08/18] Clean up logs and todos --- .../io/flutter/app/FlutterActivity.java | 2 - .../flutter/app/FlutterActivityDelegate.java | 1 - .../flutter/app/FlutterFragmentActivity.java | 2 - .../embedding/android/FlutterActivity.java | 39 ++++++++----------- .../FlutterActivityAndFragmentDelegate.java | 1 - .../embedding/android/FlutterFragment.java | 13 ++----- .../android/FlutterFragmentActivity.java | 1 - .../systemchannels/PlatformChannel.java | 1 + .../plugin/platform/PlatformPlugin.java | 10 +---- 9 files changed, 23 insertions(+), 47 deletions(-) diff --git a/shell/platform/android/io/flutter/app/FlutterActivity.java b/shell/platform/android/io/flutter/app/FlutterActivity.java index 8d5d0cabdbddd..a28176b0f799b 100644 --- a/shell/platform/android/io/flutter/app/FlutterActivity.java +++ b/shell/platform/android/io/flutter/app/FlutterActivity.java @@ -10,7 +10,6 @@ import android.content.res.Configuration; import android.os.Bundle; import androidx.annotation.NonNull; -import io.flutter.Log; import io.flutter.app.FlutterActivityDelegate.ViewFactory; import io.flutter.plugin.common.PluginRegistry; import io.flutter.view.FlutterNativeView; @@ -112,7 +111,6 @@ protected void onDestroy() { @Override public void onBackPressed() { - Log.e("justin", "onBackPressed in FlutterActivity"); if (!eventDelegate.onBackPressed()) { super.onBackPressed(); } diff --git a/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java b/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java index 033b7d863a687..21a9443228156 100644 --- a/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java +++ b/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java @@ -248,7 +248,6 @@ public void onDestroy() { @Override public boolean onBackPressed() { - Log.e("justin", "onBackPressed in FlutterActivityDelegate"); if (flutterView != null) { flutterView.popRoute(); return true; diff --git a/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java b/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java index bcbfa5ac8b623..bf8935e8bb161 100644 --- a/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java +++ b/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java @@ -9,7 +9,6 @@ import android.content.res.Configuration; import android.os.Bundle; import androidx.fragment.app.FragmentActivity; -import io.flutter.Log; import io.flutter.app.FlutterActivityDelegate.ViewFactory; import io.flutter.plugin.common.PluginRegistry; import io.flutter.view.FlutterNativeView; @@ -102,7 +101,6 @@ protected void onDestroy() { @Override public void onBackPressed() { - Log.e("justin", "onBackPressed ok in FlutterFragmentActivity"); if (!eventDelegate.onBackPressed()) { super.onBackPressed(); } diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index bb85029437106..73a69904aeed1 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -665,10 +665,6 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { @VisibleForTesting public void registerOnBackInvokedCallback() { if (Build.VERSION.SDK_INT >= 33) { - // TODO(justinmc): This is really the one and only thing that stops root - // pback for me. There are probably other places you need to mess with - // this for other embedding strategies! - Log.e("justin", "registerOnBackInvokedCallback"); getOnBackInvokedDispatcher() .registerOnBackInvokedCallback( OnBackInvokedDispatcher.PRIORITY_DEFAULT, onBackInvokedCallback); @@ -676,21 +672,6 @@ public void registerOnBackInvokedCallback() { } } - @Override - public void updateNavigationStackStatus(boolean hasMultiple) { - Log.e( - "justin", - "updateNavigationStackStatus in embedding FlutterActivity. hasMultiple: " - + Boolean.toString(hasMultiple) - + " hasRegisteredCallback: " - + Boolean.toString(hasRegisteredCallback)); - if (hasMultiple && !hasRegisteredCallback) { - registerOnBackInvokedCallback(); - } else if (!hasMultiple && hasRegisteredCallback) { - unregisterOnBackInvokedCallback(); - } - } - /** * Unregisters the callback from OnBackInvokedDispatcher. * @@ -722,6 +703,23 @@ public void onBackInvoked() { } : null; + // TODO(justinmc): Do the same thing in other embedding strategies (justin FlutterFragment? + // FlutterFragmentActivity?). + @Override + public void updateNavigationStackStatus(boolean hasMultiple) { + Log.e( + "justin", + "updateNavigationStackStatus in embedding FlutterActivity. hasMultiple: " + + Boolean.toString(hasMultiple) + + " hasRegisteredCallback: " + + Boolean.toString(hasRegisteredCallback)); + if (hasMultiple && !hasRegisteredCallback) { + registerOnBackInvokedCallback(); + } else if (!hasMultiple && hasRegisteredCallback) { + unregisterOnBackInvokedCallback(); + } + } + /** * Switches themes for this {@code Activity} from the theme used to launch this {@code Activity} * to a "normal theme" that is intended for regular {@code Activity} operation. @@ -951,11 +949,8 @@ protected void onNewIntent(@NonNull Intent intent) { } } - // TODO(justinmc): Do I need to get rid of this? Or use it for old Android - // versions? Or it's just written by us and doesn't affect pback? @Override public void onBackPressed() { - Log.e("justin", "onBackPressed in FlutterActivity (embedder)"); if (stillAttachedForEvent("onBackPressed")) { delegate.onBackPressed(); } diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java index bdbc974598112..56db871f1ef72 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java @@ -778,7 +778,6 @@ void onDetach() { *

This method instructs Flutter's navigation system to "pop route". */ void onBackPressed() { - Log.e("justin", "onBackPressed in FlutterFragmentAndFragmentDelegate"); ensureAlive(); if (flutterEngine != null) { Log.v(TAG, "Forwarding onBackPressed() to FlutterEngine."); diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java index 1d694c72b696b..2a52adb339239 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java @@ -1003,9 +1003,6 @@ public FlutterActivityAndFragmentDelegate createDelegate( new OnBackPressedCallback(true) { @Override public void handleOnBackPressed() { - Log.e( - "justin", - "calling onBackPressed in onBackPressedCallback in FlutterFragment (embedder)"); onBackPressed(); } }; @@ -1047,10 +1044,11 @@ public void onAttach(@NonNull Context context) { super.onAttach(context); delegate = delegateFactory.createDelegate(this); delegate.onAttach(context); + // TODO(justinmc): What is ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED? + // In order to follow what this PR did in FlutterActivity, this should + // be removed and only add a callback when the framework sends the message. + static void intercept(args) { } if (getArguments().getBoolean(ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED, false)) { - // TODO(justinmc): This is highly suspicious, but it's not blocking the - // pback gesture. Maybe it's only in some cases. - Log.e("justin", "onAttach in FlutterFragment (embedding) adding a callback"); requireActivity().getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback); } context.registerComponentCallbacks(this); @@ -1206,7 +1204,6 @@ public void onNewIntent(@NonNull Intent intent) { */ @ActivityCallThrough public void onBackPressed() { - Log.e("justin", "onBackPressed in FlutterFragment (embedder)"); if (stillAttachedForEvent("onBackPressed")) { delegate.onBackPressed(); } @@ -1650,7 +1647,6 @@ public boolean popSystemNavigator() { // Unless we disable the callback, the dispatcher call will trigger it. This will then // trigger the fragment's onBackPressed() implementation, which will call through to the // dart side and likely call back through to this method, creating an infinite call loop. - Log.e("justin", "changine enabled on onBackPressedCallback"); onBackPressedCallback.setEnabled(false); activity.getOnBackPressedDispatcher().onBackPressed(); onBackPressedCallback.setEnabled(true); @@ -1665,7 +1661,6 @@ public boolean popSystemNavigator() { public void updateNavigationStackStatus(boolean hasMultiple) { // TODO(justinmc): Implement. Implementing in FlutterActivity first. // unregisterOnBackInvokedCallback(); - Log.e("justin", "updateNavigationStackStatus in embedding FlutterFragment"); } @VisibleForTesting diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java index 531d5bf43fd24..d5e7fcad325df 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java @@ -663,7 +663,6 @@ protected void onNewIntent(@NonNull Intent intent) { @Override public void onBackPressed() { - Log.e("justin", "onBackPressed in FlutterFragmentActivity (embedder)"); flutterFragment.onBackPressed(); } diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index 80440464d15cb..0838f811aeda6 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -136,6 +136,7 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result.error("error", exception.getMessage(), null); } break; + // TODO(justinmc): Potentially rename this. case "SystemNavigator.updateNavigationStackStatus": { boolean hasMultiple = (boolean) arguments; diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 4d83421c8d59f..19f0181afd6cb 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -113,7 +113,6 @@ public void setSystemUiOverlayStyle( @Override public void updateNavigationStackStatus(boolean hasMultiple) { - Log.e("justin", "updateNavigationStackStatus in PlatformHandler.PlatformMessageChannel."); PlatformPlugin.this.updateNavigationStackStatus(hasMultiple); } @@ -484,7 +483,6 @@ private void setSystemChromeSystemUIOverlayStyle( } private void updateNavigationStackStatus(boolean hasMultiple) { - Log.e("justin", "updateNavigationStackStatus in PlatformPlugin"); platformPluginDelegate.updateNavigationStackStatus(hasMultiple); } @@ -494,16 +492,10 @@ private void popSystemNavigator() { return; } - // TODO(justinmc): This is another use of backpresseddispatcher that is not - // blocking the pback gesture for me. It seems like this if is false, so the - // app exits here. + // TODO(justinmc): Will this ever interfer with predictive back? if (activity instanceof OnBackPressedDispatcherOwner) { - Log.e("justin", "calling onBackPressed in popSystemNavigator in PlatformPlugin"); ((OnBackPressedDispatcherOwner) activity).getOnBackPressedDispatcher().onBackPressed(); } else { - Log.e( - "justin", - "popSystemNavigator in PlatformPlugin finishing the activity because it's not an OnBackPressedDispatcherOwner"); activity.finish(); } } From 0ed2becdb5ec3865580f442bfa439aa7da627796 Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Tue, 7 Mar 2023 13:52:30 -0800 Subject: [PATCH 09/18] Rename hasMultiple to frameworkHandlesPop for clarity --- .../flutter/embedding/android/FlutterActivity.java | 12 +++--------- .../flutter/embedding/android/FlutterFragment.java | 1 - .../engine/systemchannels/PlatformChannel.java | 10 +++++++--- .../io/flutter/plugin/platform/PlatformPlugin.java | 10 +++++----- 4 files changed, 15 insertions(+), 18 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index 73a69904aeed1..3d5cc3807d916 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -706,16 +706,10 @@ public void onBackInvoked() { // TODO(justinmc): Do the same thing in other embedding strategies (justin FlutterFragment? // FlutterFragmentActivity?). @Override - public void updateNavigationStackStatus(boolean hasMultiple) { - Log.e( - "justin", - "updateNavigationStackStatus in embedding FlutterActivity. hasMultiple: " - + Boolean.toString(hasMultiple) - + " hasRegisteredCallback: " - + Boolean.toString(hasRegisteredCallback)); - if (hasMultiple && !hasRegisteredCallback) { + public void updateNavigationStackStatus(boolean frameworkHandlesPop) { + if (frameworkHandlesPop && !hasRegisteredCallback) { registerOnBackInvokedCallback(); - } else if (!hasMultiple && hasRegisteredCallback) { + } else if (!frameworkHandlesPop && hasRegisteredCallback) { unregisterOnBackInvokedCallback(); } } diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java index 2a52adb339239..073e0bed74a7a 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java @@ -1047,7 +1047,6 @@ public void onAttach(@NonNull Context context) { // TODO(justinmc): What is ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED? // In order to follow what this PR did in FlutterActivity, this should // be removed and only add a callback when the framework sends the message. - static void intercept(args) { } if (getArguments().getBoolean(ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED, false)) { requireActivity().getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback); } diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index 0838f811aeda6..7159f90609120 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -139,8 +139,8 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result // TODO(justinmc): Potentially rename this. case "SystemNavigator.updateNavigationStackStatus": { - boolean hasMultiple = (boolean) arguments; - platformMessageHandler.updateNavigationStackStatus(hasMultiple); + boolean frameworkHandlesPop = (boolean) arguments; + platformMessageHandler.updateNavigationStackStatus(frameworkHandlesPop); result.success(null); break; } @@ -517,7 +517,11 @@ public interface PlatformMessageHandler { */ void setSystemUiOverlayStyle(@NonNull SystemChromeStyle systemUiOverlayStyle); - void updateNavigationStackStatus(boolean hasMultiple); + /** + * The Flutter application would or would not like to handle navigation pop + * events itself. + */ + void updateNavigationStackStatus(boolean frameworkHandlesPop); /** * The Flutter application would like to pop the top item off of the Android app's navigation diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 19f0181afd6cb..bf88ef7da9946 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -57,7 +57,7 @@ public interface PlatformPluginDelegate { */ boolean popSystemNavigator(); - void updateNavigationStackStatus(boolean hasMultiple); + void updateNavigationStackStatus(boolean frameworkHandlesPop); } @VisibleForTesting @@ -112,8 +112,8 @@ public void setSystemUiOverlayStyle( } @Override - public void updateNavigationStackStatus(boolean hasMultiple) { - PlatformPlugin.this.updateNavigationStackStatus(hasMultiple); + public void updateNavigationStackStatus(boolean frameworkHandlesPop) { + PlatformPlugin.this.updateNavigationStackStatus(frameworkHandlesPop); } @Override @@ -482,8 +482,8 @@ private void setSystemChromeSystemUIOverlayStyle( currentTheme = systemChromeStyle; } - private void updateNavigationStackStatus(boolean hasMultiple) { - platformPluginDelegate.updateNavigationStackStatus(hasMultiple); + private void updateNavigationStackStatus(boolean frameworkHandlesPop) { + platformPluginDelegate.updateNavigationStackStatus(frameworkHandlesPop); } private void popSystemNavigator() { From 8aeba572c457fab03d412c682dfce7891e70fc42 Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Tue, 7 Mar 2023 15:33:40 -0800 Subject: [PATCH 10/18] Analyzer fix --- .../embedding/engine/systemchannels/PlatformChannel.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index 7159f90609120..c6f29f5f17ac9 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -517,10 +517,7 @@ public interface PlatformMessageHandler { */ void setSystemUiOverlayStyle(@NonNull SystemChromeStyle systemUiOverlayStyle); - /** - * The Flutter application would or would not like to handle navigation pop - * events itself. - */ + /** The Flutter application would or would not like to handle navigation pop events itself. */ void updateNavigationStackStatus(boolean frameworkHandlesPop); /** From 5e89211658c03a59d5853209a23ffc90b216b1f6 Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Fri, 7 Apr 2023 10:46:26 -0700 Subject: [PATCH 11/18] WIP some debugging --- .../android/io/flutter/embedding/android/FlutterActivity.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index 3d5cc3807d916..3e4f1bb51b02a 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -664,6 +664,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { */ @VisibleForTesting public void registerOnBackInvokedCallback() { + // TODO(justinmc): Make sure this still works as before on older Android + // devices. Not sure if I'm still listening to backs somewhere. if (Build.VERSION.SDK_INT >= 33) { getOnBackInvokedDispatcher() .registerOnBackInvokedCallback( @@ -708,8 +710,10 @@ public void onBackInvoked() { @Override public void updateNavigationStackStatus(boolean frameworkHandlesPop) { if (frameworkHandlesPop && !hasRegisteredCallback) { + Log.e("justin", "Stopping predictive back"); registerOnBackInvokedCallback(); } else if (!frameworkHandlesPop && hasRegisteredCallback) { + Log.e("justin", "Enabling predictive back"); unregisterOnBackInvokedCallback(); } } From 6bc7d5ed6a23064bc71337d7e43178c994579b17 Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Fri, 26 May 2023 15:19:50 -0700 Subject: [PATCH 12/18] Rename to frameworkHandlesBacks --- .../io/flutter/embedding/android/FlutterActivity.java | 8 ++++---- .../io/flutter/embedding/android/FlutterFragment.java | 2 +- .../engine/systemchannels/PlatformChannel.java | 9 ++++----- .../io/flutter/plugin/platform/PlatformPlugin.java | 10 +++++----- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index 671a5875d01b4..d4be501d5e33f 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -705,14 +705,14 @@ public void onBackInvoked() { } : null; - // TODO(justinmc): Do the same thing in other embedding strategies (justin FlutterFragment? + // TODO(justinmc): Do the same thing in other embedding strategies (just FlutterFragment? // FlutterFragmentActivity?). @Override - public void updateNavigationStackStatus(boolean frameworkHandlesPop) { - if (frameworkHandlesPop && !hasRegisteredCallback) { + public void setFrameworkHandlesBacks(boolean frameworkHandlesBacks) { + if (frameworkHandlesBacks && !hasRegisteredCallback) { Log.e("justin", "Stopping predictive back"); registerOnBackInvokedCallback(); - } else if (!frameworkHandlesPop && hasRegisteredCallback) { + } else if (!frameworkHandlesBacks && hasRegisteredCallback) { Log.e("justin", "Enabling predictive back"); unregisterOnBackInvokedCallback(); } diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java index 4bca486b001c1..6948bbdad001e 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java @@ -1687,7 +1687,7 @@ public boolean popSystemNavigator() { } @Override - public void updateNavigationStackStatus(boolean hasMultiple) { + public void setFrameworkHandlesBacks(boolean frameworkHandlesBacks) { // TODO(justinmc): Implement. Implementing in FlutterActivity first. // unregisterOnBackInvokedCallback(); } diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index c6f29f5f17ac9..003181ba75f43 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -136,11 +136,10 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result.error("error", exception.getMessage(), null); } break; - // TODO(justinmc): Potentially rename this. - case "SystemNavigator.updateNavigationStackStatus": + case "SystemNavigator.setFrameworkHandlesBacks": { - boolean frameworkHandlesPop = (boolean) arguments; - platformMessageHandler.updateNavigationStackStatus(frameworkHandlesPop); + boolean frameworkHandlesBacks = (boolean) arguments; + platformMessageHandler.setFrameworkHandlesBacks(frameworkHandlesBacks); result.success(null); break; } @@ -518,7 +517,7 @@ public interface PlatformMessageHandler { void setSystemUiOverlayStyle(@NonNull SystemChromeStyle systemUiOverlayStyle); /** The Flutter application would or would not like to handle navigation pop events itself. */ - void updateNavigationStackStatus(boolean frameworkHandlesPop); + void setFrameworkHandlesBacks(boolean frameworkHandlesPop); /** * The Flutter application would like to pop the top item off of the Android app's navigation diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index bf88ef7da9946..a01ef3c7ae636 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -57,7 +57,7 @@ public interface PlatformPluginDelegate { */ boolean popSystemNavigator(); - void updateNavigationStackStatus(boolean frameworkHandlesPop); + void setFrameworkHandlesBacks(boolean frameworkHandlesBacks); } @VisibleForTesting @@ -112,8 +112,8 @@ public void setSystemUiOverlayStyle( } @Override - public void updateNavigationStackStatus(boolean frameworkHandlesPop) { - PlatformPlugin.this.updateNavigationStackStatus(frameworkHandlesPop); + public void setFrameworkHandlesBacks(boolean frameworkHandlesBacks) { + PlatformPlugin.this.setFrameworkHandlesBacks(frameworkHandlesBacks); } @Override @@ -482,8 +482,8 @@ private void setSystemChromeSystemUIOverlayStyle( currentTheme = systemChromeStyle; } - private void updateNavigationStackStatus(boolean frameworkHandlesPop) { - platformPluginDelegate.updateNavigationStackStatus(frameworkHandlesPop); + private void setFrameworkHandlesBacks(boolean frameworkHandlesBacks) { + platformPluginDelegate.setFrameworkHandlesBacks(frameworkHandlesBacks); } private void popSystemNavigator() { From 01a22a235c219c2816ee077cf5ef7cfe78be5ceb Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Fri, 26 May 2023 16:03:23 -0700 Subject: [PATCH 13/18] Clean up --- .../io/flutter/embedding/android/FlutterActivity.java | 5 ----- .../android/io/flutter/plugin/platform/PlatformPlugin.java | 1 - 2 files changed, 6 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index d4be501d5e33f..e2f951e32d0d4 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -697,9 +697,6 @@ public void unregisterOnBackInvokedCallback() { @SuppressWarnings("Override") @Override public void onBackInvoked() { - Log.e( - "justin", - "calling onBackPressed in onBackInvokedCallback in FlutterActivity (embedder)"); onBackPressed(); } } @@ -710,10 +707,8 @@ public void onBackInvoked() { @Override public void setFrameworkHandlesBacks(boolean frameworkHandlesBacks) { if (frameworkHandlesBacks && !hasRegisteredCallback) { - Log.e("justin", "Stopping predictive back"); registerOnBackInvokedCallback(); } else if (!frameworkHandlesBacks && hasRegisteredCallback) { - Log.e("justin", "Enabling predictive back"); unregisterOnBackInvokedCallback(); } } diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index a01ef3c7ae636..219fc1ee3dfc5 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -492,7 +492,6 @@ private void popSystemNavigator() { return; } - // TODO(justinmc): Will this ever interfer with predictive back? if (activity instanceof OnBackPressedDispatcherOwner) { ((OnBackPressedDispatcherOwner) activity).getOnBackPressedDispatcher().onBackPressed(); } else { From 6f220092e13b39cd750b6f68057f5516386b35a9 Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Fri, 26 May 2023 16:32:12 -0700 Subject: [PATCH 14/18] Confirmed that it works on my old (API 24) samsung device --- .../android/io/flutter/embedding/android/FlutterActivity.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index e2f951e32d0d4..d4808bebc66e0 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -664,8 +664,6 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { */ @VisibleForTesting public void registerOnBackInvokedCallback() { - // TODO(justinmc): Make sure this still works as before on older Android - // devices. Not sure if I'm still listening to backs somewhere. if (Build.VERSION.SDK_INT >= 33) { getOnBackInvokedDispatcher() .registerOnBackInvokedCallback( From 440a6ee66bbc8ee2b5adfca1aa9a063b13d49784 Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Tue, 30 May 2023 13:25:33 -0700 Subject: [PATCH 15/18] I dont think I need to modify flutterfragment(activity) --- .../io/flutter/embedding/android/FlutterActivity.java | 2 -- .../io/flutter/embedding/android/FlutterFragment.java | 9 --------- 2 files changed, 11 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index d4808bebc66e0..95b448fc7dd9b 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -700,8 +700,6 @@ public void onBackInvoked() { } : null; - // TODO(justinmc): Do the same thing in other embedding strategies (just FlutterFragment? - // FlutterFragmentActivity?). @Override public void setFrameworkHandlesBacks(boolean frameworkHandlesBacks) { if (frameworkHandlesBacks && !hasRegisteredCallback) { diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java index 6948bbdad001e..85ce3ade38fb0 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java @@ -1060,9 +1060,6 @@ public void onAttach(@NonNull Context context) { super.onAttach(context); delegate = delegateFactory.createDelegate(this); delegate.onAttach(context); - // TODO(justinmc): What is ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED? - // In order to follow what this PR did in FlutterActivity, this should - // be removed and only add a callback when the framework sends the message. if (getArguments().getBoolean(ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED, false)) { requireActivity().getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback); } @@ -1686,12 +1683,6 @@ public boolean popSystemNavigator() { return false; } - @Override - public void setFrameworkHandlesBacks(boolean frameworkHandlesBacks) { - // TODO(justinmc): Implement. Implementing in FlutterActivity first. - // unregisterOnBackInvokedCallback(); - } - @VisibleForTesting @NonNull boolean shouldDelayFirstAndroidViewDraw() { From e075275da3a00001775e37b0495211e878e42d93 Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Fri, 2 Jun 2023 15:44:44 -0700 Subject: [PATCH 16/18] Tests and empty implementation for FlutterFragment --- .../flutter/embedding/android/FlutterFragment.java | 5 +++++ .../embedding/android/FlutterActivityTest.java | 8 +++++++- .../android/FlutterAndroidComponentTest.java | 3 +++ .../flutter/plugin/platform/PlatformPluginTest.java | 13 +++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java index 85ce3ade38fb0..49bb58a84906f 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java @@ -1689,6 +1689,11 @@ boolean shouldDelayFirstAndroidViewDraw() { return getArguments().getBoolean(ARG_SHOULD_DELAY_FIRST_ANDROID_VIEW_DRAW); } + @Override + public void setFrameworkHandlesBacks(boolean frameworkHandlesBacks) { + // Irrelevant to FlutterFragment. + } + private boolean stillAttachedForEvent(String event) { if (delegate == null) { Log.w(TAG, "FlutterFragment " + hashCode() + " " + event + " called after release."); 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 cd5ab22165a85..c865a5d761449 100644 --- a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityTest.java +++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityTest.java @@ -92,7 +92,7 @@ public void flutterViewHasId() { // test that directly exercises the OnBackInvoked APIs when API 33 is supported. @Test @TargetApi(33) - public void itRegistersOnBackInvokedCallbackOnCreate() { + public void itRegistersOnBackInvokedCallbackOnChangingFrameworkHandlesBack() { Intent intent = FlutterActivityWithReportFullyDrawn.createDefaultIntent(ctx); ActivityController activityController = Robolectric.buildActivity(FlutterActivityWithReportFullyDrawn.class, intent); @@ -100,6 +100,12 @@ public void itRegistersOnBackInvokedCallbackOnCreate() { activity.onCreate(null); + verify(activity, times(0)).registerOnBackInvokedCallback(); + + activity.setFrameworkHandlesBacks(false); + verify(activity, times(0)).registerOnBackInvokedCallback(); + + activity.setFrameworkHandlesBacks(true); verify(activity, times(1)).registerOnBackInvokedCallback(); } diff --git a/shell/platform/android/test/io/flutter/embedding/android/FlutterAndroidComponentTest.java b/shell/platform/android/test/io/flutter/embedding/android/FlutterAndroidComponentTest.java index 602e758013f64..390abfc94a81d 100644 --- a/shell/platform/android/test/io/flutter/embedding/android/FlutterAndroidComponentTest.java +++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterAndroidComponentTest.java @@ -417,5 +417,8 @@ public void updateSystemUiOverlays() {} public boolean popSystemNavigator() { return false; } + + @Override + public void setFrameworkHandlesBacks(boolean frameworkHandlesBacks) {} } } diff --git a/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java b/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java index 2aa09af6c83c1..51086bd32a523 100644 --- a/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java +++ b/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java @@ -469,6 +469,19 @@ public void verifyWindowFlagsSetToStyleOverlays() { | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); } + @Test + public void setFrameworkHandlesBacksFlutterActivity() { + Activity mockActivity = mock(Activity.class); + PlatformChannel mockPlatformChannel = mock(PlatformChannel.class); + PlatformPluginDelegate mockPlatformPluginDelegate = mock(PlatformPluginDelegate.class); + PlatformPlugin platformPlugin = + new PlatformPlugin(mockActivity, mockPlatformChannel, mockPlatformPluginDelegate); + + platformPlugin.mPlatformMessageHandler.setFrameworkHandlesBacks(true); + + verify(mockPlatformPluginDelegate, times(1)).setFrameworkHandlesBacks(true); + } + @Test public void popSystemNavigatorFlutterActivity() { Activity mockActivity = mock(Activity.class); From 1db22e58a8097fae25ead358c8cc293cc329df28 Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Wed, 7 Jun 2023 14:43:52 -0700 Subject: [PATCH 17/18] More specific name for hasRegisteredCallback --- .../io/flutter/embedding/android/FlutterActivity.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index 95b448fc7dd9b..bebc625ca36b9 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -217,7 +217,7 @@ public class FlutterActivity extends Activity implements FlutterActivityAndFragmentDelegate.Host, LifecycleOwner { private static final String TAG = "FlutterActivity"; - private boolean hasRegisteredCallback = false; + private boolean hasRegisteredBackCallback = false; /** * The ID of the {@code FlutterView} created by this activity. @@ -668,7 +668,7 @@ public void registerOnBackInvokedCallback() { getOnBackInvokedDispatcher() .registerOnBackInvokedCallback( OnBackInvokedDispatcher.PRIORITY_DEFAULT, onBackInvokedCallback); - hasRegisteredCallback = true; + hasRegisteredBackCallback = true; } } @@ -682,7 +682,7 @@ public void registerOnBackInvokedCallback() { public void unregisterOnBackInvokedCallback() { if (Build.VERSION.SDK_INT >= 33) { getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(onBackInvokedCallback); - hasRegisteredCallback = false; + hasRegisteredBackCallback = false; } } @@ -702,9 +702,9 @@ public void onBackInvoked() { @Override public void setFrameworkHandlesBacks(boolean frameworkHandlesBacks) { - if (frameworkHandlesBacks && !hasRegisteredCallback) { + if (frameworkHandlesBacks && !hasRegisteredBackCallback) { registerOnBackInvokedCallback(); - } else if (!frameworkHandlesBacks && hasRegisteredCallback) { + } else if (!frameworkHandlesBacks && hasRegisteredBackCallback) { unregisterOnBackInvokedCallback(); } } From 4701d6691f8ee45f36d9fd4a8057ab5e319ff7ad Mon Sep 17 00:00:00 2001 From: Justin McCandless Date: Wed, 7 Jun 2023 15:07:02 -0700 Subject: [PATCH 18/18] Backs to Back --- .../io/flutter/embedding/android/FlutterActivity.java | 2 +- .../io/flutter/embedding/android/FlutterFragment.java | 2 +- .../engine/systemchannels/PlatformChannel.java | 6 +++--- .../io/flutter/plugin/platform/PlatformPlugin.java | 10 +++++----- .../flutter/embedding/android/FlutterActivityTest.java | 4 ++-- .../embedding/android/FlutterAndroidComponentTest.java | 2 +- .../io/flutter/plugin/platform/PlatformPluginTest.java | 6 +++--- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java index bebc625ca36b9..d5ffa971c5f74 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java @@ -701,7 +701,7 @@ public void onBackInvoked() { : null; @Override - public void setFrameworkHandlesBacks(boolean frameworkHandlesBacks) { + public void setFrameworkHandlesBack(boolean frameworkHandlesBacks) { if (frameworkHandlesBacks && !hasRegisteredBackCallback) { registerOnBackInvokedCallback(); } else if (!frameworkHandlesBacks && hasRegisteredBackCallback) { diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java index 49bb58a84906f..ad1de8c698fd0 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java @@ -1690,7 +1690,7 @@ boolean shouldDelayFirstAndroidViewDraw() { } @Override - public void setFrameworkHandlesBacks(boolean frameworkHandlesBacks) { + public void setFrameworkHandlesBack(boolean frameworkHandlesBacks) { // Irrelevant to FlutterFragment. } diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java index 003181ba75f43..2c0a3bf378a39 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java @@ -136,10 +136,10 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result.error("error", exception.getMessage(), null); } break; - case "SystemNavigator.setFrameworkHandlesBacks": + case "SystemNavigator.setFrameworkHandlesBack": { boolean frameworkHandlesBacks = (boolean) arguments; - platformMessageHandler.setFrameworkHandlesBacks(frameworkHandlesBacks); + platformMessageHandler.setFrameworkHandlesBack(frameworkHandlesBacks); result.success(null); break; } @@ -517,7 +517,7 @@ public interface PlatformMessageHandler { void setSystemUiOverlayStyle(@NonNull SystemChromeStyle systemUiOverlayStyle); /** The Flutter application would or would not like to handle navigation pop events itself. */ - void setFrameworkHandlesBacks(boolean frameworkHandlesPop); + void setFrameworkHandlesBack(boolean frameworkHandlesBack); /** * The Flutter application would like to pop the top item off of the Android app's navigation diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java index 219fc1ee3dfc5..129e3318461fc 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java @@ -57,7 +57,7 @@ public interface PlatformPluginDelegate { */ boolean popSystemNavigator(); - void setFrameworkHandlesBacks(boolean frameworkHandlesBacks); + void setFrameworkHandlesBack(boolean frameworkHandlesBacks); } @VisibleForTesting @@ -112,8 +112,8 @@ public void setSystemUiOverlayStyle( } @Override - public void setFrameworkHandlesBacks(boolean frameworkHandlesBacks) { - PlatformPlugin.this.setFrameworkHandlesBacks(frameworkHandlesBacks); + public void setFrameworkHandlesBack(boolean frameworkHandlesBacks) { + PlatformPlugin.this.setFrameworkHandlesBack(frameworkHandlesBacks); } @Override @@ -482,8 +482,8 @@ private void setSystemChromeSystemUIOverlayStyle( currentTheme = systemChromeStyle; } - private void setFrameworkHandlesBacks(boolean frameworkHandlesBacks) { - platformPluginDelegate.setFrameworkHandlesBacks(frameworkHandlesBacks); + private void setFrameworkHandlesBack(boolean frameworkHandlesBacks) { + platformPluginDelegate.setFrameworkHandlesBack(frameworkHandlesBacks); } private void popSystemNavigator() { 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 c865a5d761449..d2992e656559b 100644 --- a/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityTest.java +++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterActivityTest.java @@ -102,10 +102,10 @@ public void itRegistersOnBackInvokedCallbackOnChangingFrameworkHandlesBack() { verify(activity, times(0)).registerOnBackInvokedCallback(); - activity.setFrameworkHandlesBacks(false); + activity.setFrameworkHandlesBack(false); verify(activity, times(0)).registerOnBackInvokedCallback(); - activity.setFrameworkHandlesBacks(true); + activity.setFrameworkHandlesBack(true); verify(activity, times(1)).registerOnBackInvokedCallback(); } diff --git a/shell/platform/android/test/io/flutter/embedding/android/FlutterAndroidComponentTest.java b/shell/platform/android/test/io/flutter/embedding/android/FlutterAndroidComponentTest.java index 390abfc94a81d..b7f9d9060dcfd 100644 --- a/shell/platform/android/test/io/flutter/embedding/android/FlutterAndroidComponentTest.java +++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterAndroidComponentTest.java @@ -419,6 +419,6 @@ public boolean popSystemNavigator() { } @Override - public void setFrameworkHandlesBacks(boolean frameworkHandlesBacks) {} + public void setFrameworkHandlesBack(boolean frameworkHandlesBacks) {} } } diff --git a/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java b/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java index 51086bd32a523..8b27e80fd4264 100644 --- a/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java +++ b/shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java @@ -470,16 +470,16 @@ public void verifyWindowFlagsSetToStyleOverlays() { } @Test - public void setFrameworkHandlesBacksFlutterActivity() { + public void setFrameworkHandlesBackFlutterActivity() { Activity mockActivity = mock(Activity.class); PlatformChannel mockPlatformChannel = mock(PlatformChannel.class); PlatformPluginDelegate mockPlatformPluginDelegate = mock(PlatformPluginDelegate.class); PlatformPlugin platformPlugin = new PlatformPlugin(mockActivity, mockPlatformChannel, mockPlatformPluginDelegate); - platformPlugin.mPlatformMessageHandler.setFrameworkHandlesBacks(true); + platformPlugin.mPlatformMessageHandler.setFrameworkHandlesBack(true); - verify(mockPlatformPluginDelegate, times(1)).setFrameworkHandlesBacks(true); + verify(mockPlatformPluginDelegate, times(1)).setFrameworkHandlesBack(true); } @Test