Android WorkManager

Learn via video courses
Topics Covered

Overview

WorkManager Android is an API provided by the Jetpack library to execute background tasks that can be completed at a specific or later time along with ensuring the necessary constraints. Additionally, the work can be executed even if the app is not running or if the device reboots.

Types of Persistent Work

Persistent work in WorkManager Android refers to any work that is mandated for execution, even in scenarios where the app is killed or the device has been restarted. This is possible by storing the work in persistent storage and rescheduling it if the conditions for the same are favorable.

types of persistent work

WorkManager provides three types of persistent work:

Immediate

Immediate work is the one that needs to be executed as soon as possible. They require immediate attention and must begin immediately, such as syncing data inside an app or showing a notification in real time.

Long Running

Long Running work might run for a longer duration of time. Such works involve downloading a huge file or enormous data processing. Usually, Long Running work may run longer than 10 minutes to some hours or days and even survive device reboots and app restarts. It can be interrupted by the system if necessary to preserve system resources.

Deferrable

This type of work will be executed regularly at specific times or intervals. It can either be a data backup or a daily reminder. Like a Long-Running work, it can also survive device reboots and app restarts.

Moreover, they can be deferred to at a later time, if needed (when the device is in charging mode or connected to a specific network where the update cannot take place) because they aren't critical.

Features

WorkManager provides a number of features that make it a powerful tool for managing background tasks.

Work Constraints

Using work constraints in WorkManager Android, the work can be scheduled based on the factors such as the battery level, network connectivity, or if the device is idle. The constraints allow us to ensure that the app is not executing any unnecessary work that would drain more battery or consume more data on a metered connection.

Robust Scheduling

WorkManager facilitates a robust scheduling system that is capable of handling numerous scenarios such as rescheduling work that was not completed earlier due to inadequate fulfilling conditions or also retrying a failed work.

With a robust scheduling system, work can also be uniquely named and tagged. This helps in monitoring groups of work easily. The work that is scheduled is stored in an SQLite database.

Expedited Work

WorkManager provides a mechanism for expediting work that needs to be executed immediately, such as in response to a user action or system event. This allows you to ensure that your app is responsive and provides a good user experience.

Flexible Retry Policy

WorkManager Android provides a way of customizing how and when work should be retried if it fails. With this policy, we can determine the maximum number of retries.

WorkManager Android comprises two retry policies:

  • Exponential backoff: WorkManager would retry the work by increasing the delay between each retry.
  • Linear backoff: WorkManager would retry the work with a fixed delay time between each retry.

Moreover, you can also use a Custom retry strategy for defining your own criteria for retrying work.

Work Chaining

Work chaining is a feature of Android WorkManager that allows you to specify a sequence of work to be executed in a specific order, with dependencies between them. This is useful when you have complex workflows that require multiple steps or when you want to ensure that your work is executed in a specific order.

The use of work chaining is demonstarted in the upcoming section.

When to Use WorkManager while Working with Background Processing?

We should think about using WorkManager when we need to schedule work to run at a given time or in reaction to a specific event, or when we need to execute background work that has to run even while the app is not in the foreground.

WorkManager also ensures that the work is executed even if the device restarts or the app is closed.

Creating a Background Work with Android WorkManager

creting a background work with android workmanager

For instance, let's consider creating a file, compressing it, and uploading it as well. So, we require three OneTimeWorkRequest objects from the following Worker classes:

CreateFileWorker, CompressFileWorker, and UploadFileWorker.

We'll create a public class CreateFileWorker that extends Worker. We pass the required Context and WorkerParameters arguments to the superclass constructor via the constructor of the CreateFileWorker class.

Here's the sample code for CreateFileWorker class in Java and Kotlin.

Java:

The doWork() method is called which overrides the method from the Parent class and executes the background work. Inside this method, we have called the createFile() method and have returned a Result.success() object.

Kotlin:

Similarly, we can create the CompressFileWorker and UploadFileWorker classes as well.

Since we have defined all our worker classes, we can now create a WorkRequest and schedule it using the WorkManager API.

The next section discuss the use of WorkRequests in WorkManager Android.

Working with WorkRequests

WorkRequests are used to specify the work that needs to be executed in the background. WorkRequest in Android is an abstract class in the WorkManager library that defines a request to perform a specific piece of work in an application. With WorkRequest in Android, we can specify the type of work to be done and also the constraints that should be fulfilled in order to execute the work.

working with workrequests

When we create a WorkRequest, an ID is assigned to the request along with a tag in order to make it easily accessible and also a backoff policy (as we discussed earlier) to facilitate the rescheduling of work, if needed.

There are three types of WorkRequests: OneTimeWorkRequest, PeriodicWorkRequest, and UniqueWorkRequest.

OneTimeWorkRequest

OneTimeWorkRequest is used to schedule a one-time background task that runs immediately or at a specific time. This request is not meant to be repeated.

onetimeworkrequest

Java:

Kotlin:

PeriodicWorkRequest

PeriodicWorkRequest is used to schedule a background task that runs at a specific interval. This can be used to check for updates after a specific interval of time.

periodicworkrequest

  • PeriodicWorkRequest will continue executing and has to be canceled for discontinuation.
  • The minimum time interval for PeriodicWorkRequest is 15 minutes and it cannot be chained with other requests as well.

