|  | 
| 14 | 14 | import android.view.View; | 
| 15 | 15 | import android.view.ViewGroup; | 
| 16 | 16 | import android.view.ViewTreeObserver.OnWindowFocusChangeListener; | 
|  | 17 | +import android.window.OnBackInvokedCallback; | 
|  | 18 | +import android.window.OnBackInvokedDispatcher; | 
| 17 | 19 | import androidx.activity.OnBackPressedCallback; | 
| 18 | 20 | import androidx.annotation.NonNull; | 
| 19 | 21 | import androidx.annotation.Nullable; | 
| @@ -170,6 +172,8 @@ public class FlutterFragment extends Fragment | 
| 170 | 172 |   protected static final String ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED = | 
| 171 | 173 |       "should_automatically_handle_on_back_pressed"; | 
| 172 | 174 | 
 | 
|  | 175 | +  private boolean hasRegisteredBackCallback = false; | 
|  | 176 | + | 
| 173 | 177 |   @RequiresApi(18) | 
| 174 | 178 |   private final OnWindowFocusChangeListener onWindowFocusChangeListener = | 
| 175 | 179 |       Build.VERSION.SDK_INT >= 18 | 
| @@ -1023,6 +1027,20 @@ public void handleOnBackPressed() { | 
| 1023 | 1027 |         } | 
| 1024 | 1028 |       }; | 
| 1025 | 1029 | 
 | 
|  | 1030 | +  private final OnBackInvokedCallback onBackInvokedCallback = | 
|  | 1031 | +      Build.VERSION.SDK_INT >= 33 | 
|  | 1032 | +          ? new OnBackInvokedCallback() { | 
|  | 1033 | +            // TODO(garyq): Remove SuppressWarnings annotation. This was added to workaround | 
|  | 1034 | +            // a google3 bug where the linter is not properly running against API 33, causing | 
|  | 1035 | +            // a failure here. See b/243609613 and https://github.com/flutter/flutter/issues/111295 | 
|  | 1036 | +            @SuppressWarnings("Override") | 
|  | 1037 | +            @Override | 
|  | 1038 | +            public void onBackInvoked() { | 
|  | 1039 | +              onBackPressed(); | 
|  | 1040 | +            } | 
|  | 1041 | +          } | 
|  | 1042 | +          : null; | 
|  | 1043 | + | 
| 1026 | 1044 |   public FlutterFragment() { | 
| 1027 | 1045 |     // Ensure that we at least have an empty Bundle of arguments so that we don't | 
| 1028 | 1046 |     // need to continually check for null arguments before grabbing one. | 
| @@ -1060,9 +1078,11 @@ public void onAttach(@NonNull Context context) { | 
| 1060 | 1078 |     super.onAttach(context); | 
| 1061 | 1079 |     delegate = delegateFactory.createDelegate(this); | 
| 1062 | 1080 |     delegate.onAttach(context); | 
|  | 1081 | +    /* | 
| 1063 | 1082 |     if (getArguments().getBoolean(ARG_SHOULD_AUTOMATICALLY_HANDLE_ON_BACK_PRESSED, false)) { | 
| 1064 | 1083 |       requireActivity().getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback); | 
| 1065 | 1084 |     } | 
|  | 1085 | +    */ | 
| 1066 | 1086 |     context.registerComponentCallbacks(this); | 
| 1067 | 1087 |   } | 
| 1068 | 1088 | 
 | 
| @@ -1684,6 +1704,59 @@ public boolean popSystemNavigator() { | 
| 1684 | 1704 |     return false; | 
| 1685 | 1705 |   } | 
| 1686 | 1706 | 
 | 
|  | 1707 | +  @Override | 
|  | 1708 | +  public void setFrameworkHandlesBack(boolean frameworkHandlesBack) { | 
|  | 1709 | +    Log.e( | 
|  | 1710 | +        "justin", | 
|  | 1711 | +        "setFrameworkHandlesBack in FlutterFragment! setEnabled: " + frameworkHandlesBack); | 
|  | 1712 | +    // TODO(justinmc): Doesn't quite work. | 
|  | 1713 | +    // Home route: pback works (good) | 
|  | 1714 | +    // Second route: pback doesn't work (good) | 
|  | 1715 | +    // Home route again: pback still doesn't work (bad) though I received the right call here... | 
|  | 1716 | +    if (frameworkHandlesBack && !hasRegisteredBackCallback) { | 
|  | 1717 | +      registerOnBackInvokedCallback(); | 
|  | 1718 | +    } else if (!frameworkHandlesBack && hasRegisteredBackCallback) { | 
|  | 1719 | +      unregisterOnBackInvokedCallback(); | 
|  | 1720 | +    } | 
|  | 1721 | +  } | 
|  | 1722 | + | 
|  | 1723 | +  /** | 
|  | 1724 | +   * Registers the callback with OnBackPressedDispatcher to capture back navigation gestures and | 
|  | 1725 | +   * pass them to the framework. | 
|  | 1726 | +   * | 
|  | 1727 | +   * <p>This replaces the deprecated onBackPressed method override in order to support API 33's | 
|  | 1728 | +   * predictive back navigation feature. | 
|  | 1729 | +   * | 
|  | 1730 | +   * <p>The callback must be unregistered in order to prevent unpredictable behavior once outside | 
|  | 1731 | +   * the Flutter app. | 
|  | 1732 | +   */ | 
|  | 1733 | +  @VisibleForTesting | 
|  | 1734 | +  public void registerOnBackInvokedCallback() { | 
|  | 1735 | +    if (Build.VERSION.SDK_INT >= 33) { | 
|  | 1736 | +      getActivity() | 
|  | 1737 | +          .getOnBackInvokedDispatcher() | 
|  | 1738 | +          .registerOnBackInvokedCallback( | 
|  | 1739 | +              OnBackInvokedDispatcher.PRIORITY_DEFAULT, onBackInvokedCallback); | 
|  | 1740 | +      hasRegisteredBackCallback = true; | 
|  | 1741 | +    } | 
|  | 1742 | +  } | 
|  | 1743 | + | 
|  | 1744 | +  /** | 
|  | 1745 | +   * Unregisters the callback from OnBackPressedDispatcher. | 
|  | 1746 | +   * | 
|  | 1747 | +   * <p>This should be called when the activity is no longer in use to prevent unpredictable | 
|  | 1748 | +   * behavior such as being stuck and unable to press back. | 
|  | 1749 | +   */ | 
|  | 1750 | +  @VisibleForTesting | 
|  | 1751 | +  public void unregisterOnBackInvokedCallback() { | 
|  | 1752 | +    if (Build.VERSION.SDK_INT >= 33) { | 
|  | 1753 | +      getActivity() | 
|  | 1754 | +          .getOnBackInvokedDispatcher() | 
|  | 1755 | +          .unregisterOnBackInvokedCallback(onBackInvokedCallback); | 
|  | 1756 | +      hasRegisteredBackCallback = false; | 
|  | 1757 | +    } | 
|  | 1758 | +  } | 
|  | 1759 | + | 
| 1687 | 1760 |   @VisibleForTesting | 
| 1688 | 1761 |   @NonNull | 
| 1689 | 1762 |   boolean shouldDelayFirstAndroidViewDraw() { | 
|  | 
0 commit comments