Skip to content

Commit

Permalink
fix: headless tasks in bridgeless mode (fix #44255)
Browse files Browse the repository at this point in the history
  • Loading branch information
robik committed Jun 21, 2024
1 parent 51e464f commit 3bb9d4a
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
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.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.jstasks.HeadlessJsTaskConfig;
import com.facebook.react.jstasks.HeadlessJsTaskContext;
import com.facebook.react.jstasks.HeadlessJsTaskEventListener;
Expand Down Expand Up @@ -94,19 +97,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);
}
Expand Down Expand Up @@ -166,4 +161,55 @@ 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 ReactHost getReactHost() {
return ((ReactApplication) getApplication()).getReactHost();
}

protected ReactContext getReactContext() {
if (DefaultNewArchitectureEntryPoint.getBridgelessEnabled()) {
ReactHost reactHost = getReactHost();
Assertions.assertNotNull(reactHost, "React host is null in newArchitecture");
return reactHost.getCurrentReactContext();
}

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();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ public interface ReactHost {

public fun onConfigurationChanged(context: Context)

public fun addReactInstanceEventListener(listener: ReactInstanceEventListener)

public fun removeReactInstanceEventListener(listener: ReactInstanceEventListener)

public fun addBeforeDestroyListener(onBeforeDestroy: () -> Unit)

public fun removeBeforeDestroyListener(onBeforeDestroy: () -> Unit)
Expand Down

0 comments on commit 3bb9d4a

Please sign in to comment.