mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Reland "Support basic back navigation in Android 13/API 33 #35678" (flutter/engine#36051)
This commit is contained in:
parent
c024760a13
commit
218fb443b9
@ -35,6 +35,8 @@ import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.window.OnBackInvokedCallback;
|
||||
import android.window.OnBackInvokedDispatcher;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
@ -495,6 +497,8 @@ public class FlutterActivity extends Activity
|
||||
|
||||
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
|
||||
|
||||
registerOnBackInvokedCallback();
|
||||
|
||||
configureWindowForTransparency();
|
||||
|
||||
setContentView(createFlutterView());
|
||||
@ -502,6 +506,52 @@ public class FlutterActivity extends Activity
|
||||
configureStatusBarForFullscreenFlutterExperience();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the callback with OnBackInvokedDispatcher to capture back navigation gestures and
|
||||
* pass them to the framework.
|
||||
*
|
||||
* <p>This replaces the deprecated onBackPressed method override in order to support API 33's
|
||||
* predictive back navigation feature.
|
||||
*
|
||||
* <p>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) {
|
||||
getOnBackInvokedDispatcher()
|
||||
.registerOnBackInvokedCallback(
|
||||
OnBackInvokedDispatcher.PRIORITY_DEFAULT, onBackInvokedCallback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the callback from OnBackInvokedDispatcher.
|
||||
*
|
||||
* <p>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() {
|
||||
// TODO(garyq): Remove SuppressWarnings annotation. This was added to workaround
|
||||
// a google3 bug where the linter is not properly running against API 33, causing
|
||||
// a failure here. See b/243609613 and https://github.com/flutter/flutter/issues/111295
|
||||
@SuppressWarnings("Override")
|
||||
@Override
|
||||
public void onBackInvoked() {
|
||||
onBackPressed();
|
||||
}
|
||||
}
|
||||
: null;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -680,7 +730,9 @@ public class FlutterActivity extends Activity
|
||||
*
|
||||
* <p>After calling, this activity should be disposed immediately and not be re-used.
|
||||
*/
|
||||
private void release() {
|
||||
@VisibleForTesting
|
||||
public void release() {
|
||||
unregisterOnBackInvokedCallback();
|
||||
if (delegate != null) {
|
||||
delegate.release();
|
||||
delegate = null;
|
||||
|
||||
@ -88,6 +88,36 @@ public class FlutterActivityTest {
|
||||
assertTrue(activity.findViewById(FlutterActivity.FLUTTER_VIEW_ID) instanceof FlutterView);
|
||||
}
|
||||
|
||||
// TODO(garyq): Robolectric does not yet support android api 33 yet. Switch to a robolectric
|
||||
// test that directly exercises the OnBackInvoked APIs when API 33 is supported.
|
||||
@Test
|
||||
@TargetApi(33)
|
||||
public void itRegistersOnBackInvokedCallbackOnCreate() {
|
||||
Intent intent = FlutterActivityWithReportFullyDrawn.createDefaultIntent(ctx);
|
||||
ActivityController<FlutterActivityWithReportFullyDrawn> activityController =
|
||||
Robolectric.buildActivity(FlutterActivityWithReportFullyDrawn.class, intent);
|
||||
FlutterActivityWithReportFullyDrawn activity = spy(activityController.get());
|
||||
|
||||
activity.onCreate(null);
|
||||
|
||||
verify(activity, times(1)).registerOnBackInvokedCallback();
|
||||
}
|
||||
|
||||
// TODO(garyq): Robolectric does not yet support android api 33 yet. Switch to a robolectric
|
||||
// test that directly exercises the OnBackInvoked APIs when API 33 is supported.
|
||||
@Test
|
||||
@TargetApi(33)
|
||||
public void itUnregistersOnBackInvokedCallbackOnRelease() {
|
||||
Intent intent = FlutterActivityWithReportFullyDrawn.createDefaultIntent(ctx);
|
||||
ActivityController<FlutterActivityWithReportFullyDrawn> activityController =
|
||||
Robolectric.buildActivity(FlutterActivityWithReportFullyDrawn.class, intent);
|
||||
FlutterActivityWithReportFullyDrawn activity = spy(activityController.get());
|
||||
|
||||
activity.release();
|
||||
|
||||
verify(activity, times(1)).unregisterOnBackInvokedCallback();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void itCreatesDefaultIntentWithExpectedDefaults() {
|
||||
Intent intent = FlutterActivity.createDefaultIntent(ctx);
|
||||
@ -596,6 +626,14 @@ public class FlutterActivityTest {
|
||||
}
|
||||
}
|
||||
|
||||
private class FlutterActivityWithMockBackInvokedHandling extends FlutterActivity {
|
||||
@Override
|
||||
public void registerOnBackInvokedCallback() {}
|
||||
|
||||
@Override
|
||||
public void unregisterOnBackInvokedCallback() {}
|
||||
}
|
||||
|
||||
private static final class FakeFlutterPlugin
|
||||
implements FlutterPlugin,
|
||||
ActivityAware,
|
||||
|
||||
@ -71,10 +71,10 @@ android {
|
||||
testImplementation "com.google.android.play:core:1.8.0"
|
||||
testImplementation "com.ibm.icu:icu4j:69.1"
|
||||
testImplementation "org.robolectric:robolectric:4.7.3"
|
||||
testImplementation "junit:junit:4.13"
|
||||
testImplementation "androidx.test.ext:junit:1.1.3"
|
||||
testImplementation "junit:junit:4.13.2"
|
||||
testImplementation "androidx.test.ext:junit:1.1.4-alpha07"
|
||||
|
||||
def mockitoVersion = "4.1.0"
|
||||
def mockitoVersion = "4.7.0"
|
||||
testImplementation "org.mockito:mockito-core:$mockitoVersion"
|
||||
testImplementation "org.mockito:mockito-inline:$mockitoVersion"
|
||||
testImplementation "org.mockito:mockito-android:$mockitoVersion"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user