Problem with Androids "OneTimeWorker", it executes when app starts

Viewed 121

Short description:


I am currently working in Android Studio with OneTimeWorkRequest(). What I want to achieve is to create a background-worker that runs and repeats "almost" on a specific time, like every hour (09:00, 10:00, etc). It has not to be exactly but should not variate too much after a long time running.

I already know that the worker only runs every 15 minutes at minimum due to the android restrictions (like battery saving mechanism and so on). I do not need the worker to run exactly at the given time but at least almost around a target time! That is why I used OneTimeWorkRequest() instead of PeriodicWorkRequest() because I needed the possibility of variation in setting the intervall for the worker since the documentation mentions that the PeriodicWorkRequest() will add up a time delay from one execution to another.

What I did:


I have created a custom Worker-Class and used OneTimeWorkRequest() in my MainActivity to create the BackgroundWorker. I have set the setInitialDelay() of the worker to 20 minutes for testing purpose. Everytime the worker did doWork() it creates another OneTimeWorkRequest() at the end of execution so a chain of worker gets created in at a given time. The worker gets queued with the enqueueUniqueWork() method from the WorkerManager.getInstance(context) and the intervall is calculated.

The Problem:


Everytime I close the App's process and reopen the App, the Worker executes directly. Also when I list all worker created by the specified Tag, it lists many workers. It seems to me that my logic created too many worker without closing the old ones, or it creates multiple ones? Yet I thought the enqueueUniqueWork() would replace or create only unique/single worker with the given tag... In addition the WorkManager.getInstance(this).cancelAllWorkByTag(TAG) function does not close the (later in this post) listed worker!

Right now it is not important for me how to create worker execution at a given time but how to create consistent Worker-Chain with OneTimeWorkRequest() that do not create a "worker-overload", if possible. Yet I am open for alternative solutions.

So again:

  • Why does the worker execute after closing the process and opening the App?
  • Why are there so many workers listed?
  • Does my logic create one single worker chain or multiple ones?
  • Is my logic even consistent/usable like this?
  • Why are the worker not closing using .cancelAllWorkByTag(TAG)?

Code:


// MainActivity.java:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    ...
    
        // For testing purpose used...
    ListScheduledWorker(TAG);
    WorkManager.getInstance(this).cancelAllWorkByTag(TAG);
    ListScheduledWorker(TAG);
        // ...until here.

    CreateOneTimeWorker();
    
    ...
}

private void CreateOneTimeWorker(){
    long timeValue = 20;
    TimeUnit timeUnit = TimeUnit.MINUTES;
    String workerTag = MhdExpirationPushNotification.class.getSimpleName();
    OneTimeWorkRequest worker = new OneTimeWorkRequest.Builder(CustomPeriodicallyWorker.class)
            .setInitialDelay(timeValue, timeUnit)
            .addTag(workerTag)
            .setConstraints(Constraints.NONE)
            .build();
    WorkManager.getInstance(this).enqueueUniqueWork(workerTag, ExistingWorkPolicy.KEEP, worker);
}

// CustomPeriodicallyWorker.java:

public Result doWork(){
    Log.v(TAG, "Work is in progress");
    try {
        CustomDateFormatter currentDateTime = new CustomDateFormatter();
        CustomDateFormatter targetDateTime = new CustomDateFormatter();
        targetDateTime.AddMinutes(20);
        long timeDifference = targetDateTime.GetDateTime().getTime() - currentDateTime.GetDateTime().getTime();

        OneTimeWorkRequest worker = new OneTimeWorkRequest.Builder(CustomPeriodicallyWorker.class)
                .setInitialDelay(timeDifference, TimeUnit.MILLISECONDS)
                .addTag(TAG)
                .build();
        WorkManager.getInstance(context).enqueueUniqueWork(TAG, ExistingWorkPolicy.REPLACE, worker);

    } catch (Exception e) {
        e.printStackTrace();
    }
    Log.v(TAG, "Work finished");;

    return Result.success();
}

// The function in MainActivity.java that lists all scheduled worker:

private boolean ListScheduledWorker(String tag) {
    WorkManager instance = WorkManager.getInstance(this);
    ListenableFuture<List<WorkInfo>> statuses = instance.getWorkInfosByTag(tag);
    try {
        boolean running = false;
        List<WorkInfo> workInfoList = statuses.get();
        for (WorkInfo workInfo : workInfoList) {
            Log.i(TAG, "Scheduled Worker running with ID: " + workInfo.getId());
            WorkInfo.State state = workInfo.getState();
            running = state == WorkInfo.State.RUNNING | state == WorkInfo.State.ENQUEUED;
        }
        return running;
    } catch (ExecutionException e) {
        e.printStackTrace();
        return false;
    } catch (InterruptedException e) {
        e.printStackTrace();
        return false;
    }
}

// The ListScheduledWorker(String tag) prints me this out:

I/TAG: Scheduled Worker running with ID: 27bb31ed-5984-434f-a6ca-08b50462b3df
    Scheduled Worker running with ID: 2d6abbb1-3a55-4652-83ca-60617631e0ab
    Scheduled Worker running with ID: 3e89851d-7e0b-410d-86b8-e664a4d710f0
    Scheduled Worker running with ID: 430e77b2-5fb8-4596-acd5-51e35a6a538b
    Scheduled Worker running with ID: 73b57443-8195-4c55-a24d-bd643b88e13c
    Scheduled Worker running with ID: 74c8a44b-2a9a-4448-b3d5-e2c085be3d06
    Scheduled Worker running with ID: 75deabd3-08e8-403a-b9d7-6c23f114a908
    Scheduled Worker running with ID: 89ec6239-e215-4ea1-a7bc-fcaa8b63065c
    Scheduled Worker running with ID: 9363038e-be74-4a83-9d1f-eeeda35ebbfa
    Scheduled Worker running with ID: 9a09806f-f0cf-43c1-a4f6-1f10448904f4
    Scheduled Worker running with ID: c6686c56-fd8a-4866-8eb1-5124654b6cb7
    Scheduled Worker running with ID: d3343328-db8f-4c8d-8055-a1acfc9d1c5c
    Scheduled Worker running with ID: dea9272f-6770-45f0-ba66-2c845e156d7b
    Scheduled Worker running with ID: eb4c111c-97c5-46c3-ba5c-ceefe652398c
    Scheduled Worker running with ID: fc71f8dc-1785-43cd-9a44-1fe4e913ca6e
    Scheduled Worker running with ID: fca1bcea-97d9-4066-8b5a-8b5496ffed1e

..and the list grows everytime when I rebuild/restart the App in Android Studio or on my physical device.

0 Answers
Related