Java:

Kotlin:

In WorkManager Android, work can be chained by first using the WorkManager.beginWith() method. This method uses the OneTimeWorkRequest objects and returns a WorkContinuation object.

A WorkContinuation is an object in Android's WorkManager API that represents a chain of work requests that are enqueued together and have dependencies among each other.

For instance, we can continue with the example of creating a file and uploading it. So, we require three OneTimeWorkRequest objects: CreateFileWorker, CompressFileWorker, and UploadFileWorker.

Here's how these workers can be chained. Java

Kotlin:

You can use the beginWith() and then() methods to chain one-time work requests together and create a sequence of work to be executed in a specific order. Finally, we call enqueue() on the WorkContinuation object to start the chain of work requests.

Constraints in Android WorkManager

WorkManager Android provides a set of constraints with the Constraints.Builder helper class that can help us specify certain conditions to be considered before a scheduled work is executed.

Here are some of the constraints used to specify the conditions to be met before executing a work:

BatteryNotLow

The method setRequiresBatteryNotLow(boolean requiresBatteryNotLow) ensures that the Worker runs only if the battery is not low.

StorageNotLow

The method setRequiresStorageNotLow(boolean requiresStorageNotLow) ensures that the Worker runs only if the storage for the device is not low.

Java:

Kotlin:

DeviceIdle

The method setRequiresDeviceIdle(boolean requiresDeviceIdle) should be set to true if you want the Worker to run only when the device is idle.

Java:

Kotlin:

Charging

The method setRequiresCharging(boolean requiresCharging) should be set to true if you want the Worker to run only when the device is idle.

Java:

Kotlin:

NetworkType

The method setRequiredNetworkType(NetworkType networkType) is used to specify the type of network connection with which the Worker shoud run.

If the Worker should only run when the device is connected to an unmeterd network, such as a Wi-Fi, then the enum NetworkType should be UNMETERED. Java:

The other constants for the enum NetworkType can be NETWORK_NOT_REQUIRED, CONNECTED, NOT_ROAMING, and METERED.

Input Data, Worker Results, and Output Data in WorkManager

Input data is the way of passing data from the app to the Worker before it starts to execute. It can be used to pass parameters or configurational data to the worker.

Data object is a key-value pair object used to pass input data to a Worker and receive output data from it. It is an immutable data structure that allows passing of small amounts of data between components of an application.

Here's how we can write code for input data:

The input data will now be utilized by CompressFileWorker which fetches the file path and in return, creates an input data to send the newly compressed file's path to UploadFileWorker.

The output of the Worker is represented by the Result class, which indicates the status of its execution. Result class comprises three possibilities:

  • Result.success() indicates that the work has been executed successfully.
  • Result.failure() indicates that the work execution has failed and needs to be retried via retry policies.
  • Result.retry() indicates that the work has encountered an error and is therefore terminated and should be retried immediately.

When a Worker returns a Result value, it triggers the onStopped() method to release any resources that were acquired in order to execute the work.

Output data is used to pass the data from a Worker that has successfully completed to the calling Worker. It can be used to send the results of a long-running operation or any other relevant data back to the application.

To fetch the output data, we can use the getOutputData() method of the WorkInfo object returned by the WorkManager class.

Result.success() method takes a Data object as its parameter.

Observing Worker State via LiveData in WorkManager

WorkManager Android provides a way of observing the state of a Worker by using LiveData. Let's first get to know what LiveData is.

Note: LiveData in Android is an observable data holder class.

The getWorkInfoByIdLiveData() returns a LiveData instance that reflects the current state of a specific WorkRequest.

Java:

Kotlin:

Relationship to Other APIs

One of the main reasons for this is that the WorkManager library is built on top of other libraries such as JobScheduler and AlarmManager, which are part of the Android framework and have been optimized over time to provide better reliability and power efficiency.

Moreover, with the release of Android 10 (API level 29) and higher, the WorkManager library can take advantage of the new JobScheduler API enhancements, such as the ability to set a deadline for a work request, which ensures that the work is completed within a specified time frame.

WorkManager is designed to work with several other Jetpack components such as Room Persistence Library, LiveData, ViewModel, etc.

Coroutines are lightweight and efficient, so they can perform asynchronous operations without the need to create separate threads for each.

However, they are preferred for shortlived tasks and also the ones that need lesser processing time, such as making a network request. They are not meant to be used for persistent work.

On the contrary, AlarmManager and WorkManager are convenient for longer-running tasks that can also be deferred (can be completed at a later time) if the necessary conditions aren't fulfilled.

In addition, AlarmManager is mostly used for clocks and calendar event notifications. It isn't very efficient when it comes to utilizing resources and power at a minimal rate.

Conclusion

  • With WorkManager, we can specify the time interval at which a task can be scheduled to execute.
  • Persistent work in WorkManager Android refers to any work that is mandated for execution, even in scenarios where the app is killed or the device has been restarted. It can either be Immediate, Long-Running, or Deferrable.
  • WorkManager Android provides a way of customizing how and when work should be retried if it fails. It can be an Exponential backoff or Linear backoff.
  • WorkRequests are used to specify the work that needs to be executed in the background.
  • A WorkContinuation is an object in Android's WorkManager API that represents a chain of work requests that are enqueued together and have dependencies among each other