WorkManager
public abstract class WorkManager
WorkManager is the recommended library for persistent work. Scheduled work is guaranteed to execute sometime after its Constraints are met. WorkManager allows observation of work status and the ability to create complex chains of work.
WorkManager uses an underlying job dispatching service when available based on the following criteria:
-
Uses JobScheduler for API 23+
-
Uses a custom AlarmManager + BroadcastReceiver implementation for API 14-22
All work must be done in a ListenableWorker class. A simple implementation, Worker, is recommended as the starting point for most developers. With the optional dependencies, you can also use CoroutineWorker or RxWorker. All background work is given a maximum of ten minutes to finish its execution. After this time has expired, the worker will be signalled to stop.
There are two types of work supported by WorkManager: OneTimeWorkRequest and PeriodicWorkRequest. You can enqueue requests using WorkManager as follows:
WorkManager workManager = WorkManager.getInstance(Context);
workManager.enqueue(new OneTimeWorkRequest.Builder(FooWorker.class).build());
A WorkRequest has an associated id that can be used for lookups and observation as follows:
WorkRequest request = new OneTimeWorkRequest.Builder(FooWorker.class).build();
workManager.enqueue(request);
LiveData<WorkInfo> status = workManager.getWorkInfoByIdLiveData(request.getId());
status.observe(...);
You can also use the id for cancellation:
WorkRequest request = new OneTimeWorkRequest.Builder(FooWorker.class).build();
workManager.enqueue(request);
workManager.cancelWorkById(request.getId());
You can chain work as follows:
WorkRequest request1 = new OneTimeWorkRequest.Builder(FooWorker.class).build();
WorkRequest request2 = new OneTimeWorkRequest.Builder(BarWorker.class).build();
WorkRequest request3 = new OneTimeWorkRequest.Builder(BazWorker.class).build();
workManager.beginWith(request1, request2).then(request3).enqueue();
Each call to beginWith returns a WorkContinuation upon which you can call WorkContinuation.then with a single OneTimeWorkRequest or a list of OneTimeWorkRequest to chain further work. This allows for creation of complex chains of work. For example, to create a chain like this:
A
|
+----------+
| |
B C
|
+----+
| |
D E
you would enqueue them as follows:
WorkContinuation continuation = workManager.beginWith(A);
continuation.then(B).then(D, E).enqueue(); // A is implicitly enqueued here
continuation.then(C).enqueue();
Work is eligible for execution when all of its prerequisites are complete. If any of its prerequisites fail or are cancelled, the work will never run.
WorkRequests can accept Constraints, inputs (see Data), and backoff criteria. WorkRequests can be tagged with human-readable Strings (see WorkRequest.Builder.addTag), and chains of work can be given a uniquely-identifiable name (see beginUniqueWork).
Initializing WorkManager
By default, WorkManager auto-initializes itself using a built-in ContentProvider. ContentProviders are created and run before the Application object, so this allows the WorkManager singleton to be setup before your code can run in most cases. This is suitable for most developers. However, you can provide a custom Configuration by using Configuration.Provider or WorkManager.initialize.
Renaming and Removing ListenableWorker Classes
Exercise caution in renaming classes derived from ListenableWorkers. WorkManager stores the class name in its internal database when the WorkRequest is enqueued so it can later create an instance of that worker when constraints are met. Unless otherwise specified in the WorkManager Configuration, this is done in the default WorkerFactory which tries to reflectively create the ListenableWorker object. Therefore, renaming or removing these classes is dangerous - if there is pending work with the given class, it will fail permanently if the class cannot be found. If you are using a custom WorkerFactory, make sure you properly handle cases where the class is not found so that your code does not crash.
In case it is desirable to rename a class, implement a custom WorkerFactory that instantiates the right ListenableWorker for the old class name.
Summary
Nested types |
|---|
public enum WorkManager.UpdateResult extends EnumAn enumeration of results for |
Public methods |
|
|---|---|
final @NonNull WorkContinuation |
beginUniqueWork(This method allows you to begin unique chains of work for situations where you only want one chain with a given name to be active at a time. |
abstract @NonNull WorkContinuation |
beginUniqueWork(This method allows you to begin unique chains of work for situations where you only want one chain with a given name to be active at a time. |
final @NonNull WorkContinuation |
beginWith(@NonNull OneTimeWorkRequest request)Begins a chain with one or more |
abstract @NonNull WorkContinuation |
beginWith(@NonNull List<@NonNull OneTimeWorkRequest> requests)Begins a chain with one or more |
abstract @NonNull Operation |
Cancels all unfinished work. |
abstract @NonNull Operation |
cancelAllWorkByTag(@NonNull String tag)Cancels all unfinished work with the given tag. |
abstract @NonNull Operation |
cancelUniqueWork(@NonNull String uniqueWorkName)Cancels all unfinished work in the work chain with the given name. |
abstract @NonNull Operation |
cancelWorkById(@NonNull UUID id)Cancels work with the given id if it isn't finished. |
abstract @NonNull PendingIntent |
Creates a |
final @NonNull Operation |
enqueue(@NonNull WorkRequest request)Enqueues one item for background processing. |
abstract @NonNull Operation |
enqueue(@NonNull List<@NonNull WorkRequest> requests)Enqueues one or more items for background processing. |
abstract @NonNull Operation |
enqueueUniquePeriodicWork(This method allows you to enqueue a uniquely-named |
@NonNull Operation |
enqueueUniqueWork(This method allows you to enqueue |
abstract @NonNull Operation |
enqueueUniqueWork(This method allows you to enqueue |
abstract @NonNull Configuration |
The |
static @NonNull WorkManager |
This method is deprecated. Use the overload receiving Context |
static @NonNull WorkManager |
getInstance(@NonNull Context context)Retrieves the |
abstract @NonNull ListenableFuture<@NonNull Long> |
Gets a |
abstract @NonNull LiveData<@NonNull Long> |
Gets a |
abstract @NonNull ListenableFuture<WorkInfo> |
getWorkInfoById(@NonNull UUID id)Gets a |
abstract @NonNull Flow<WorkInfo> |
|
abstract @NonNull LiveData<WorkInfo> |
|
abstract @NonNull ListenableFuture<@NonNull List<@NonNull WorkInfo>> |
getWorkInfos(@NonNull WorkQuery workQuery)Gets the |
abstract @NonNull ListenableFuture<@NonNull List<@NonNull WorkInfo>> |
getWorkInfosByTag(@NonNull String tag)Gets a |
abstract @NonNull Flow<@NonNull List<@NonNull WorkInfo>> |
|
abstract @NonNull LiveData<@NonNull List<@NonNull WorkInfo>> |
Gets a |
abstract @NonNull Flow<@NonNull List<@NonNull WorkInfo>> |
getWorkInfosFlow(@NonNull WorkQuery workQuery)Gets the |
abstract @NonNull ListenableFuture<@NonNull List<@NonNull WorkInfo>> |
getWorkInfosForUniqueWork(@NonNull String uniqueWorkName)Gets a |
abstract @NonNull Flow<@NonNull List<@NonNull WorkInfo>> |
getWorkInfosForUniqueWorkFlow(@NonNull String uniqueWorkName)Gets a |
abstract @NonNull LiveData<@NonNull List<@NonNull WorkInfo>> |
getWorkInfosForUniqueWorkLiveData(@NonNull String uniqueWorkName)Gets a |
abstract @NonNull LiveData<@NonNull List<@NonNull WorkInfo>> |
getWorkInfosLiveData(@NonNull WorkQuery workQuery)Gets the |
static void |
initialize(@NonNull Context context, @NonNull Configuration configuration)Used to do a one-time initialization of the |
static boolean |
Provides a way to check if |
abstract @NonNull Operation |
Prunes all eligible finished work from the internal database. |
abstract @NonNull ListenableFuture<@NonNull WorkManager.UpdateResult> |
updateWork(@NonNull WorkRequest request)Updates the work with the new specification. |
Public methods
beginUniqueWork
public final @NonNull WorkContinuation beginUniqueWork(
@NonNull String uniqueWorkName,
@NonNull ExistingWorkPolicy existingWorkPolicy,
@NonNull OneTimeWorkRequest request
)
This method allows you to begin unique chains of work for situations where you only want one chain with a given name to 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.
The uniqueWorkName uniquely identifies this set of work.
If this method determines that new work should be enqueued and run, all records of previous work with uniqueWorkName will be pruned. If this method determines that new work should NOT be run, then the entire chain will be considered a no-op.
If any work in the chain fails or is cancelled, all of its dependent work inherits that state and will never run. This is particularly important if you are using APPEND as your ExistingWorkPolicy.
| Parameters | |
|---|---|
@NonNull String uniqueWorkName |
A unique name which for this chain of work |
@NonNull ExistingWorkPolicy existingWorkPolicy |
|
@NonNull OneTimeWorkRequest request |
The |
| Returns | |
|---|---|
@NonNull WorkContinuation |
A |
beginUniqueWork
public abstract @NonNull WorkContinuation beginUniqueWork(
@NonNull String uniqueWorkName,
@NonNull ExistingWorkPolicy existingWorkPolicy,
@NonNull List<@NonNull OneTimeWorkRequest> requests
)
This method allows you to begin unique chains of work for situations where you only want one chain with a given name to 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.
The uniqueWorkName uniquely identifies this set of work.
If this method determines that new work should be enqueued and run, all records of previous work with uniqueWorkName will be pruned. If this method determines that new work should NOT be run, then the entire chain will be considered a no-op.
If any work in the chain fails or is cancelled, all of its dependent work inherits that state and will never run. This is particularly important if you are using APPEND as your ExistingWorkPolicy.
| Parameters | |
|---|---|
@NonNull String uniqueWorkName |
A unique name which for this chain of work |
@NonNull ExistingWorkPolicy existingWorkPolicy |
An |
@NonNull List<@NonNull OneTimeWorkRequest> requests |
One or more |
| Returns | |
|---|---|
@NonNull WorkContinuation |
A |
beginWith
public final @NonNull WorkContinuation beginWith(@NonNull OneTimeWorkRequest request)
Begins a chain with one or more OneTimeWorkRequests, which can be enqueued together in the future using WorkContinuation.enqueue.
If any work in the chain fails or is cancelled, all of its dependent work inherits that state and will never run.
| Parameters | |
|---|---|
@NonNull OneTimeWorkRequest request |
One or more |
| Returns | |
|---|---|
@NonNull WorkContinuation |
A |
beginWith
public abstract @NonNull WorkContinuation beginWith(@NonNull List<@NonNull OneTimeWorkRequest> requests)
Begins a chain with one or more OneTimeWorkRequests, which can be enqueued together in the future using WorkContinuation.enqueue.
If any work in the chain fails or is cancelled, all of its dependent work inherits that state and will never run.
| Parameters | |
|---|---|
@NonNull List<@NonNull OneTimeWorkRequest> requests |
One or more |
| Returns | |
|---|---|
@NonNull WorkContinuation |
A |
cancelAllWork
public abstract @NonNull Operation cancelAllWork()
Cancels all unfinished work. Use this method with extreme caution! By invoking it, you will potentially affect other modules or libraries in your codebase. It is strongly recommended that you use one of the other cancellation methods at your disposal.
Upon cancellation, ListenableFuture returned by ListenableWorker.startWork will be cancelled. Also ListenableWorker.onStopped will be invoked for any affected workers.
cancelAllWorkByTag
public abstract @NonNull Operation cancelAllWorkByTag(@NonNull String tag)
Cancels all unfinished work with the given tag. Note that cancellation is a best-effort policy and work that is already executing may continue to run. Upon cancellation, ListenableFuture returned by ListenableWorker.startWork will be cancelled. Also ListenableWorker.onStopped will be invoked for any affected workers.
cancelUniqueWork
public abstract @NonNull Operation cancelUniqueWork(@NonNull String uniqueWorkName)
Cancels all unfinished work in the work chain with the given name. Note that cancellation is a best-effort policy and work that is already executing may continue to run. Upon cancellation, ListenableFuture returned by ListenableWorker.startWork will be cancelled. Also ListenableWorker.onStopped will be invoked for any affected workers.
cancelWorkById
public abstract @NonNull Operation cancelWorkById(@NonNull UUID id)
Cancels work with the given id if it isn't finished. Note that cancellation is a best-effort policy and work that is already executing may continue to run. Upon cancellation, ListenableFuture returned by ListenableWorker.startWork will be cancelled. Also ListenableWorker.onStopped will be invoked for any affected workers.
createCancelPendingIntent
public abstract @NonNull PendingIntent createCancelPendingIntent(@NonNull UUID id)
Creates a PendingIntent which can be used to cancel a WorkRequest with the given id.
| Parameters | |
|---|---|
@NonNull UUID id |
The |
| Returns | |
|---|---|
@NonNull PendingIntent |
The |
enqueue
public final @NonNull Operation enqueue(@NonNull WorkRequest request)
Enqueues one item for background processing.
| Parameters | |
|---|---|
@NonNull WorkRequest request |
The |
enqueue
public abstract @NonNull Operation enqueue(@NonNull List<@NonNull WorkRequest> requests)
Enqueues one or more items for background processing.
| Parameters | |
|---|---|
@NonNull List<@NonNull WorkRequest> requests |
One or more |
enqueueUniquePeriodicWork
public abstract @NonNull Operation enqueueUniquePeriodicWork(
@NonNull String uniqueWorkName,
@NonNull ExistingPeriodicWorkPolicy existingPeriodicWorkPolicy,
@NonNull PeriodicWorkRequest request
)
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.
The uniqueWorkName uniquely identifies this PeriodicWorkRequest.
| Parameters | |
|---|---|
@NonNull String uniqueWorkName |
A unique name which for this operation |
@NonNull ExistingPeriodicWorkPolicy existingPeriodicWorkPolicy |
|
@NonNull PeriodicWorkRequest request |
A |
enqueueUniqueWork
public @NonNull Operation enqueueUniqueWork(
@NonNull String uniqueWorkName,
@NonNull ExistingWorkPolicy existingWorkPolicy,
@NonNull OneTimeWorkRequest request
)
This method allows you to enqueue work requests to a uniquely-named WorkContinuation, where only one continuation 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.
The uniqueWorkName uniquely identifies this WorkContinuation.
| Parameters | |
|---|---|
@NonNull String uniqueWorkName |
A unique name which for this operation |
@NonNull ExistingWorkPolicy existingWorkPolicy |
An |
@NonNull OneTimeWorkRequest request |
The |
enqueueUniqueWork
public abstract @NonNull Operation enqueueUniqueWork(
@NonNull String uniqueWorkName,
@NonNull ExistingWorkPolicy existingWorkPolicy,
@NonNull List<@NonNull OneTimeWorkRequest> requests
)
This method allows you to enqueue work requests to a uniquely-named WorkContinuation, where only one continuation 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.
The uniqueWorkName uniquely identifies this WorkContinuation.
| Parameters | |
|---|---|
@NonNull String uniqueWorkName |
A unique name which for this operation |
@NonNull ExistingWorkPolicy existingWorkPolicy |
|
@NonNull List<@NonNull OneTimeWorkRequest> requests |
|
getConfiguration
public abstract @NonNull Configuration getConfiguration()
The Configuration instance that WorkManager was initialized with.
public static @NonNull WorkManagergetInstance()
Retrieves the default singleton instance of WorkManager.
| Returns | |
|---|---|
@NonNull WorkManager |
The singleton instance of |
| Throws | |
|---|---|
kotlin.IllegalStateException |
If WorkManager is not initialized properly as per the exception message. |
getInstance
public static @NonNull WorkManager getInstance(@NonNull Context context)
Retrieves the default singleton instance of WorkManager.
| Returns | |
|---|---|
@NonNull WorkManager |
The singleton instance of |
| Throws | |
|---|---|
kotlin.IllegalStateException |
If WorkManager is not initialized properly |
getLastCancelAllTimeMillis
public abstract @NonNull ListenableFuture<@NonNull Long> getLastCancelAllTimeMillis()
Gets a ListenableFuture of the last time all work was cancelled. This method is intended for use by library and module developers who have dependent data in their own repository that must be updated or deleted in case someone cancels their work without their prior knowledge.
| Returns | |
|---|---|
@NonNull ListenableFuture<@NonNull Long> |
A |
getLastCancelAllTimeMillisLiveData
public abstract @NonNull LiveData<@NonNull Long> getLastCancelAllTimeMillisLiveData()
Gets a LiveData of the last time all work was cancelled. This method is intended for use by library and module developers who have dependent data in their own repository that must be updated or deleted in case someone cancels their work without their prior knowledge.
getWorkInfoById
public abstract @NonNull ListenableFuture<WorkInfo> getWorkInfoById(@NonNull UUID id)
Gets a ListenableFuture of the WorkInfo for a given work id.
| Returns | |
|---|---|
@NonNull ListenableFuture<WorkInfo> |
A |
getWorkInfoByIdFlow
public abstract @NonNull Flow<WorkInfo> getWorkInfoByIdFlow(@NonNull UUID id)
getWorkInfoByIdLiveData
public abstract @NonNull LiveData<WorkInfo> getWorkInfoByIdLiveData(@NonNull UUID id)
getWorkInfos
public abstract @NonNull ListenableFuture<@NonNull List<@NonNull WorkInfo>> getWorkInfos(@NonNull WorkQuery workQuery)
Gets the ListenableFuture of the List of WorkInfo for all work referenced by the WorkQuery specification.
| Returns | |
|---|---|
@NonNull ListenableFuture<@NonNull List<@NonNull WorkInfo>> |
A |
getWorkInfosByTag
public abstract @NonNull ListenableFuture<@NonNull List<@NonNull WorkInfo>> getWorkInfosByTag(@NonNull String tag)
Gets a ListenableFuture of the WorkInfo for all work for a given tag.
| Returns | |
|---|---|
@NonNull ListenableFuture<@NonNull List<@NonNull WorkInfo>> |
A |
getWorkInfosByTagFlow
public abstract @NonNull Flow<@NonNull List<@NonNull WorkInfo>> getWorkInfosByTagFlow(@NonNull String tag)
getWorkInfosByTagLiveData
public abstract @NonNull LiveData<@NonNull List<@NonNull WorkInfo>> getWorkInfosByTagLiveData(@NonNull String tag)
Gets a LiveData of the WorkInfo for all work for a given tag.
getWorkInfosFlow
public abstract @NonNull Flow<@NonNull List<@NonNull WorkInfo>> getWorkInfosFlow(@NonNull WorkQuery workQuery)
Gets the Flow of the List of WorkInfo for all work referenced by the WorkQuery specification.
getWorkInfosForUniqueWork
public abstract @NonNull ListenableFuture<@NonNull List<@NonNull WorkInfo>> getWorkInfosForUniqueWork(@NonNull String uniqueWorkName)
Gets a ListenableFuture of the WorkInfo for all work in a work chain with a given unique name.
| Returns | |
|---|---|
@NonNull ListenableFuture<@NonNull List<@NonNull WorkInfo>> |
A |
getWorkInfosForUniqueWorkFlow
public abstract @NonNull Flow<@NonNull List<@NonNull WorkInfo>> getWorkInfosForUniqueWorkFlow(@NonNull String uniqueWorkName)
Gets a Flow of the WorkInfo for all work in a work chain with a given unique name.
getWorkInfosForUniqueWorkLiveData
public abstract @NonNull LiveData<@NonNull List<@NonNull WorkInfo>> getWorkInfosForUniqueWorkLiveData(@NonNull String uniqueWorkName)
Gets a LiveData of the WorkInfo for all work in a work chain with a given unique name.
getWorkInfosLiveData
public abstract @NonNull LiveData<@NonNull List<@NonNull WorkInfo>> getWorkInfosLiveData(@NonNull WorkQuery workQuery)
Gets the LiveData of the List of WorkInfo for all work referenced by the WorkQuery specification.
initialize
public static void initialize(@NonNull Context context, @NonNull Configuration configuration)
Used to do a one-time initialization of the WorkManager singleton with a custom Configuration. By default, this method should not be called because WorkManager is automatically initialized. To initialize WorkManager yourself, please follow these steps:
-
Disable
androidx.work.WorkManagerInitializerin your manifest. -
Invoke this method in
Application#onCreateor aContentProvider. Note that this method must be invoked in one of these two places or you risk getting aNullPointerExceptioningetInstance.
This method throws an IllegalStateException when attempting to initialize in direct boot mode.
This method throws an exception if it is called multiple times.
| Parameters | |
|---|---|
@NonNull Context context |
A |
@NonNull Configuration configuration |
The |
| See also | |
|---|---|
Configuration.Provider |
for on-demand initialization. |
isInitialized
public static boolean isInitialized()
Provides a way to check if WorkManager is initialized in this process.
| Returns | |
|---|---|
boolean |
|
pruneWork
public abstract @NonNull Operation pruneWork()
Prunes all eligible finished work from the internal database. Eligible work must be finished (WorkInfo.State.SUCCEEDED, WorkInfo.State.FAILED, or WorkInfo.State.CANCELLED), with zero unfinished dependents.
Use this method with caution; by invoking it, you (and any modules and libraries in your codebase) will no longer be able to observe the WorkInfo of the pruned work. You do not normally need to call this method - WorkManager takes care to auto-prune its work after a sane period of time. This method also ignores the OneTimeWorkRequest.Builder.keepResultsForAtLeast policy.
updateWork
public abstract @NonNull ListenableFuture<@NonNull WorkManager.UpdateResult> updateWork(@NonNull WorkRequest request)
Updates the work with the new specification. A WorkRequest passed as parameter must have an id set with WorkRequest.Builder.setId that matches an id of the previously enqueued work.
It preserves enqueue time, e.g. if a work was enqueued 3 hours ago and had 6 hours long initial delay, after the update it would be still eligible for run in 3 hours, assuming that initial delay wasn't updated.
If the work being updated is currently running the returned ListenableFuture will be completed with UpdateResult.APPLIED_FOR_NEXT_RUN. In this case the current run won't be interrupted and will continue to rely on previous state of the request, e.g. using old constraints, tags etc. However, on the next run, e.g. retry of one-time Worker or another iteration of periodic worker, the new worker specification will be used.
If the one time work that is updated is already finished the returned ListenableFuture will be completed with UpdateResult.NOT_APPLIED.
If update can be applied immediately, e.g. the updated work isn't currently running, the returned ListenableFuture will be completed with UpdateResult.APPLIED_IMMEDIATELY.
If the work with the given id (request.getId()) doesn't exist the returned ListenableFuture will be completed exceptionally with IllegalArgumentException.
Worker type can't be changed, OneTimeWorkRequest can't be updated to PeriodicWorkRequest and otherwise, the returned ListenableFuture will be completed with IllegalArgumentException.
| Parameters | |
|---|---|
@NonNull WorkRequest request |
the new specification for the work. |
| Returns | |
|---|---|
@NonNull ListenableFuture<@NonNull WorkManager.UpdateResult> |
a |