diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 98e0fc91d6e72e..094537dd7ff26e 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -46,6 +46,8 @@ public class com/facebook/react/DebugCorePackage$$ReactModuleInfoProvider : com/ public abstract class com/facebook/react/HeadlessJsTaskService : android/app/Service, com/facebook/react/jstasks/HeadlessJsTaskEventListener { public fun ()V public static fun acquireWakeLockNow (Landroid/content/Context;)V + protected fun getReactContext ()Lcom/facebook/react/bridge/ReactContext; + protected fun getReactHost ()Lcom/facebook/react/ReactHost; protected fun getReactNativeHost ()Lcom/facebook/react/ReactNativeHost; protected fun getTaskConfig (Landroid/content/Intent;)Lcom/facebook/react/jstasks/HeadlessJsTaskConfig; public fun onBind (Landroid/content/Intent;)Landroid/os/IBinder; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/HeadlessJsTaskService.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/HeadlessJsTaskService.java index 70a8f7c105d47d..c5dfeb33de14f9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/HeadlessJsTaskService.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/HeadlessJsTaskService.java @@ -14,10 +14,12 @@ import android.content.Intent; import android.os.IBinder; import android.os.PowerManager; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.UiThreadUtil; +import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.jstasks.HeadlessJsTaskConfig; import com.facebook.react.jstasks.HeadlessJsTaskContext; import com.facebook.react.jstasks.HeadlessJsTaskEventListener; @@ -94,19 +96,11 @@ public static void acquireWakeLockNow(Context context) { protected void startTask(final HeadlessJsTaskConfig taskConfig) { UiThreadUtil.assertOnUiThread(); acquireWakeLockNow(this); - final ReactInstanceManager reactInstanceManager = - getReactNativeHost().getReactInstanceManager(); - ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); + + ReactContext reactContext = getReactContext(); + if (reactContext == null) { - reactInstanceManager.addReactInstanceEventListener( - new ReactInstanceEventListener() { - @Override - public void onReactContextInitialized(ReactContext reactContext) { - invokeStartTask(reactContext, taskConfig); - reactInstanceManager.removeReactInstanceEventListener(this); - } - }); - reactInstanceManager.createReactContextInBackground(); + createReactContextAndScheduleTask(taskConfig); } else { invokeStartTask(reactContext, taskConfig); } @@ -166,4 +160,54 @@ public void onHeadlessJsTaskFinish(int taskId) { protected ReactNativeHost getReactNativeHost() { return ((ReactApplication) getApplication()).getReactNativeHost(); } + + /** + * Get the {@link ReactHost} used by this app. By default, assumes {@link #getApplication()} is an + * instance of {@link ReactApplication} and calls {@link ReactApplication#getReactHost()}. This + * method assumes it is called in new architecture and returns null if not. + */ + protected @Nullable ReactHost getReactHost() { + return ((ReactApplication) getApplication()).getReactHost(); + } + + protected ReactContext getReactContext() { + if (ReactFeatureFlags.enableBridgelessArchitecture) { + ReactHost reactHost = getReactHost(); + Assertions.assertNotNull(reactHost, "getReactHost() is null in New Architecture"); + return reactHost.getCurrentReactContext(); + } else { + final ReactInstanceManager reactInstanceManager = + getReactNativeHost().getReactInstanceManager(); + return reactInstanceManager.getCurrentReactContext(); + } + } + + private void createReactContextAndScheduleTask(final HeadlessJsTaskConfig taskConfig) { + final ReactHost reactHost = getReactHost(); + + if (reactHost == null) { // old arch + final ReactInstanceManager reactInstanceManager = + getReactNativeHost().getReactInstanceManager(); + + reactInstanceManager.addReactInstanceEventListener( + new ReactInstanceEventListener() { + @Override + public void onReactContextInitialized(@NonNull ReactContext reactContext) { + invokeStartTask(reactContext, taskConfig); + reactInstanceManager.removeReactInstanceEventListener(this); + } + }); + reactInstanceManager.createReactContextInBackground(); + } else { // new arch + reactHost.addReactInstanceEventListener( + new ReactInstanceEventListener() { + @Override + public void onReactContextInitialized(@NonNull ReactContext reactContext) { + invokeStartTask(reactContext, taskConfig); + reactHost.removeReactInstanceEventListener(this); + } + }); + reactHost.start(); + } + } }