Search code examples
androidandroid-workmanager

WorkManager - how to execute jobs sequentially


I have a service listening for incoming FCM notifications. When such a notification is received, I run a job with WorkManager.

When multiple notifications are received at the same time, how can I ensure that only one job is executed at the time? The jobs should be executed sequentially. In this case, I want to send an sms and these cannot not be sent simultaneously. (Note that I do other stuff like http requests in this job before and after sending sms, that's why I decided to create a job for it instead of sending an sms straight from the service.)

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    public void onMessageReceived(RemoteMessage remoteMessage) {
        //...
        OneTimeWorkRequest sendSmsWorker = new OneTimeWorkRequest.Builder(SendSmsWorker.class).build();
        WorkManager.getInstance().enqueue(sendSmsWorker);
        //...
    }
}

I've checked the advanced section in the WorkManager docs; it mentions Chained sequences, however these must be chained to each other explicitly (beginWith/then/then/...).


Solution

  • You need to create the jobs as a OneTimeWorkRequest with the same group name, and enqueue them as a unique work with APPEND. This will make all the jobs to be appended to the same chain and execute sequentially.

    Beware that you should always return Result.SUCCESS, or Result.RETRY at most. Returning Result.FAILURE will cancel all the enqueued jobs. If you need to know if a job has failed, then you could set a custom flag in the worker setOutputData to handle such scenario as you may require.

    final String JOB_GROUP_NAME = "your_jobs_group_name";
    
    ......
    
    OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(YOUR_WORK.class)
        .setInputData(YOUR_WORK_DATA_BUILDER.build())
        .build();
    
    final WorkManager workManager = WorkManager.getInstance();
    WorkContinuation work = workManager.beginUniqueWork(JOB_GROUP_NAME, ExistingWorkPolicy.APPEND, request);
    work.enqueue();