Hard Prerequisites |
IMPORTANT: Please review these prerequisites, they include important information that will help you with this content. |
|
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.
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.
Let’s start coding now…
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<MyWork>().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<MyWork>().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<MyWork>()
.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 account.
We’ve seen how we can use WorkManager class to perform some background processing.