Simplifying Background Tasks with WorkManager in Android

Introduction

In this article, We'll explore how WorkManager simplifies task scheduling, optimizes background processing, and enhances app development across all Android devices. WorkManager is the ultimate solution for managing background tasks in Android effortlessly. WorkManager is part of Android Jetpack Architecture Components.

Android Jetpack

What is Android Jetpack

Android Jetpack is a set of components, tools, and guidance to make great Android apps. The Android Jetpack components bring together the existing Support Library and Architecture Components and arrange them into four categories.

Android apps

Here, we are exploring only the WorkManager component.

WorkManager

WorkManager

According to the official Android doc - "The WorkManager is the recommended solution for persistent work. Work is persistent when it remains scheduled through app restarts and system reboots. Because most background processing is best accomplished through persistent work, WorkManager is the primary recommended API for background processing. The WorkManager component is a powerful new library that provides a one-stop solution for constraint-based background jobs that need guaranteed execution, replacing the need to use things like jobs, etc.

Why We Should Use Work Manager?

WorkManager is preferred for handling background tasks in Android for several reasons.

  1. Simplified Task Management: WorkManager simplifies the process of managing background tasks by providing a high-level API that abstracts away complexities like managing threads, handling task persistence, and ensuring proper execution across different Android versions.
  2. Guaranteed Execution: WorkManager ensures that scheduled tasks are executed, even if the application or the device undergoes system changes like reboots or app closures. This reliability is crucial for tasks like syncing data or performing periodic updates.
  3. Backward Compatibility: WorkManager is designed to offer backward compatibility with older versions of Android, allowing developers to leverage its features without worrying about compatibility issues across different devices and OS versions.
  4. Battery Optimization: WorkManager incorporates best practices for battery optimization, ensuring that background tasks are executed efficiently without draining the device's battery excessively.
  5. Integration with Jetpack: As part of the Android Jetpack library, WorkManager seamlessly integrates with other Jetpack components, such as LiveData and Room, making it easy to incorporate background task management into modern Android app architectures.

WorkManager Components

WorkManager in Android comprises several key components that work together to manage background tasks effectively.

  1. Worker / CoroutineWorker: A Worker is a class that performs work synchronously on a background thread. As we are interested in asynchronous work, we can use CoroutineWorker, which has interoperability with Kotlin Coroutines. You extend from the CoroutineWorker class and override the doWork() method. This method is where you put the code for the actual work you want to perform in the background.
  2. WorkRequest: This is an abstraction representing a request to do some work. There are different types of WorkRequest.
    • OneTimeWorkRequest: Enqueues a task to be executed once.
    • PeriodicWorkRequest: Enqueues a task to be executed periodically at specified intervals.
  3. WorkManager: The WorkManager class is the primary interface for managing and executing work requests. It handles task scheduling, execution, and lifecycle management. You use it to enqueue work requests and observe their progress.
  4. Constraints: Constraints are conditions that must be met for the work to run. You can specify constraints such as network connectivity, device charging status, or device idle state when creating a WorkRequest. WorkManager ensures that tasks respect these constraints before executing.
  5. WorkInfo: WorkInfo provides information about the status and progress of a work request. You can observe WorkInfo to receive updates on the state of the work, such as whether it's running, succeeded, failed, or canceled.

Let's Start With Android Studio

Step 1. Create a New project

Open Android Studio, click on "New Project," and select Empty View Activity. Then, choose your preferred language (Java or Kotlin) and click "Next. and click on the finish button.

Step 2. Add WorkManager Dependency.

First, add the WorkManager dependency to your app's build.gradle(App Level) file.

// WorkManager dependency
implementation("androidx.work:work-runtime-ktx:2.8.1")

Step 3. Add Internet Permission

We are going to fetch some data from the internet, so we require internet permission.

<uses-permission android:name="android.permission.INTERNET"/>

OneTimeRequestWorker Example

Step 1. Create a new Kotlin class named OneTimeRequestWorker.kt

The OneTimeRequestWorker class extends the CoroutineWorker class instead of the more general Worker class. The CoroutineWorker class implementation of the work () is a suspending function, which lets it run asynchronous code that a Worker cannot do. As detailed in the guide Threading in WorkManager, "CoroutineWorker is the recommended implementation for Kotlin users.

