How long does WorkManager persist failed jobs? - android

I have a scenario where I want to retry recently failed jobs but workmanager returns all failed jobs. Is there way to remove old jobs?

For OneTimeWorkRequest, FAILURE it's a final status. It's not going to be re-executed. For PeriodicWorkRequest it is different. Check this blogs:
Introducing WorkManager
WorkManager Periodicity
Also this video covers this.
Back to your question:
Is there a way to remove old jobs?
Yes!
Use WorkManager#pruneWork() to remove jobs in a final state (SUCCEEDED, FAILED and CANCELLED). As you can see from the docs, this method has to be used with caution.
Keep in mind that this removes all jobs that is in the failed state. A way to remove old jobs, is to reduce the amount of time that WorkRequests are keeped in WorkManager's DB setting a custom retention value when you build them. For this use WorkRequest#keepResultsForAtLeast(long duration, TimeUnit timeUnit)

Definitely there is a way to cancel works from WorkManager.
To cancel works from WorkManager you just need to save the UUID of Works.
And you will be able to cancel any work by this piece of code -
WorkManager.getInstance(context).cancelWorkById(UUID); [Deprecated]
Edit:
You can cancel like below - Taken from - https://developer.android.com/topic/libraries/architecture/workmanager/how-to/managing-work#cancelling
// by id
workManager.cancelWorkById(syncWorker.id);
// by name
workManager.cancelUniqueWork("sync");
// by tag
workManager.cancelAllWorkByTag("syncTag");
Under the hood, WorkManager checks the State of the work. If the work is already finished, nothing happens. Otherwise, the work's state is changed to CANCELLED and the work will not run in the future. Any WorkRequest jobs that are dependent on this work will also be CANCELLED.
Currently RUNNING work receives a call to ListenableWorker.onStopped(). Override this method to handle any potential cleanup. See stop a running worker for more information.

Related

What's the alternative manuallly restarting a Work manager Worker

WorkManager API doesn't provide a dedicated restart worker method. Is there a good way to restart a failed worker which has chained workers as well?
For example let's assume we have 3 workers in a chain A->B->C and any of them can fail.
What's the proper way to rebuild the chain since there is no restart method? Assume also that the restart is not synchronous which means that it will happen after user triggered it and not in some specific time frame.
There is Retry and Backoff policy in work manager for retrying your work in case of any error or if you want to retry your work in any case. For details on chained workers retry strategies here is the link.

Android WorkManager use cases

I am reading about WorkManager (https://developer.android.com/guide/background). What confuses me are the 2 conflicting statements. It says WorkManager should be used:
For tasks that should be executed immediately and need continued processing
For tasks that can run at any time in the future can be and deferred
Can someone explain this and show me 2 simple examples with the code of WorkManger that does statement number1 and statement number2 situations. Thanks
WorkManager is basically to offload work from your Process/Activity to dedicated worker meaning your app doesn't need to be active for WorkManager to do your work.
The above mentioned both statements makes sense, I won't be writing code but i'll mention use cases supporting two statements.
Statement1 says tasks which should be executed immediately and need continued processing, it means you can schedule any task right away and will be long running, for instance consider you are uploading some images on click of a button, so you will start the UploadWorker as soon as user clicks upload(instantly) and even if user kills your App, upload should still happen which will be taken care by WorkManager.
Statement2 says tasks that can run at any time in the future can be and deferred, it means you can schedule some work in future point of time and WorkManager will run it at your desired time. A typical example would be backups, you want to back up user data every day at morning, then you can create a BackUpWorker and ask WorkManager to run it at a future time periodically.

Android PeriodicWorkRequestBuilder how to avoid double scheduling?

I'm using the new WorkManager, and was wondering, when I schedule a Periodic work, how can I avoid re-schedule it, is it automatically handled by OS?
If you need to check already running work manager just because you don't want duplicate works. You can simply use enqueueUniquePeriodicWork()
This method allows you to enqueue a uniquely-named
PeriodicWorkRequest, where only one PeriodicWorkRequest of a
particular name can be active at a time. For example, you may only
want one sync operation to be active. If there is one pending, you can
choose to let it run or replace it with your new work.
So you don't need to worry about duplicacy about works.
workmanager.enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.KEEP , photoCheckWork);
Where TAG is unique name by which work manager will check duplicacy.
You can choose between ExistingPeriodicWorkPolicy.KEEP and ExistingPeriodicWorkPolicy.REPLACE.
It's a periodic Worker, so it handles rescheduling the next occurrence automatically.
To avoid that it is re-scheduled, you can return Result.failed() from your Worker or you can cancel the WorkRequest from your app. In this case you should handle cancellation inside your Worker as explained in the documentation.

can I always use WorkManager instead of coroutines?

