diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index f879b8f0b242..680096951b9b 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -114,18 +114,15 @@ public class com/facebook/react/ReactActivityDelegate { protected fun composeLaunchOptions ()Landroid/os/Bundle; protected fun createRootView ()Lcom/facebook/react/ReactRootView; protected fun getContext ()Landroid/content/Context; - public fun getCurrentReactContext ()Lcom/facebook/react/bridge/ReactContext; + public final fun getCurrentReactContext ()Lcom/facebook/react/bridge/ReactContext; protected fun getLaunchOptions ()Landroid/os/Bundle; - public fun getMainComponentName ()Ljava/lang/String; protected fun getPlainActivity ()Landroid/app/Activity; protected fun getReactActivity ()Lcom/facebook/react/ReactActivity; - protected fun getReactDelegate ()Lcom/facebook/react/ReactDelegate; public fun getReactHost ()Lcom/facebook/react/ReactHost; public fun getReactInstanceManager ()Lcom/facebook/react/ReactInstanceManager; - protected fun getReactNativeHost ()Lcom/facebook/react/ReactNativeHost; protected fun isFabricEnabled ()Z protected fun isWideColorGamutEnabled ()Z - protected fun loadApp (Ljava/lang/String;)V + public final fun loadApp (Ljava/lang/String;)V public fun onActivityResult (IILandroid/content/Intent;)V public fun onBackPressed ()Z public fun onConfigurationChanged (Landroid/content/res/Configuration;)V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.kt index 4eb90518da1d..4d5d77d1e999 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.kt @@ -29,10 +29,10 @@ public abstract class ReactActivity protected constructor() : get() = reactActivityDelegate.reactHost protected val reactNativeHost: ReactNativeHost - get() = reactActivityDelegate.reactNativeHost + @Suppress("DEPRECATION") get() = reactActivityDelegate.reactNativeHost protected val reactInstanceManager: ReactInstanceManager - get() = reactActivityDelegate.reactInstanceManager + @Suppress("DEPRECATION") get() = reactActivityDelegate.reactInstanceManager /** * Returns the name of the main component registered from JavaScript. This is used to schedule diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java deleted file mode 100644 index 3b15b287b07a..000000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * 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; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.view.KeyEvent; -import androidx.annotation.Nullable; -import com.facebook.infer.annotation.Assertions; -import com.facebook.react.bridge.Callback; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.common.annotations.DeprecatedInNewArchitecture; -import com.facebook.react.interfaces.fabric.ReactSurface; -import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatureFlags; -import com.facebook.react.modules.core.PermissionListener; -import com.facebook.systrace.Systrace; - -/** - * Delegate class for {@link ReactActivity}. You can subclass this to provide custom implementations - * for e.g. {@link #getReactNativeHost()}, if your Application class doesn't implement {@link - * ReactApplication}. - */ -public class ReactActivityDelegate { - - private final @Nullable Activity mActivity; - private final @Nullable String mMainComponentName; - - private @Nullable PermissionListener mPermissionListener; - private @Nullable Callback mPermissionsCallback; - private @Nullable ReactDelegate mReactDelegate; - - /** - * Prefer using ReactActivity when possible, as it hooks up all Activity lifecycle methods by - * default. It also implements DefaultHardwareBackBtnHandler, which ReactDelegate requires. - */ - @Deprecated - public ReactActivityDelegate(@Nullable Activity activity, @Nullable String mainComponentName) { - mActivity = activity; - mMainComponentName = mainComponentName; - } - - public ReactActivityDelegate( - @Nullable ReactActivity activity, @Nullable String mainComponentName) { - mActivity = activity; - mMainComponentName = mainComponentName; - } - - /** - * Public API to populate the launch options that will be passed to React. Here you can customize - * the values that will be passed as `initialProperties` to the Renderer. - * - * @return Either null or a key-value map as a Bundle - */ - protected @Nullable Bundle getLaunchOptions() { - return null; - } - - protected @Nullable Bundle composeLaunchOptions() { - return getLaunchOptions(); - } - - /** - * Override to customize ReactRootView creation. - * - *
Not used on bridgeless - */ - protected @Nullable ReactRootView createRootView() { - return null; - } - - /** - * Get the {@link ReactNativeHost} used by this app with Bridge enabled. By default, assumes - * {@link Activity#getApplication()} is an instance of {@link ReactApplication} and calls {@link - * ReactApplication#getReactNativeHost()}. Override this method if your application class does not - * implement {@code ReactApplication} or you simply have a different mechanism for storing a - * {@code ReactNativeHost}, e.g. as a static field somewhere. - */ - @DeprecatedInNewArchitecture(message = "Use getReactHost()") - protected ReactNativeHost getReactNativeHost() { - return ((ReactApplication) getPlainActivity().getApplication()).getReactNativeHost(); - } - - /** - * Get the {@link ReactHost} used by this app with Bridgeless enabled. By default, assumes {@link - * Activity#getApplication()} is an instance of {@link ReactApplication} and calls {@link - * ReactApplication#getReactHost()}. Override this method if your application class does not - * implement {@code ReactApplication} or you simply have a different mechanism for storing a - * {@code ReactHost}, e.g. as a static field somewhere. - */ - public @Nullable ReactHost getReactHost() { - return ((ReactApplication) getPlainActivity().getApplication()).getReactHost(); - } - - protected @Nullable ReactDelegate getReactDelegate() { - return mReactDelegate; - } - - @DeprecatedInNewArchitecture(message = "Use getReactHost()") - public ReactInstanceManager getReactInstanceManager() { - return mReactDelegate.getReactInstanceManager(); - } - - public @Nullable String getMainComponentName() { - return mMainComponentName; - } - - public void onCreate(Bundle savedInstanceState) { - Systrace.traceSection( - Systrace.TRACE_TAG_REACT, - "ReactActivityDelegate.onCreate::init", - () -> { - String mainComponentName = getMainComponentName(); - final Bundle launchOptions = composeLaunchOptions(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && isWideColorGamutEnabled()) { - mActivity.getWindow().setColorMode(ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT); - } - if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) { - mReactDelegate = - new ReactDelegate( - getPlainActivity(), getReactHost(), mainComponentName, launchOptions); - } else { - mReactDelegate = - new ReactDelegate( - getPlainActivity(), - getReactNativeHost(), - mainComponentName, - launchOptions, - isFabricEnabled()) { - @Override - protected ReactRootView createRootView() { - ReactRootView rootView = ReactActivityDelegate.this.createRootView(); - if (rootView == null) { - rootView = super.createRootView(); - } - return rootView; - } - }; - } - if (mainComponentName != null) { - loadApp(mainComponentName); - } - }); - } - - protected void loadApp(String appKey) { - mReactDelegate.loadApp(appKey); - getPlainActivity().setContentView(mReactDelegate.getReactRootView()); - } - - public void setReactSurface(ReactSurface reactSurface) { - mReactDelegate.setReactSurface(reactSurface); - } - - public void setReactRootView(ReactRootView reactRootView) { - mReactDelegate.setReactRootView(reactRootView); - } - - public void onUserLeaveHint() { - if (mReactDelegate != null) { - mReactDelegate.onUserLeaveHint(); - } - } - - public void onPause() { - mReactDelegate.onHostPause(); - } - - public void onResume() { - mReactDelegate.onHostResume(); - - if (mPermissionsCallback != null) { - mPermissionsCallback.invoke(); - mPermissionsCallback = null; - } - } - - public void onDestroy() { - mReactDelegate.onHostDestroy(); - } - - public void onActivityResult(int requestCode, int resultCode, Intent data) { - mReactDelegate.onActivityResult(requestCode, resultCode, data, true); - } - - public boolean onKeyDown(int keyCode, KeyEvent event) { - return mReactDelegate.onKeyDown(keyCode, event); - } - - public boolean onKeyUp(int keyCode, KeyEvent event) { - return mReactDelegate.shouldShowDevMenuOrReload(keyCode, event); - } - - public boolean onKeyLongPress(int keyCode, KeyEvent event) { - return mReactDelegate.onKeyLongPress(keyCode); - } - - public boolean onBackPressed() { - return mReactDelegate.onBackPressed(); - } - - public boolean onNewIntent(Intent intent) { - return mReactDelegate.onNewIntent(intent); - } - - public void onWindowFocusChanged(boolean hasFocus) { - mReactDelegate.onWindowFocusChanged(hasFocus); - } - - public void onConfigurationChanged(Configuration newConfig) { - mReactDelegate.onConfigurationChanged(newConfig); - } - - public void requestPermissions( - String[] permissions, int requestCode, PermissionListener listener) { - mPermissionListener = listener; - getPlainActivity().requestPermissions(permissions, requestCode); - } - - public void onRequestPermissionsResult( - final int requestCode, final String[] permissions, final int[] grantResults) { - mPermissionsCallback = - args -> { - if (mPermissionListener != null - && mPermissionListener.onRequestPermissionsResult( - requestCode, permissions, grantResults)) { - mPermissionListener = null; - } - }; - } - - protected Context getContext() { - return Assertions.assertNotNull(mActivity); - } - - protected Activity getPlainActivity() { - return ((Activity) getContext()); - } - - protected ReactActivity getReactActivity() { - return ((ReactActivity) getContext()); - } - - /** - * Get the current {@link ReactContext} from ReactHost or ReactInstanceManager - * - *
Do not store a reference to this, if the React instance is reloaded or destroyed, this
- * context will no longer be valid.
- */
- public @Nullable ReactContext getCurrentReactContext() {
- return mReactDelegate.getCurrentReactContext();
- }
-
- /**
- * Override this method if you wish to selectively toggle Fabric for a specific surface. This will
- * also control if Concurrent Root (React 18) should be enabled or not.
- *
- * @return true if Fabric is enabled for this Activity, false otherwise.
- */
- protected boolean isFabricEnabled() {
- return ReactNativeNewArchitectureFeatureFlags.enableFabricRenderer();
- }
-
- /**
- * Override this method if you wish to selectively toggle wide color gamut for a specific surface.
- *
- * @return true if wide gamut is enabled for this Activity, false otherwise.
- */
- protected boolean isWideColorGamutEnabled() {
- return false;
- }
-}
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.kt
new file mode 100644
index 000000000000..89bb3d16e0b2
--- /dev/null
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.kt
@@ -0,0 +1,248 @@
+/*
+ * 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
+
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.content.pm.ActivityInfo
+import android.content.res.Configuration
+import android.os.Build
+import android.os.Bundle
+import android.view.KeyEvent
+import com.facebook.react.bridge.Callback
+import com.facebook.react.bridge.ReactContext
+import com.facebook.react.interfaces.fabric.ReactSurface
+import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatureFlags
+import com.facebook.react.modules.core.PermissionListener
+import com.facebook.systrace.Systrace
+
+/**
+ * Delegate class for [ReactActivity]. You can subclass this to provide custom implementations for
+ * e.g. [.getReactNativeHost], if your Application class doesn't implement [ ].
+ */
+public open class ReactActivityDelegate {
+ private val activity: ReactActivity?
+ private val mainComponentName: String?
+
+ private var permissionListener: PermissionListener? = null
+ private var permissionsCallback: Callback? = null
+ internal var reactDelegate: ReactDelegate? = null
+ private set
+
+ protected open val launchOptions: Bundle?
+ /**
+ * Public API to populate the launch options that will be passed to React. Here you can
+ * customize the values that will be passed as `initialProperties` to the Renderer.
+ *
+ * @return Either null or a key-value map as a Bundle
+ */
+ get() = null
+
+ @Deprecated("Use reactHost in New Architecture")
+ internal open val reactNativeHost: ReactNativeHost
+ /**
+ * Get the [ReactNativeHost] used by this app with Bridge enabled. By default, assumes
+ * [Activity.getApplication] is an instance of [ReactApplication] and calls
+ * [ ][ReactApplication.getReactNativeHost]. Override this method if your application class does
+ * not implement `ReactApplication` or you simply have a different mechanism for storing a
+ * `ReactNativeHost`, e.g. as a static field somewhere.
+ */
+ get() = (plainActivity.getApplication() as ReactApplication).reactNativeHost
+
+ public open val reactHost: ReactHost?
+ /**
+ * Get the [ReactHost] used by this app with Bridgeless enabled. By default, assumes
+ * [ ][Activity.getApplication] is an instance of [ReactApplication] and calls
+ * [ ][ReactApplication.getReactHost]. Override this method if your application class does not
+ * implement `ReactApplication` or you simply have a different mechanism for storing a
+ * `ReactHost`, e.g. as a static field somewhere.
+ */
+ get() = (plainActivity.getApplication() as ReactApplication).reactHost
+
+ /**
+ * Prefer using ReactActivity when possible, as it hooks up all Activity lifecycle methods by
+ * default. It also implements DefaultHardwareBackBtnHandler, which ReactDelegate requires.
+ */
+ @Deprecated("")
+ public constructor(activity: Activity?, mainComponentName: String?) {
+ this.activity = activity as? ReactActivity
+ this.mainComponentName = mainComponentName
+ }
+
+ public constructor(activity: ReactActivity?, mainComponentName: String?) {
+ this.activity = activity
+ this.mainComponentName = mainComponentName
+ }
+
+ protected open fun composeLaunchOptions(): Bundle? = launchOptions
+
+ /**
+ * Override to customize ReactRootView creation.
+ *
+ * Not used on bridgeless
+ */
+ protected open fun createRootView(): ReactRootView? = null
+
+ @Deprecated("Use reactHost in New Architecture")
+ public open val reactInstanceManager: ReactInstanceManager
+ get() = checkNotNull(reactDelegate).reactInstanceManager
+
+ public open fun onCreate(savedInstanceState: Bundle?) {
+ Systrace.traceSection(Systrace.TRACE_TAG_REACT, "ReactActivityDelegate.onCreate::init") {
+ val mainComponentName = mainComponentName
+ val launchOptions: Bundle? = composeLaunchOptions()
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && isWideColorGamutEnabled) {
+ activity?.getWindow()?.setColorMode(ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT)
+ }
+ if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) {
+ reactDelegate = ReactDelegate(plainActivity, reactHost, mainComponentName, launchOptions)
+ } else {
+ @Suppress("DEPRECATION")
+ reactDelegate =
+ object :
+ ReactDelegate(
+ plainActivity,
+ reactNativeHost,
+ mainComponentName,
+ launchOptions,
+ isFabricEnabled) {
+ override fun createRootView(): ReactRootView {
+ var rootView = this@ReactActivityDelegate.createRootView()
+ if (rootView == null) {
+ rootView = super.createRootView()
+ }
+ return rootView
+ }
+ }
+ }
+ if (mainComponentName != null) {
+ loadApp(mainComponentName)
+ }
+ }
+ }
+
+ public fun loadApp(appKey: String?) {
+ reactDelegate?.loadApp(appKey)
+ plainActivity.setContentView(reactDelegate?.reactRootView)
+ }
+
+ public open fun setReactSurface(reactSurface: ReactSurface?) {
+ reactDelegate?.setReactSurface(reactSurface)
+ }
+
+ public open fun setReactRootView(reactRootView: ReactRootView?) {
+ reactDelegate?.reactRootView = reactRootView
+ }
+
+ public open fun onUserLeaveHint() {
+ reactDelegate?.onUserLeaveHint()
+ }
+
+ public open fun onPause() {
+ reactDelegate?.onHostPause()
+ }
+
+ public open fun onResume() {
+ reactDelegate?.onHostResume()
+ permissionsCallback?.invoke()
+ permissionsCallback = null
+ }
+
+ public open fun onDestroy() {
+ reactDelegate?.onHostDestroy()
+ }
+
+ public open fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ reactDelegate?.onActivityResult(requestCode, resultCode, data, true)
+ }
+
+ public open fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean =
+ reactDelegate?.onKeyDown(keyCode, event) ?: false
+
+ public open fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean =
+ reactDelegate?.shouldShowDevMenuOrReload(keyCode, event) ?: false
+
+ public open fun onKeyLongPress(keyCode: Int, event: KeyEvent?): Boolean =
+ reactDelegate?.onKeyLongPress(keyCode) ?: false
+
+ public open fun onBackPressed(): Boolean = reactDelegate?.onBackPressed() ?: false
+
+ public open fun onNewIntent(intent: Intent?): Boolean =
+ reactDelegate?.onNewIntent(intent) ?: false
+
+ public open fun onWindowFocusChanged(hasFocus: Boolean) {
+ reactDelegate?.onWindowFocusChanged(hasFocus)
+ }
+
+ public open fun onConfigurationChanged(newConfig: Configuration?) {
+ reactDelegate?.onConfigurationChanged(newConfig)
+ }
+
+ public open fun requestPermissions(
+ permissions: Array