--- _db_id: 389 content_type: topic prerequisites: hard: - topics/kotlin/internet-data-and-images soft: [] ready: true title: Work Manager --- ### Working With Android WorkManager Using Kotlin An ideal way of scheduling future tasks with backward compatibilit The __WorkManager__ is an API which can schedule your future asynchronous tasks and can run them in the background. The tasks assigned to the WorkManager are executed even if the user is outside the app or app is closed. WorkManager can run your task(s) for one time only as well as many times or periodically. ### Features of WorkManager - It provides backward compatibility up to API level 14 - You can add one or many constraints, such as execute tasks only when phone is charging or phone is restarted etc. - You can schedule onetime task or periodic tasks - You can also chain multiple tasks. For instance, task (B) should only be executed when task (A) is finished. - It can help you to execute tasks on particular events. __Note:__ WorkManager is not intended for in-process background work that can safely be terminated if the app process goes away or for tasks that require immediate execution. ### The classes - __Worker:__ The work needed to be done is defined here. - __WorkRequest:__ It decides which worker class is going to be executed. It's an abstract class, so we’re going to use its direct classes, and they’re OneTimeWorkRequest and PeriodWorkRequest. - __WorkManger:__ It enqueues and manages the work request. - __WorkInfo:__ It gives us information about the work, whether its success, running or failed. Let’s start coding now… ### What we’ll create? We’re going to create a notification in the background and this notification can be created only once because we’re using the OneTimeWorkRequest class. Later on, We’ll use some constraints to generate the notification on the basis of events. First of all, add the following dependency. ``` implementation "androidx.work:work-runtime-ktx:2.3.4" ``` We’ll create our worker class first by extending the Worker class, and override its doWork() method for background processing. When doWork() method is called by WorkManager, then it calls user defined method createNotification(). ``` package com.workmanagerdemo import android.app.NotificationChannel import android.app.NotificationManager import android.content.Context import android.os.Build import androidx.core.app.NotificationCompat import androidx.work.Worker import androidx.work.WorkerParameters class MyWork(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) { override fun doWork(): Result { createNotification("Background Task", "This notification is generated by workManager") return Result.success() } fun createNotification(title: String, description: String) { var notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val notificationChannel = NotificationChannel("101", "channel", NotificationManager.IMPORTANCE_DEFAULT) notificationManager.createNotificationChannel(notificationChannel) } val notificationBuilder = NotificationCompat.Builder(applicationContext, "101") .setContentTitle(title) .setContentText(description) .setSmallIcon(R.drawable.ic_launcher_background) notificationManager.notify(1, notificationBuilder.build()) } } ``` In our MainActivity.kt class, I’ve created a button, when user clicks on the button, then immediately notification gets generated. ``` package com.workmanagerdemo import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Toast import androidx.lifecycle.Observer import androidx.work.OneTimeWorkRequest import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkManager import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val request = OneTimeWorkRequestBuilder().build() btnClick.setOnClickListener { WorkManager.getInstance(this).enqueue(request) } WorkManager.getInstance(this).getWorkInfoByIdLiveData(request.id) .observe(this, Observer { val status: String = it.state.name Toast.makeText(this,status, Toast.LENGTH_SHORT).show() }) } } ``` Here, I’m creating the object of OneTimeWorkRequest and passing the class name of our MyWork class. In the real world, we can have many worker classes, so which class should be executed is decided by this request object. ``` val request = OneTimeWorkRequestBuilder().build() ``` As user clicks on the button, WorkManager enqueues the request. ``` WorkManager.getInstance(this).enqueue(request) ``` Here, we’re creating a toast to display the status of our task, whether its RUNNING, SUCCESS, and FAILED. The getWorkInfoByIdLiveData method takes the request id and gives the information about the task. ``` WorkManager.getInstance(this).getWorkInfoByIdLiveData(request.id) .observe(this, Observer { val status: String = it.state.name Toast.makeText(this,status, Toast.LENGTH_SHORT).show() }) } ``` Now run your application and click on the button, you’ll see a notification. Now we’ll see how we can add constraints to create notification only when the phone is charging. Add the following line of code to create the constraint and modify your request object. In the request object, I’m just setting the constraints and that’s it. Now notification will only be generated when this particular criterion is met. ``` val constraints = Constraints.Builder() .setRequiresCharging(true) .build() var request = OneTimeWorkRequestBuilder() .setConstraints(constraints) .build() ``` Note: When multiple constraints are specified, your task will run only when all the constraints are met. If you click on the button and your phone is not charging, then you’ll see a status saying “Enqueued”, this means that your request has been put in the queue and this will only execute when your phone will be charging. If you’re facing any problem running the code, then you can download this project from this [Github](https://github.com/himanshujbd/WorkManager) account. ### Conclusion We’ve seen how we can use WorkManager class to perform some background processing.