mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
migrate deprecated onBackPressed() (#51096)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/51096 **Problem:** `Activity.onBackPressed()` has been deprecated and with targetSdk 36, predictive back will be enforced and the API no longer called. We need to migrate to backward compatible AndroidX `OnBackPressedCallback`. - https://developer.android.com/about/versions/16/behavior-changes-16#predictive-back. **Solution:** `OnBackPressedCallback` is registered conditionally only if it is `targetSdk` 36 or greater. If the callback in enabled, `onBackPressed()` is not called and callback is used regardless of `android:enableOnBackInvokedCallback` property in <application> or <activity> set in AndroidManifest.xml. As a workaround callback is manually calling existing `onBackPressed()`. This is done rather than removing onBackPressed() completely and using only `OnBackPressedCallback` as we are not sure of the impact of removing the implementation entirely. Once we determine it is safe to do so then, we should remove the workaround and fully transition to `OnBackPressedCallback` * I also surveyed child classes extending ReactActivity for overridden `onPressedBack()` usage and found only one usage which will be handled later. NOTE: `ReactDelegate.onHostResume()` sets up the `DefaultHardwareBackBtnHandler` using `ReactActivity` (https://fburl.com/ul47tbeo) and will be called from JS `BackHanderl.exitApp` (https://fburl.com/code/a4l2pjsw). Calling `BackHanderl.exitApp` enables predictive back to work. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D74161428 fbshipit-source-id: 2e081ba6922b315e9d1746e83a41bab5277fa62e
This commit is contained in:
committed by
React Native Bot
parent
84cf4d8869
commit
0e3764c8aa
+20
@@ -11,11 +11,13 @@ import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
|
||||
import com.facebook.react.modules.core.PermissionAwareActivity;
|
||||
import com.facebook.react.modules.core.PermissionListener;
|
||||
import com.facebook.react.util.AndroidVersion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/** Base Activity for React Native applications. */
|
||||
@@ -24,6 +26,18 @@ public abstract class ReactActivity extends AppCompatActivity
|
||||
|
||||
private final ReactActivityDelegate mDelegate;
|
||||
|
||||
// Due to enforced predictive back on targetSdk 36, 'onBackPressed()' is disabled by default.
|
||||
// Using a workaround to trigger it manually.
|
||||
private final OnBackPressedCallback mBackPressedCallback =
|
||||
new OnBackPressedCallback(true) {
|
||||
@Override
|
||||
public void handleOnBackPressed() {
|
||||
setEnabled(false);
|
||||
onBackPressed();
|
||||
setEnabled(true);
|
||||
}
|
||||
};
|
||||
|
||||
protected ReactActivity() {
|
||||
mDelegate = createReactActivityDelegate();
|
||||
}
|
||||
@@ -45,6 +59,9 @@ public abstract class ReactActivity extends AppCompatActivity
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mDelegate.onCreate(savedInstanceState);
|
||||
if (AndroidVersion.isAtLeastTargetSdk36(this)) {
|
||||
getOnBackPressedDispatcher().addCallback(this, mBackPressedCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -103,6 +120,9 @@ public abstract class ReactActivity extends AppCompatActivity
|
||||
|
||||
@Override
|
||||
public void invokeDefaultOnBackPressed() {
|
||||
// Disabling callback so the fallback logic (finish activity) can run
|
||||
// as super.onBackPressed() will call all enabled callbacks in the dispatcher.
|
||||
mBackPressedCallback.setEnabled(false);
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.util
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
|
||||
/** Helper class for checking Android version-related information. */
|
||||
internal object AndroidVersion {
|
||||
|
||||
/**
|
||||
* This is the version code for Android 16 (SDK Level 36). Delete it once we bump up the default
|
||||
* compile SDK version to 36.
|
||||
*/
|
||||
private const val VERSION_CODE_BAKLAVA: Int = 36
|
||||
|
||||
/**
|
||||
* This method is used to check if the current device is running Android 16 (SDK Level 36) or
|
||||
* higher and the app is targeting Android 16 (SDK Level 36) or higher.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isAtLeastTargetSdk36(context: Context): Boolean =
|
||||
Build.VERSION.SDK_INT >= VERSION_CODE_BAKLAVA &&
|
||||
context.applicationInfo.targetSdkVersion >= VERSION_CODE_BAKLAVA
|
||||
}
|
||||
Reference in New Issue
Block a user