WorkManager executing enqueueUniquePeriodicWork() multiple times at once?

Viewed 1383

I'm new to this so do let me know if the question is badly worded! I have an Android app that needs to execute a task roughly every 15 minutes even if the phone is on lock. The context is: - Im targeting SDK 23 or higher - The task 1) takes the user's location 2) makes a call to an HTTPS API using OKHttpClient, then 3) sends the results to a Firestore database

I'm using WorkManager to try to achieve this goal. However, the problem is every time it executes, it does so 8 - 9 times and it is very irregular in timing. I can see this from the Firestore entries and Logcat.

Is WorkManager even the right way to go about this task? I am using

implementation "androidx.work:work-runtime:2.0.1"
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;
import androidx.work.ExistingPeriodicWorkPolicy;

I see others have had this issue: Android Worker execute the job multiple times

//In MainActivity.java: 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder(
                PeriodicReadings.class, 15, TimeUnit.MINUTES).build();

        WorkManager.getInstance().enqueueUniquePeriodicWork("PWR", ExistingPeriodicWorkPolicy.REPLACE, periodicWorkRequest);

//In PeriodicReadings.java:

    @NonNull
    @Override
    public Result doWork() {
        getReadings(); //work to be done 
        return Result.success();
    }

Every 15 minutes I expected a reading to appear in the Firestore database, but instead I see batches of 8 - 9 readings appear at irregular intervals varying every 15minutes - 2 hours.

I have tried clean and rebuild, invalidating and restarting cache, and also reloading the app on the phone.

3 Answers

Try this out:

WorkManager.getInstance().enqueueUniquePeriodicWork("PWR",ExistingPeriodicWorkPolicy.KEEP, periodicWorkRequest);

KEEP: If a previous worker exists, your new attempt is simply ignored, else your new worker is enqueued.

REPLACE: If a previous worker exists, it is cancelled, leading to a state CANCELLED for it. Then or else, your new worker is enqueued.

Well it's not the best way but it would be better if you cancel all your Work managers task before starting your WorkManager.getInstance().enqueueUniquePeriodicWork("PWR", ExistingPeriodicWorkPolicy.REPLACE, periodicWorkRequest);

OR

Check if there is already a Workmanager is in queue then don't start it again in OnCreate.

You are enqueueing work in your Activity#onCreate() so every time your activity gets created you are enqueuing a new WorkRequest. Which is why you will see multiple instances of the work request. You probably want the enqueueUniquePeriodicWork() API.

Related