🤖Understand Android Jetpack’s WorkManager in 5 minutes

Michael M.H
5 min readSep 11, 2022

--

Hi, I`m Michael👋! Today, I want to share you about Workmanager that I`ve learned years ago (2019?). I have a feeling that it’s too late for sharing it with you guys, but it`s still useful. So it`s still worth reading this post.

🔧So what is WorkManager❓

It is one of the APIs, and it is a function to schedule tasks that can be postponed even if the application is terminated or restarted. According to the official doc, it seems to be convenient for periodic synchronization with the server and transmission of logs.

WorkManager can schedule periodic asynchronous tasks under the following circumstances:

  • When the app is closed
  • When the device is rebooted

🔧So what functions does WorkManager provide❓

  • Backward compatible with API level 14 and above and compatible with API level 23 and above
  • JobScheduler provides equivalent functionality for API level 23 and above.
  • From API level 14 to 22, the combination of BroadcastReceiver and AlarmManager provides equivalent functionality.
  • You can decide whether to execute the scheduled task according to the state of the terminal such as network and battery.
  • You can set up a one-off asynchronous task.
  • You can monitor and control scheduled tasks.
  • Scheduled tasks are guaranteed to run even if the app or device restarts.
  • You can chain tasks.

🔧 So let’s try out and see how it works!

First, add WorkManager Library to Android Project WorkManager requires compiled-sdk version 28 or higher. Refer to this link . Open up your build.gradle and add the following to use the WorkManager library.

def work_version = "2.7.1"

// (Java only)
implementation "androidx.work:work-runtime:$work_version"

// Kotlin + coroutines
implementation "androidx.work:work-runtime-ktx:$work_version"

đź“ŚDefine a task in Worker(Create a class that extends Worker).
Describe the process you want to execute in the doWork method.
And you can receive task execution results in the Result class.

The status returned by the Result class is as the following:

  • Result.success(): whether the task finished successfully
  • Result.failure(): whether the task failed
  • Result.retry(): whether the task should be retried later

đź“ŚCyclic execution
There are two options for executing a task: one-time execution and periodic execution.

Use WorkerRequest

⚙️OneTimeWorkRequest: only once
⚙️ PeriodicWorkRequest: Periodic

đź“ŚOne Time Work Request sample

For example, if you want to make it a periodic task every 16 seconds, create it as follows ⬇️

How to check worker statusâť“
Work status is stored in WorkInfo obtained by getWorkInfoByIdLiveData. State is stored as the state property. The states are declared with an Enum inside the Work class. Check what the status is.

đź“–WorkInfo. State
đź“ťBLOCKED: Indicates a state that cannot be executed because the preconditions are not met.

đź“ťCANCELLED:Represents a canceled state. Associated WorkRequests are also treated as canceled and associated WorkRequests are not executed.

đź“ťENQUEUED: Represents a state where the preconditions have been met and queued in a ready state.

đź“ťFAILED: Processing failed. Associated WorkRequests are also treated as failed, and associated WorkRequests are not executed.

đź“ťRUNNING: Indicates that the process is running.

đź“ťSUCCEEDED: Processing completed successfully. A PeriodicWorkRequest (executed periodically) does not enter this state and transitions to ENQUEUED and executes again.

đź“ŚIf you want to get the Status of the Worker, you can implement it like the following.

The Task execution timingâť“

The Constraints class can be used when you want to change each task according to the state of the device.

setRequiredNetworkType: network state
setRequiresBatteryNotLow: when the battery level is high
setRequiresCharging: when connected to power
setRequiresDeviceIdle: when the device is idle
setRequiresStorageNotLow: when you have a lot of storage

In the following sample, I`m using only
setRequiresCharging, which means that the Worker will be activated only
when the device is connected to power. ⬇️

If you want to add more constraint, you can add it like this.⬇️

What is Input Data in Workerâť“

We need to pass the Data object in order to move data between workers. We must set the Data as an input when creating a Worker and receive the output as a Data object.

🧪Data class and Data.Builder class
Use the Data class to pass data to the Worker class.
The name is too general, and there are many classes with the same name, so it is necessary to remember including the package.
The full class name is “ androidx.work.Data “.
It holds a Map internally, and the data stored in that Map is passed to the class that inherits the Worker class.

Use the Data.Builder class to generate Data class objects.
Call the setXXX method of the Builder class and store the data.

I think that understanding will be quicker if you check the actual implementation example. So let’s examine the process for producing a data object for a worker.⬇️

Store in WorkRequest
To store the generated Data class object, call the setInputData method of WorkRequest (See above image).

đź“Ś Get Data and get value in Worker class
To receive data, call the getinputData method in a class that inherits the Worker class. In Kotlin, property access can be accessed like a variable without calling a getter method.

To get the stored value from the acquired Data, specify the key when stored in the getXXX method and get it.Let’s check it in code.⬇️

Okay, how about Outputâť“
I think that the example that I prepared is straight forward.
All we have to do is to pass the outputData into sucess(outputData).

To receive data, call the outputData like the following.

✒️I think that is about it. Thank you for reading until the end! Feel free to follow me. I will be posting new posts every week!

--

--

Michael M.H

🥋 Karate Instructor / 🤖Mobile developer / 👨‍💻 IT Consultant / 🎮 Creator / FX Crypto Trader Bro