import android.content.Context
import android.util.Log
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters

class OneTimeRequestWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {

        val imageUrl = inputData.getString("image_url")

        if (imageUrl.isNullOrEmpty()){
            return Result.failure()
        }

        Log.v("ImageURl",imageUrl.toString())

        return Result.success()

    }

}

Step 2. Create a OneTimeWorkRequest

Go to your activity and inside onCreate, create your OneTimeWorkRequest, and add the multiple constraints that are required.

// Define your constraints
val constraints= Constraints.Builder()
constraints.setRequiredNetworkType(NetworkType.CONNECTED)
constraints.setRequiresBatteryNotLow(true)

// Create a OneTimeWorkRequest
val oneTimeRequestWorker = OneTimeWorkRequestBuilder<OneTimeRequestWorker>()
.setInputData(workDataOf("image_url" to "https://upload.wikimedia.org/wikipedia/commons/a/a3/June_odd-eyed-cat.jpg"))
.setConstraints(constraints.build())
.setInitialDelay(1, TimeUnit.MINUTES) // Optional initial delay
.build()

Step 3. Enqueue the WorkRequest

// Enqueue the OneTimeWorkRequest
WorkManager.getInstance(applicationContext).enqueue(oneTimeRequestWorker)

Step 4. Launch Your app

Launch your app, and after 1 minute delay, check your logs.

Output

2024-04-21 16:24:52.751 13671-14718 ImageURl                com.example.helloworldapp            V  https://upload.wikimedia.org/wikipedia/commons/a/a3/June_odd-eyed-cat.jpg

PeriodicWorkRequest Example

You can use PeriodicWorkRequest when you have tasks in your app that need to be executed repeatedly and at fixed intervals. Some common use cases for PeriodicWorkRequest include.

  1. Data Synchronization: Periodically syncing data with a server to keep app data up-to-date.
  2. Content Updates: Fetching and updating content, such as news articles or social media feeds, at regular intervals.
  3. Cache Refresh: Refreshing cached data or content to ensure it remains accurate and current.
  4. Background Processing: Performing background processing tasks, such as database cleanup or periodic notifications.

Step 1. Create a new Kotlin class named PreodicRequestWorker.kt.

class PreodicRequestWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {

        val imageUrl = inputData.getString("image_url")

        if (imageUrl.isNullOrEmpty()){
            return Result.failure()
        }

        Log.v("ImageURl",imageUrl.toString())

        return Result.success()

    }

}

Step 2. Create a PreodicWorkRequest

Go to your activity and inside onCreate, create your PreodicWorkRequest, and add the multiple constraints that are required. The minimum interval for a PeriodicWorkRequest in WorkManager is 15 minutes. This means that you cannot schedule a periodic work request to run more frequently than every 15 minutes.

// Define your constraints
val constraints= Constraints.Builder()
constraints.setRequiredNetworkType(NetworkType.CONNECTED)
constraints.setRequiresBatteryNotLow(true)

// Create a PreodicWorkRequest
val preodicRequestWorker = PeriodicWorkRequestBuilder<PreodicRequestWorker>(15, TimeUnit.MINUTES)
.setInputData(workDataOf("image_url" to "https://upload.wikimedia.org/wikipedia/commons/a/a3/June_odd-eyed-cat.jpg"))
.setConstraints(constraints.build())
.setInitialDelay(1, TimeUnit.MINUTES) // Optional initial delay
.build()

Step 3. Enqueue the WorkRequest

// Enqueue the OneTimeWorkRequest
WorkManager.getInstance(applicationContext).enqueue(preodicRequestWorker)

Step 4. Launch Your app

Launch your app, and after 1 minute delay, check your logs.

Output

2024-04-21 17:33:48.035  3132-4310  ImageURl                com.example.helloworldapp            V  https://upload.wikimedia.org/wikipedia/commons/a/a3/June_odd-eyed-cat.jpg

Resource Link

This article covers the basics of WorkManager. If you want to go to an advanced level, check these resources.

Conclusion

This article guides you, WorkManager makes it easy to handle background tasks in Android apps. With its simple interface and strong features, WorkManager helps developers create apps that run smoothly in the background, meeting user needs effectively. By integrating WorkManager, developers can ensure their apps are reliable and responsive, providing a better experience for users.


Similar Articles