Site icon C1CTech

Android JetPack WorkManager Example

Google released Android Jetpack. It’s a set of libraries, tools and architectural guidance to help make it quick and easy to build great Android apps. In this Android Jetpack, team at Google release one library specifically designed for scheduling and managing the background tasks. It’s called “WorkManager”.

WorkManager

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. For example, an app might need to download new resources from the network from time to time. Using these classes, you can set up a task, choose appropriate circumstances for it to run (like “only while device is charging and online”), and hand it off to WorkManager to run when the conditions are met. The task is still guaranteed to run, even if your app is force-quit or the device is rebooted.

Why need WorkManager

For background task which needs guaranteed execution and can be deferrable we have lot of options to do.We can use JobScheduler API but it is supported for API≥23. To overcome this we have FirebaseJobDispatcher library which provide backward compatibility upto API 14 but it requires Google Play services.So to avoid all these handling Work manager comes to rescue.
You don’t need to write device logic to figure out what capabilities the device has and choose an appropriate API; instead, you can just hand your task off to WorkManager and let it choose the best option.

How WorkManager works

WorkManager chooses the appropriate way to run your task based on such factors as the device API level and the app state. If WorkManager executes one of your tasks while the app is running, WorkManager can run your task in a new thread in your app’s process. If your app is not running, WorkManager chooses an appropriate way to schedule a background task depending on the device API level and included dependencies, WorkManager might use JobSchedulerFirebase JobDispatcher, or AlarmManager.

  1. For devices whose API>=23 it will use JobScheduler as the best option to schedule the task.
  2. For devices whose API>=14 and in which google play services installed, it will use FirebaseJobDispatcher.
  3. For devices whose API<14 it will use AlarmManager or BroadcastReceivers.

FEATURES OF WORKMANAGER

WORKMANAGER CORE CLASSES

There are few WorkManager classes you need to know about.

          Types of WorkRequest

           OneTimeWorkRequest : For task that you need to run only once.

           PeriodicWorkRequest : For task that you need to perform repeatedly.

 How to use WorkManager

So, enough of this theory let’s see how we can integrate WorkManager in Android app.

First, open your app level build. gradle file and add a dependency.

Add dependency 

dependencies {
implementation "android.arch.work:work-runtime:1.0.0-alpha02" }
Extend the worker class

Now the setup part is done. Let’s see how we can make a simple Worker.  

Class UploadImageWorker: Worker()  {

override fun doWork(): WorkerResult {

// Upload image to FirebaseStorage
uploadImage()

// Indicate success or failure with your return value:
return WorkerResult.SUCCESS

// (Returning RETRY tells WorkManager to try this task again
// FAILURE says not to try again.)

}

}

The doWork method actually runs on a background thread. WorkManager automatically runs this function on a background thread you don’t need to do run. You see doWork method have return type WorkerResultSo, we need to return Success if everything goes well and Failure if any error occurred.

Create a  WorkRequest

Now let’s see how we can call this UploadImageWorker class by creating request.

val uploadImageRequest = OneTimeWorkRequest.Builder(UploadImageWorker::class.java)
        .build()
val workManager = WorkManager.getInstance()
workManager.enqueue(uploadImageRequest)
Adding Contraints
val constraints = Constraints.Builder()
        .setRequiredNetworkType(NetworkType.CONNECTED)
        .build()


val uploadImageRequest = OneTimeWorkRequest.Builder(UploadImageWorker::class.java)
        .setConstraints(constraints)
        .build()
val workManager = WorkManager.getInstance()
workManager.enqueue(uploadImageRequest)
Observing Work

Now let’s say I want to observe the request. I wanna show a progress bar while this work is executing and I wanna hide the spinner when it’s done.

The following shows how to observe a WorkRequest.

workManager.getStatusById(uploadImageRequest.id).observe(this, Observer {
    if(it!=null && it.state.isFinished)
    {
        progressBar.setVisbility(GONE)
    }
});

it : refers to WorkStatus  contains information about a particular task.

The WorkManager provides a LiveData for each WorkRequest .The LiveData holds a WorkStatus object; by observing that LiveData, you can determine the current status of the task, and get any returned values after the task finishes.

Canceling a Task

You can cancel a task after you enqueue it. To cancel the task, you need its work ID, which you can get from the WorkRequest object. For example, the following code cancels the uploadImageRequest :

val workManager = WorkManager.getInstance()
workManager.cancelWorkById(uploadImageRequest.id)

Note:-We can also set tag in work request using addTag() method and can use this tag for query work status or cancelling the task instead of using workId.We can also set multiple tags on single request.

Running Multiple Request

Now let’s say I want to upload multiple images in parallel. The following shows how to execute requests in parallel.

val uploadImageRequest1 = OneTimeWorkRequest.Builder(UploadImageWorker::class.java)
        .build()

val uploadImageRequest2 = OneTimeWorkRequest.Builder(UploadImageWorker::class.java)
        .build()

val uploadImageRequest3 = OneTimeWorkRequest.Builder(UploadImageWorker::class.java)
        .build()

val workManager = WorkManager.getInstance()
workManager.enqueue(uploadImageRequest1,uploadImageRequest2,uploadImageRequest3)

These all work requests will be executed in parallel and everytime the order may differ.

Recurring tasks

You might have a task that you need to perform repeatedly. For example, before uploading the list of images to firebase storage you want to  check whether the list of images is in the compressed form or not by calling compressCheckRequest every one hour.

To create a recurring task, use the PeriodicWorkRequest.Builder class to create a PeriodicWorkRequest object, then enqueue the PeriodicWorkRequest the same way you would a OneTimeWorkRequest object.

val compressCheckRequest = PeriodicWorkRequest.Builder(CompressCheckWorker::class.java, 1,
        TimeUnit.HOURS)
        .build()

val workManager = WorkManager.getInstance()
workManager.enqueue(compressCheckRequest)
Chained tasks

Your app might need to run several tasks in a particular order. WorkManager allows you to create and enqueue a work sequence that specifies multiple tasks, and what order they should run in.

For example,here I will first compress the list of images  then upload it in firebase storage and then I will save the imageUrl in firebase database .The tasks must be run in the same order .

class CompressImageWorker : Worker() {
    override fun doWork(): WorkerResult {
      //compress image
        //compressImage()
        return WorkerResult.SUCCESS;
    }
}

class UploadImageWorker : Worker() {
    override fun doWork(): Worker.WorkerResult {
    //upload image to firebase storage
        //uploadImage()
        return WorkerResult.SUCCESS
    }
}

class SaveImageWorker : Worker() {
    override fun doWork(): WorkerResult {
     //save image to firebase database
        //saveImage()
        return WorkerResult.SUCCESS
    }
}

val compressImageRequest = OneTimeWorkRequest.Builder(CompressImageWorker::class.java)
        .setConstraints(constraints)
        .build()

val uploadImageRequest = OneTimeWorkRequest.Builder(UploadImageWorker::class.java)
        .setConstraints(constraints)
        .build()
val saveImageRequest = OneTimeWorkRequest.Builder(SaveImageWorker::class.java)
        .setConstraints(constraints)
        .build()

val workManager = WorkManager.getInstance()

workManager.beginWith(compressImageRequest).then(uploadImageRequest).then(saveImageRequest).enqueue()

I hope that this post helps you in understanding the basics of WorkManager.Thank You for being Here.

Exit mobile version