I wonder why should I bother with rx or coroutines when there is brilliant solution as WorkManager. But for almost all tutorials they use coroutines so may be WorkManager has disadvantages ?
The scope of both is different. WorkManager is to schedule deferrable (for any later time) or immediately.
tasks asynchronously.
As documentation says
The WorkManager API makes it easy to specify deferrable, asynchronous
tasks and when they should run. These APIs let you create a task and
hand it off to WorkManager to run immediately or at an appropriate
time.
On the other hand, coroutines are designed to compute a given task only immediately and asynchronously.
Also
Internally, coroutines and WorkManager work differently. Work manager heavily depends on Android system components like Services, Alarm manager, etc to schedule the work whereas coroutines schedule the work on Worker Threads and also is a language feature unlike WorkManager (API). So it is safe to say that coroutines do not go beyond your application. On the other hand, WorkManager can even execute the given tasks when your application is not active. for instance, background services.
Also as Marko answered, using coroutines will lead to better code readability and quality due to their fundamental design.
I would also like to include ANKO, Its a great library that provides a helpful API around coroutines for Android.
Background tasks fall into one of the following main categories:
Immediate
Deferred
Exact
To categorize a task, answer the following questions:
Does the task need to complete while the user is interacting with the application?
If so, this task should be categorized for immediate execution. If
not, proceed to the second question.
Does the task need to run at an exact time?
If you do need to run a task at an exact time, categorize the task as
exact.
Most tasks don't need to be run at an exact time. Tasks generally allow for slight variations in when they run that are based on conditions such as network availability and remaining battery. Tasks that don't need to be run at an exact time should be categorized as deferred.
Use Kotlin Coroutine when a task needs to execute immediately and if the task will end when the user leaves a certain scope or finishes an interaction.
Use WorkManager when a task needs to execute immediately and need continued processing, even if the user puts the application in the background or the device restarts
Use AlarmManager when a task that needs to be executed at an exact point in time
For more details, visit this link
If your goal is writing clean code without explicitly constructed callbacks you pass to background tasks, then you'll find that coroutines are the only option.
Using coroutines by no means precludes using WorkManager or any other tool for background operations of your choosing. You can adapt the coroutines to any API that provides callbacks as a means to continue the execution with the results of background operations.
From official Documentation:
It is important to note that coroutines is a concurrency framework, whereas WorkManager is a library for persistent work.
WorkManager:
Support for both asynchronous one-off and periodic tasks
Support for constraints such as network conditions, storage space, and charging status
Chaining of complex work requests, including running work in parallel
Output from one work request used as input for the next
Handles API level compatibility back to API level 14(see note)
Works with or without Google Play services
Follows system health best practices
LiveData support to easily display work request state in UI
Waits proper time to run.
Coroutines:
Clean code, works under the hood in a different way. Run immediately.
So depending on your requirements choose the better option.
Has others replied, WorkManager solves a different problem than Kotlin's corountines or a reactive library like RxJava.
WorkManager is now available as beta and additional documentation is produced that hopefully makes this clear.
One of these documents is the blog post I worte with some colleagues: Introducing WorkManager, where you can read:
A common confusion about WorkManager is that it’s for tasks that needs to be run in a “background” thread but don’t need to survive process death. This is not the case. There are other solutions for this use case like Kotlin’s coroutines, ThreadPools, or libraries like RxJava. You can find more information about this use case in the guide to background processing.

Firebase JobDispatcher - how does it work compared to previous APIs (JobScheduler and GcmTaskService)?

