|
35 | 35 | import android.view.View; |
36 | 36 | import android.view.Window; |
37 | 37 | import android.view.WindowManager; |
| 38 | +import android.window.OnBackInvokedCallback; |
| 39 | +import android.window.OnBackInvokedDispatcher; |
38 | 40 | import androidx.annotation.NonNull; |
39 | 41 | import androidx.annotation.Nullable; |
40 | 42 | import androidx.annotation.VisibleForTesting; |
@@ -495,13 +497,61 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { |
495 | 497 |
|
496 | 498 | lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE); |
497 | 499 |
|
| 500 | + registerOnBackInvokedCallback(); |
| 501 | + |
498 | 502 | configureWindowForTransparency(); |
499 | 503 |
|
500 | 504 | setContentView(createFlutterView()); |
501 | 505 |
|
502 | 506 | configureStatusBarForFullscreenFlutterExperience(); |
503 | 507 | } |
504 | 508 |
|
| 509 | + /** |
| 510 | + * Registers the callback with OnBackInvokedDispatcher to capture back navigation gestures and |
| 511 | + * pass them to the framework. |
| 512 | + * |
| 513 | + * <p>This replaces the deprecated onBackPressed method override in order to support API 33's |
| 514 | + * predictive back navigation feature. |
| 515 | + * |
| 516 | + * <p>The callback must be unregistered in order to prevent unpredictable behavior once outside |
| 517 | + * the Flutter app. |
| 518 | + */ |
| 519 | + @VisibleForTesting |
| 520 | + public void registerOnBackInvokedCallback() { |
| 521 | + if (Build.VERSION.SDK_INT >= 33) { |
| 522 | + getOnBackInvokedDispatcher() |
| 523 | + .registerOnBackInvokedCallback( |
| 524 | + OnBackInvokedDispatcher.PRIORITY_DEFAULT, onBackInvokedCallback); |
| 525 | + } |
| 526 | + } |
| 527 | + |
| 528 | + /** |
| 529 | + * Unregisters the callback from OnBackInvokedDispatcher. |
| 530 | + * |
| 531 | + * <p>This should be called when the activity is no longer in use to prevent unpredictable |
| 532 | + * behavior such as being stuck and unable to press back. |
| 533 | + */ |
| 534 | + @VisibleForTesting |
| 535 | + public void unregisterOnBackInvokedCallback() { |
| 536 | + if (Build.VERSION.SDK_INT >= 33) { |
| 537 | + getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(onBackInvokedCallback); |
| 538 | + } |
| 539 | + } |
| 540 | + |
| 541 | + private final OnBackInvokedCallback onBackInvokedCallback = |
| 542 | + Build.VERSION.SDK_INT >= 33 |
| 543 | + ? new OnBackInvokedCallback() { |
| 544 | + // TODO(garyq): Remove SuppressWarnings annotation. This was added to workaround |
| 545 | + // a google3 bug where the linter is not properly running against API 33, causing |
| 546 | + // a failure here. See b/243609613 and https://github.com/flutter/flutter/issues/111295 |
| 547 | + @SuppressWarnings("Override") |
| 548 | + @Override |
| 549 | + public void onBackInvoked() { |
| 550 | + onBackPressed(); |
| 551 | + } |
| 552 | + } |
| 553 | + : null; |
| 554 | + |
505 | 555 | /** |
506 | 556 | * Switches themes for this {@code Activity} from the theme used to launch this {@code Activity} |
507 | 557 | * to a "normal theme" that is intended for regular {@code Activity} operation. |
@@ -680,7 +730,9 @@ protected void onSaveInstanceState(Bundle outState) { |
680 | 730 | * |
681 | 731 | * <p>After calling, this activity should be disposed immediately and not be re-used. |
682 | 732 | */ |
683 | | - private void release() { |
| 733 | + @VisibleForTesting |
| 734 | + public void release() { |
| 735 | + unregisterOnBackInvokedCallback(); |
684 | 736 | if (delegate != null) { |
685 | 737 | delegate.release(); |
686 | 738 | delegate = null; |
|
0 commit comments