camille
camille

Reputation: 328

React Native HeadlessJs task call with android WorkManager

I'm creating a React Native background sync task with Android WorkManager. The doWork method in WorkManager class is called periodically, correctly. The problem I'm facing is how to call the react native function from the doWork method. In my current implementation the JavaScript function is not called.

Headless Task in React Native

// index.js
AppRegistry.registerHeadlessTask('SyncHeadlessTask', () => SyncHeadlessTask);

// SyncHeadlessTask.js
module.exports = async (taskData) => {
    console.log('task running');
};

My HeadlessTask in Java

public class SyncHeadlessTaskService extends HeadlessJsTaskService {
    @Override
    protected @Nullable HeadlessJsTaskConfig getTaskConfig(Intent intent) {
        Bundle extras = intent.getExtras();
        if (extras != null) {
            return new HeadlessJsTaskConfig(
                    "SyncHeadlessTask",
                    Arguments.fromBundle(extras),
                    10000, // timeout for the task
                    true // optional: defines whether or not  the task is allowed in foreground. Default is false
            );
        }
        return null;
    }
}

My Worker

public class SyncWorker extends Worker {
    private static final String TAG = "SyncWorker";

    public SyncWorker(@Nonnull Context context, @Nonnull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    @Nonnull
    @Override
    public Result doWork() {
        return Result.success();
    }
}

My Module

public class SyncModule extends ReactContextBaseJavaModule {
    private static final String MODULE_NAME = "SyncManager";
    private Context mContext;
    private PeriodicWorkRequest workRequest;
    private static final String TAG = "SyncModule";

    SyncModule(@Nonnull ReactApplicationContext reactContext) { 
            super(reactContext);
            mContext = reactContext;
            workRequest = new PeriodicWorkRequest.Builder(SyncWorker.class, 15, TimeUnit.MINUTES).build();
    }

    @ReactMethod
    public void startSync() {
        WorkManager.getInstance().enqueueUniquePeriodicWork("SyncWork", ExistingPeriodicWorkPolicy.KEEP, workRequest);
    }

    @ReactMethod
    public void stopSync() {
        WorkManager.getInstance().cancelUniqueWork("SyncWork");
    }

    @Nonnull
    @Override
    public String getName() {
        return MODULE_NAME;
    }
}

My Package

public class SyncPackage implements ReactPackage  {

    @Nonnull
    @Override
    public List<NativeModule> createNativeModules(@Nonnull ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new SyncModule(reactContext));
        return modules;
    }

    @Nonnull
    @Override
    public List<ViewManager> createViewManagers(@Nonnull ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

Upvotes: 5

Views: 2008

Answers (1)

Eduardo Henrique
Eduardo Henrique

Reputation: 682

You need start your task as a service:

@Nonnull
@Override
public Result doWork() {
    Intent service = new Intent(getApplicationContext(), SyncHeadlessTaskService.class);
    Bundle bundle = new Bundle();
    bundle.putString("foo", "bar");
    service.putExtras(bundle);
    getApplicationContext().startService(service);
    return Result.success();
}

Don't forget to configure your AndroidManifest:

<service android:name="your.package.SyncHeadlessTaskService" />

Upvotes: 3

Related Questions