Background
Google has multiple solutions for job/task scheduling, such as JobScheduler and GcmTaskService. Each has its own advantages and disadvantages.
Recently, Google presented a new library called "Firebase JobDispatcher".
The problem
Sadly, there is very little to read about this new API. In fact, it's really hard to find anything about it.
Only thing I've found is their announcement video and a sample. But even their, there is not much to know about this API.
The questions
Looking at previous questions, investigations and comparisons I had with the other APIs (here, for example), I'd like to ask how the new API works and know what to take into consideration when using it:
Can a job have parameters that stay with it and can even be modified when needed? They say in the sample "An optional Bundle of user-supplied extras. The default is an empty Bundle." Is this it? Can it be modified by the job upon execution of it?
Can jobs be re-scheduled easily? It is said "A boolean indicating whether the Job should repeat" . How can it be chosen when to re-schedule? I've tried the sample, and chose "Recurring", but it doesn't seem to run again, only once.
Can it be protected vs library's jobs (because of unique ids)?
Does it needs extra care when updating the app (as previous APIs did)? Can jobs still be scheduled after an update of the app? Testing on the sample, it seems the jobs are completely gone after an update of the app. Can it be avoided?
Does it need RECEIVE_BOOT_COMPLETED in case I want the job to still be scheduled even when the device is restarted? The sample seems to have it.
Is it possible to get a list of all scheduled jobs and their information (including parameters), and be able to cancel specific/all of them and even modify them ?
Will a job be removed upon clear-data operation of the app?
Is it possible to tell the job that it's best that it will run in a range of time (example : between 7:00 and 8:00 in the morning)? It is mentioned "ExecutionWindowTrigger-which specifies a time window in which the Job should be executed". Is that it? What happens when it misses this window?
The method onStartJob in JobService class return a boolean and the description for it is "whether there is more work remaining." What does it mean? What does the needsReschedule parameter of jobFinished method mean? Are they related to each other?
Are there any restrictions I should know about? For example minimal & maximal values for each of the functions?
Actually Firebase Android JobDispatcher is a layer of abstraction around job scheduling engines on Android.
And for now they only have one driver implementation for GCM Network Manager.
That means currently it behaves the same way as GCM Network Manager behaves. Hopefully in the future more Drivers will be implemented.
1. Can a job have parameters that stay with it and can even be modified when needed? They say in the sample "An optional Bundle of user-supplied extras. The default is an empty Bundle." . Is this it? Can it be modified by the job upon execution of it?
Yes, Job.Builder has method setExtras with arbitrary bundle which later may be accessed via jobParameters.getExtras().
You cannot modify the bundle (jobParameters contains only getters). You could reschedule your job with flag setReplaceCurrent(true) and specify a new bundle.
2. Can jobs be re-scheduled easily ? It is said "A boolean indicating whether the Job should repeat" . How can it be chosen when to re-schedule? I've tried the sample, and chose "Recurring", but it doesn't seem to run again, only once.
To re-schedule job you need specify setRecurring(true), setTrigger(Trigger.executionWindow(10, 20))
This becomes triggered as soon as the window start deadline is
reached, and drivers are encouraged to run the Job before the window
end if possible.
3. Can it be protected vs library's jobs (because of unique ids) ?
Job tags must be unique in your application. Other apps on the phone have their own 'endpoints' (package name/service name).
To see all scheduled/finished jobs for GooglePlayDriver please use
adb shell dumpsys activity service GcmService
4. Does it needs extra care when updating the app (as previous APIs did) ? Can jobs still be scheduled after an update of the app ? Testing on the sample, it seems the jobs are completely gone after an update of the app. Can it be avoided?
As for GCM Network Manager GooglePlayDriver doesn't reschedule Jobs after Google Play Services or the app is updated.
Here is an open issue for this. So for now this is your responsibility.
5. Does it need RECEIVE_BOOT_COMPLETED in case I want the job to still be scheduled even when the device is restarted? The sample seems to have it.
Yes you need such permission.
Builder has a parameter to control the behavior: setLifetime(Lifetime.FOREVER | UNTIL_NEXT_BOOT)
Of course if you're going to create your own driver you'll have to take care of the lifetime yourself.
6. Is it possible to get a list of all scheduled jobs and their information(including parameters), and be able to cancel specific/all of them and even modify them ?
No, the same as for GCM Network Manager.
But you could track all jobs yourself somehow while scheduling them to play services.
7. Will a job be removed upon clear-data operation of the app?
Yes, the job will be removed. Probably in the previous versions of google play services it behaved differently.
8. Is it possible to tell the job that it's best that it will run in a range of time (example : between 7:00 and 8:00 in the morning) ? It is mentioned "ExecutionWindowTrigger-which specifies a time window in which the Job should be executed" . Is that it? What happens when it misses this window?
Well, you could setup an alarm to be fired at 7:00 and schedule a non-recurring job with executionWindow(0, 60*60). The job will run between 7:00 - 8:00.
You cannot use recurring job because
windowStart - The earliest time (in seconds) the job should be
considered eligible to run. Calculated from when the job was scheduled
(for new jobs) or last run (for recurring jobs).
Also, ExecutionWindowTrigger specifies approximate time. It's not guaranteed it would run at the given window.
If it misses the window the job will run any time later.
9. The method "onStartJob" in "JobService" class return a boolean and the description for it is "whether there is more work remaining." . What does it mean? What does the "needsReschedule" parameter of "jobFinished" method mean? Are they related to each other?
if onStartJob returns false that means you completed your work. No Need to invoke jobFinished. The RESULT_SUCCESS is sent automatically.
if onStartJob returns true that means you started a thread and waiting for results. As soos as you're done you must invoke jobFinished to inform google play services whether the job should be rescheduled or not. If yes the job will be rescheduled depending on RetryStrategy.
10. Are there any restrictions I should know about? For example minimal&maximal values for each of the functions?
onStartJob should offload work to another thread of execution as soon as possible. They provide a SimpleJobService as an example of what is expected from you.
There is no Driver implementation for Lollipop's JobScheduler. Also need to handle the situation when google play services are not available, we should probably implement Driver based on AlarmManager.

Categories

Resources