How to Read Your Schedule From Work

WorkManager is a useful and important component of Android Jetpack. It allows the app to practice things in the background even when the app is exited or the device is restarted.

WorkManager also has many advantages over its predecessors. For example, it'due south battery conscious, allows you to determine the conditions for your chore to run such every bit having a Wi-Fi connectedness, flexible retrying, and integration with Coroutines and RxJava.

In this tutorial, you lot'll build WorkManagerApp. The app downloads an epitome from a URL and saves the image to the device in the groundwork. During the process, you'll acquire about:

  • WorkManager basics
  • Creating different workers and querying work progress
  • WorkManager initialization types
  • Testing your workers

Getting Started

Download the materials using the Download Materials push at the top or bottom of this tutorial. Open Android Studio 4.1.two or afterward and import the starter projection.

Build and run the project. You'll run across the following screen:

WorkManager Start Download

Looking Into WorkManager

WorkManager is a Jetpack Library that allows you to run deferrable jobs.

To sympathize how WorkManager operates under the hood, you lot demand to know how it interacts with the Android operating system regarding:

  • Persisting requests
  • Running your requests

Persisting Requests

WorkManager Persist Request

Adapted from Android Dev Superlative '19 WorkManager Presentation

Once you enqueue your work asking, WorkManager stores it in the database, which acts as a Single Source of Truth.

Later this, WorkManager sends the work asking to JobScheduler for API 23 and in a higher place. For API below 23, WorkManager performs a further cheque. If the device has Play Services installed, WorkManager sends the piece of work request to GCM Network Manager. If it'south not installed, WorkManager uses Alarm Director to run the piece of work.

WorkManager does all this for you. :] Next, you lot'll wait at how WorkManager actually runs your work request.

Running Your Asking

WorkManager Run Request

Adapted from Android Dev Summit 'nineteen WorkManager Presentation

JobScheduler, GCM Network Manager and Warning Managing director are enlightened of your work. They'll get-go your application if need exist, given that the device meets all the constraints. In turn, they'll request WorkManager to run your work.

There'south as well GreedyScheduler, which runs within the app process. Hence, it doesn't start your app if it's in the background. GreedyScheduler isn't affected by the OS.

Now that you lot understand how WorkManager operates, information technology's time to define your first WorkRequest.

Defining Your Work

You define your work by extending from Worker and overriding doWork. doWork is an asynchronous method that executes in the background.

WorkManager has back up for long-running tasks. It keeps the process in these tasks live when the work is running. Instead of a normal Worker, you'll utilise a ListenableWorker if y'all're in Coffee or a CoroutineWorker if you're using Kotlin Coroutines.

First, navigate to ImageDownloadWorker.kt inside the workers package. You'll run into a class similar the one beneath:

course ImageDownloadWorker(   private val context: Context,   private val workerParameters: WorkerParameters ) : CoroutineWorker(context, workerParameters) {   override suspend fun doWork(): Result {     TODO("Not even so implemented")   } }        

The code to a higher place does the following:

  • The ImageDownloadWorker course extends CoroutineWorker.
  • ImageDownloadWorker requires instances of Context and WorkerParameters as parameters in the constructor. You pass them to CoroutineWorker, too.
  • It overrides doWork(), a suspend method. It can do long-running tasks off the main thread.

doWork() is pretty bare. You lot'll add the code to do work in this method shortly.

Navigate to ImageUtils.kt and add the post-obit extension role:

fun Context.getUriFromUrl(): Uri? {   // 1   val imageUrl =     URL(       "https://images.pexels.com/photos/169573/pexels-photo-169573.jpeg" +           "?auto=shrink&cs=tinysrgb&dpr=2&h=650&w=940"     )   // 2   val bitmap = imageUrl.toBitmap()      // 3   var savedUri: Uri? = null   bitmap?.apply {     savedUri = saveToInternalStorage(this@getUriFromUrl)   }   render savedUri }        

Here'south a breakdown of what the code to a higher place does:

  1. imageUrl converts a link to a qualified URL.
  2. Side by side, you lot convert imageUrl to a bitmap using toBitmap().
  3. Concluding, yous save the paradigm bitmap to internal storage. Moreover, you get the URI of the path to the prototype'due south storage location.

Caput to ImageDownloadWorker.kt. Supplant TODO("Not even so implemented") with the following code:

// 1 filibuster(10000) // 2 val savedUri = context.getUriFromUrl() // 3 return Consequence.success(workDataOf("IMAGE_URI" to savedUri.toString()))        

Here'south a code breakdown:

  1. The image downloads quickly. To simulate a near existent-earth situation, you add a delay of 10,000 milliseconds so the work tin can take fourth dimension.
  2. You get the URI from the extension function you added in the previous footstep.
  3. Final, one time you take the URI, you return a successful response to notify that your work has finished without failure. workDataOf() converts a list of pairs to a Data object. A Data object is a fix of central/value pairs used as inputs/outputs for ListenableWorker'due south. IMAGE_URI is a key for identifying the consequence. You're going to employ it to get the value from this worker.

Now, you might run into some warnings due to missing imports. At the top of the file, add:

import androidx.work.workDataOf import com.raywenderlich.android.workmanager.utils.getUriFromUrl import kotlinx.coroutines.delay        

Y'all have defined your work. Next, y'all'll create a WorkRequest to run the piece of work.

Creating Your WorkRequest

For your scheduled work to run, the WorkManager service has to schedule it. A WorkRequest contains information of how and when your work will run.

You tin schedule your work to run either periodically or once.

For running work periodically, you'll use a PeriodicWorkRequestBuilder. For quondam work, you'll use OneTimeWorkRequestBuilder.

Creating a 1-Time WorkRequest

To create a 1-time request, you'll begin by adding WorkManager initialization. Navigate to HomeActivity.kt. Add this at the height class definition:

private val workManager past lazy {   WorkManager.getInstance(applicationContext) }        

Here, you create an instance of WorkManager as a top-course variable. Members of HomeActivity can utilize this WorkManager case. Exist sure to add the WorkManager import when prompted to practise so.

Second, add together the following method below onCreate:

private fun createOneTimeWorkRequest() {   // i   val imageWorker = OneTimeWorkRequestBuilder<ImageDownloadWorker>()     .setConstraints(constraints)     .addTag("imageWork")     .build()   // ii   workManager.enqueueUniqueWork(     "oneTimeImageDownload",     ExistingWorkPolicy.KEEP,     imageWorker   ) }        

In the code in a higher place, you:

  1. Create your WorkRequest. Yous besides set up constraints to the piece of work. Additionally, you add a tag to make your work unique. You lot tin can utilise this tag to cancel the work and observe its progress, too.
  2. Finally, yous submit your work to WorkManager past calling enqueueUniqueWork.

You lot might see some warnings due to missing imports. At the height of the file, add:

import androidx.work.ExistingWorkPolicy import androidx.piece of work.OneTimeWorkRequestBuilder import com.raywenderlich.android.workmanager.workers.ImageDownloadWorker        

Still, yous'll come across the constraints is nonetheless highlighted in cherry-red. To resolve this, add the following lawmaking below your WorkManager initialization at the top of the class:

private val constraints = Constraints.Builder()   .setRequiredNetworkType(NetworkType.CONNECTED)   .setRequiresStorageNotLow(true)   .setRequiresBatteryNotLow(true)   .build()        

The post-obit constraints are ready for work to run. The device must have:

  • An active network connectedness
  • Enough storage
  • Plenty battery

Inside onCreate, add the following code below requestStoragePermissions():

activityHomeBinding.btnImageDownload.setOnClickListener {   showLottieAnimation()   activityHomeBinding.downloadLayout.visibility = View.GONE   createOneTimeWorkRequest() }        

In the code above, you call createOneTimeWorkRequest() when you tap Kickoff Image DOWNLOAD. Yous're likewise showing the animation and hiding the layout every bit you wait for your work to complete.

Build and run the app. The UI remains the same.

WorkManager Start Download

Tap Start IMAGE DOWNLOAD. Notice that the animation doesn't terminate. Don't worry, you'll fix this behavior in the adjacent steps.

Background Image Download

Observing Piece of work Progress

With WorkManager, you can observe the progress of your work when the app is in the foreground.

To observe your work's progress, add the following method below createOneTimeWorkRequest():

private fun observeWork(id: UUID) {   // i   workManager.getWorkInfoByIdLiveData(id)     .notice(this, { info ->       // two       if (info != null && info.country.isFinished) {         hideLottieAnimation()         activityHomeBinding.downloadLayout.visibility = View.VISIBLE         // iii         val uriResult = info.outputData.getString("IMAGE_URI")         if (uriResult != null) {           showDownloadedImage(uriResult.toUri())         }       }     }) }        

The code in a higher place:

  1. Gets the piece of work information using the work ID and returns it as observable LiveData.
  2. Adds a null check for the work information and the work completion.
  3. Gets the data from your piece of work and displays the paradigm. It uses the IMAGE_URI key from the worker to get the specific value. Without this key, information technology tin can't become the data from your work.

Add together a telephone call to observeWork() at the bottom of createOneTimeWorkRequest():

observeWork(imageWorker.id)        

You pass the work ID to observeWork(). You utilize this ID to detect information about this particular work.

Build and run the app.

WorkManager Start Download

Tap START Epitome DOWNLOAD to start the download. Once the download completes, yous'll come across the following screen:

Background Image Downloaded

At times, you'll need to create work that runs periodically, rather than once. In the adjacent section, y'all'll create such periodic work requests.

Creating a Periodic WorkRequest

Occasionally, your work needs to run several times, such every bit daily backups of a messaging app. In such cases, you use a PeriodicWorkRequest to create your WorkRequest.

Add the following code below onCreate:

private fun createPeriodicWorkRequest() {   // 1   val imageWorker = PeriodicWorkRequestBuilder<ImageDownloadWorker>(     15, TimeUnit.MINUTES)     .setConstraints(constraints)     .addTag("imageWork")     .build()   // 2   workManager.enqueueUniquePeriodicWork(     "periodicImageDownload",     ExistingPeriodicWorkPolicy.Proceed,     imageWorker   )   observeWork(imageWorker.id) }        

In the code to a higher place, y'all:

  1. Apply PeriodicWorkRequestBuilder to define your piece of work. Detect that it takes time as a parameter. A brake requires the interval between successive executions of your work to exist at least 15 minutes.
  2. Submit the work to WorkManager past calling enqueueUniquePeriodicWork. Y'all need to laissez passer the uniqueWorkName, existingPeriodicWorkPolicy and the imageWorker itself.

Within onCreate, supplant createOneTimeWorkRequest() with createPeriodicWorkRequest(). The code should at present be equally follows:

          activityHomeBinding.btnImageDownload.setOnClickListener {    showLottieAnimation()    activityHomeBinding.downloadLayout.visibility = View.GONE    createPeriodicWorkRequest()  }        

Build and run the app. Tap Start Epitome DOWNLOAD to start the download. You lot'll notice that the animation doesn't disappear. This is because periodic work never ends and merely has CANCELLED state. After each run, the work volition be re-run regardless of the previous state.

Creating a Delayed WorkRequest

A delayed WorkRequest is a Old WorkRequest whose execution is delayed past a given duration.

First, add the following code below onCreate:

private fun createDelayedWorkRequest() {   val imageWorker = OneTimeWorkRequestBuilder<ImageDownloadWorker>()     .setConstraints(constraints)     .setInitialDelay(30, TimeUnit.SECONDS)     .addTag("imageWork")     .build()   workManager.enqueueUniqueWork(     "delayedImageDownload",     ExistingWorkPolicy.KEEP,     imageWorker   )   observeWork(imageWorker.id) }        

Notice the improver of setInitialDelay(thirty, TimeUnit.SECONDS), which takes the amount of time you want to delay your work.

Inside onCreate, replace createPeriodicWorkRequest() with createDelayedWorkRequest(). Your final result will exist:

          activityHomeBinding.btnImageDownload.setOnClickListener {    showLottieAnimation()    activityHomeBinding.downloadLayout.visibility = View.GONE    createDelayedWorkRequest()  }        

Build and run the app. Tap START Prototype DOWNLOAD to commencement the download, which delays for thirty seconds. Later on this filibuster is consummate, your piece of work begins to run. When information technology finishes, you'll see the post-obit screen:

Background Image Downloaded

Yous've seen how to create your work and define and run your WorkRequest. It's time for you lot to acquire how to query work information.

Querying Piece of work Data

WorkManager allows y'all to write circuitous queries. You use the unique work name, tag and state, using WorkQuery objects.

To query information nigh the work you've run, add together the following code below observeWork():

private fun queryWorkInfo() {   // ane   val workQuery = WorkQuery.Builder     .fromTags(listOf("imageWork"))     .addStates(listOf(WorkInfo.State.SUCCEEDED))     .addUniqueWorkNames(        listOf("oneTimeImageDownload", "delayedImageDownload",           "periodicImageDownload")     )     .build()   // ii   workManager.getWorkInfosLiveData(workQuery).observe(this) { workInfos->     activityHomeBinding.tvWorkInfo.visibility = View.VISIBLE     activityHomeBinding.tvWorkInfo.text =       resources.getQuantityString(R.plurals.text_work_desc, workInfos.size,          workInfos.size)   } }        

Here's what the code higher up does:

  1. This is a WorkQuery builder, and you're setting the tag, country and unique names for the works you want to get their information.
  2. You call getWorkInfosLiveData() and pass workQuery. This method returns observable data.

To wire everything up, add the following lawmaking inside onCreate:

activityHomeBinding.btnQueryWork.setOnClickListener {   queryWorkInfo() }        

In the code above, you set a click listener to the QUERY WORK INFO button, which calls queryWorkInfo().

Build and run the app. Tap START Prototype DOWNLOAD and wait for the download to complete.

Background Image Downloaded

Tap QUERY WORK INFO:

WorkManager Query Results

The WorkQuery returns the completed piece of work and the event is shown on the screen.

In the next section, you'll learn how to initialize WorkManager in different means.

WorkManager Initialization Types

WorkManager has ii types of initialization:

  • Automatic Initialization: WorkManager initializes automatically with default configuration and no customizations. The initialization happens in your awarding onCreate. It can add together an extra overhead when WorkManager isn't in apply.
  • On-Demand Initialization: This lets you lot define WorkManager when y'all need it. It removes the overhead from app startup and in plough improves your app performance. This initialization is extremely helpful when you need more informative WorkManager logs.

Using On-Demand Initialization

To utilise On-Demand Initialization, y'all get-go need to disable automatic initialization. To achieve this, caput over to AndroidManifest.xml. Supersede TODO Add together PROVIDER with:

<provider   android:name="androidx.work.impl.WorkManagerInitializer"   android:regime="${applicationId}.workmanager-init"   tools:node="remove" />        

Exist sure to add together the tools import when prompted to do so. This removes the default WorkManager initializer.

2d, you'll need to change your application class to add together a new configuration provider. Head to WorkManagerApp.kt and replace the grade with the following code:

// ane class WorkManagerApp : Application(), Configuration.Provider {   // 2   override fun getWorkManagerConfiguration(): Configuration {     render Configuration.Builder()       .setMinimumLoggingLevel(android.util.Log.DEBUG)       .build()   }    override fun onCreate() {     super.onCreate()     // iii     WorkManager.initialize(this, workManagerConfiguration)   } }        

In the code higher up:

  1. The awarding class extends Configuration.Provider. This allows y'all to provide your own custom WorkManager configuration.
  2. You provide your own implementation of getWorkManagerConfiguration(), in which you provide your custom WorkManager initialization. You besides specify the minimum logging level.
  3. Last, you initialize WorkManager with a custom configuration you lot've created.

You might see some warnings due to missing imports. At the top of the file, add:

import androidx.work.Configuration import androidx.work.WorkManager        

Build and run the app. The functionality does not change. Now, you're using on-demand initialization for your WorkManager.

Testing Your Workers

Testing is 1 of the most important aspects of software development. WorkManager provides comprehensive APIs to enable you to write tests. This is very important because you lot can test your workers and confirm that everything runs as expected.

Inside the androidTest directory, create a new file named ImageDownloadWorkerTest.kt and add the following code:

course ImageDownloadWorkerTest {    // ane   @get:Rule   var instantTaskExecutorRule = InstantTaskExecutorRule()    @go:Dominion   var workerManagerTestRule = WorkManagerTestRule()    // ii   @Examination   fun testDownloadWork() {     // Create Work Request     val work = TestListenableWorkerBuilder<ImageDownloadWorker>(workerManagerTestRule.targetContext).build()     runBlocking {       val result = work.doWork()       // Assert       assertNotNull(outcome)     }   } }        

To sum upwards what the above code does:

  1. You go InstantTaskExecutorRule, which swaps the background executor used by the Architecture Components with a unlike ane that executes each task synchronously. You also go WorkManagerTestRule, which initializes WorkManager and likewise provides a context.
  2. This is the actual test, which is to test your ImageDownloadWorker. You're using TestListenableWorkerBuilder, which runs your Worker. In this case, your Worker is a CoroutineWorker.

Add the following imports to resolve all errors:

import androidx.curvation.core.executor.testing.InstantTaskExecutorRule import androidx.piece of work.testing.TestListenableWorkerBuilder import com.raywenderlich.android.workmanager.workers.ImageDownloadWorker import kotlinx.coroutines.runBlocking import org.junit.Assert.assertNotNull import org.junit.Dominion import org.junit.Test        

Click the Run icon to the left of testDownloadWork(). You'll see the following:

Image Download Worker Test

Congratulations! :] You wrote your first Worker exam. Side by side, you'll be writing tests for your WorkRequest.

Note: WorkManager tests need the Android platform to run. This is the reason your tests are in the androidTest directory.

Testing Delayed Piece of work

Open SampleWorker.kt inside workers and add the following code:

import android.content.Context import androidx.work.Worker import androidx.piece of work.WorkerParameters  class SampleWorker (   individual val context: Context,   private val workerParameters: WorkerParameters ) : Worker(context, workerParameters) {   override fun doWork(): Result {     return when (inputData.getString("Worker")) {       "sampleWorker" -> Consequence.success()       else -> Effect.retry()     }   } }        

The class above extends from Worker and overrides doWork(). It checks the input information and returns success when it finds the sampleWorker input. This SampleWorker is for testing purposes. Information technology shows y'all how to exam normal Workers.

Head to SampleWorkerTest.kt, which is under the androidTest directory. This class is blank and has merely the rules at the top. You'll be calculation tests in this class.

Beneath workerManagerTestRule, add the post-obit lawmaking:

@Test fun testWorkerInitialDelay() {   val inputData = workDataOf("Worker" to "sampleWorker")   // 1   val request = OneTimeWorkRequestBuilder<SampleWorker>()     .setInitialDelay(10, TimeUnit.SECONDS)     .setInputData(inputData)     .build()      // 2   val testDriver = WorkManagerTestInitHelper     .getTestDriver(workerManagerTestRule.targetContext)   val workManager = workerManagerTestRule.workManager   // iii   workManager.enqueue(request).result.become()   // four   testDriver?.setInitialDelayMet(request.id)   // v   val workInfo = workManager.getWorkInfoById(request.id).get()   // 6   assertThat(workInfo.state, `is`(WorkInfo.State.SUCCEEDED)) }        

With the code to a higher place, you:

  1. Create your WorkRequest using OneTimeWorkRequestBuilder. You set an initial delay of 10 seconds. Yous're also setting input data to your request.
  2. Create a TestDriver, which will help in simulating the delay. You're creating an instance of WorkManager, too.
  3. Enqueue your request.
  4. Simulate the actual delay for your work.
  5. Get piece of work info and output information.
  6. Do an exclamation to check the succeeded state in your piece of work.

To resolve import errors, add the post-obit imports at the top of the file:

import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkInfo import androidx.piece of work.testing.WorkManagerTestInitHelper import androidx.work.workDataOf import com.raywenderlich.android.workmanager.workers.SampleWorker import org.hamcrest.CoreMatchers.`is` import org.junit.Affirm.assertThat import coffee.util.concurrent.TimeUnit import org.junit.Test        

Click the Run icon to the left of testWorkerInitialDelay(). You'll see the following:

Delayed Worker Test

You lot've learned how to test delayed workers. Side by side, you'll examination periodic work requests.

Testing Periodic Work

Still on the SampleWorkerTest.kt, below testWorkerInitialDelay, add together:

@Test fun testPeriodicSampleWorker() {   val inputData = workDataOf("Worker" to "sampleWorker")   // i   val request = PeriodicWorkRequestBuilder<SampleWorker>(xv, TimeUnit.MINUTES)     .setInputData(inputData)     .build()   // 2   val testDriver = WorkManagerTestInitHelper     .getTestDriver(workerManagerTestRule.targetContext)   val workManager = workerManagerTestRule.workManager   // 3   workManager.enqueue(request).result.go()   // 4   testDriver?.setPeriodDelayMet(request.id)   // v   val workInfo = workManager.getWorkInfoById(request.id).get()      // 6   assertThat(workInfo.state, `is`(WorkInfo.State.ENQUEUED)) }        

In this code, you:

  1. Create your WorkRequest using PeriodicWorkRequestBuilder, with a time interval of 10 minutes. Yous're also setting input data to your request.
  2. Make a testDriver, which will aid in simulating the time interval betwixt each work. You're creating an case of workManager, as well.
  3. Enqueue your request.
  4. Notify the WorkManager testing framework that the interval'south duration is complete.
  5. Go piece of work info and output data.
  6. Practice an assertion to check for the enqueued state for your piece of work.

Click the Run icon to the left of testPeriodicSampleWorker(). You'll see the following:

Periodic Worker Test

Y'all've now learned how to test periodic piece of work requests. Next, you'll exam constraints.

Testing Constraints

SampleWorker needs simply two constraints: active network connection and enough bombardment. TestDriver has setAllConstraintsMet for simulating constraints.

In your SampleWorkerTest, below testPeriodicSampleWorker, add:

@Test fun testAllConstraintsAreMet() {   val inputData = workDataOf("Worker" to "sampleWorker")   // 1   val constraints = Constraints.Architect()     .setRequiredNetworkType(NetworkType.Connected)     .setRequiresBatteryNotLow(true)     .build()   // 2   val asking = OneTimeWorkRequestBuilder<SampleWorker>()     .setConstraints(constraints)     .setInputData(inputData)     .build()   val workManager = WorkManager     .getInstance(workerManagerTestRule.targetContext)   // three   workManager.enqueue(request).issue.get()   // 4   WorkManagerTestInitHelper.getTestDriver(workerManagerTestRule.targetContext)     ?.setAllConstraintsMet(asking.id)   // v   val workInfo = workManager.getWorkInfoById(asking.id).get()   // six   assertThat(workInfo.state, `is`(WorkInfo.Country.SUCCEEDED)) }        

Here's a breakdown of the code higher up. Information technology:

  1. Creates your network and battery constraints.
  2. Makes your WorkRequest, using OneTimeWorkRequestBuilder. It sets your constraints to the request. It besides sets input data to your request.
  3. Enqueues your request
  4. Simulates the network and battery constraints, using WorkManagerTestInitHelper
  5. Gets work info and output data
  6. Does an assertion to check for the succeeded land for your piece of work

Click the Run icon to the left of testAllConstraintsAreMet(). You'll see the following:

Constraints Worker Test

All tests have passed! :] That is truly a reason to be proud of yourself! In the next section, you're going to wait at how to create works that run in the foreground.

Creating Foreground Piece of work

For long-running tasks, you need to bear witness a persistent notification. This prevents the Android system from killing your process when your app is no longer running.

For such cases, WorkManager uses a foreground service to show a persistent notification to the user. With CoroutineWorker, yous'll apply setForeground() to specify that your WorkRequest is important or long-running.

Navigate to ImageDownloadWorker.kt and add this below doWork():

individual fun createForegroundInfo(): ForegroundInfo {   // ane   val intent = WorkManager.getInstance(applicationContext)     .createCancelPendingIntent(id)   // ii   val notification = NotificationCompat.Architect(      applicationContext, "workDownload")     .setContentTitle("Downloading Your Image")     .setTicker("Downloading Your Image")     .setSmallIcon(R.drawable.notification_action_background)     .setOngoing(truthful)     .addAction(android.R.drawable.ic_delete, "Cancel Download", intent)   // 3   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {     createChannel(notification, "workDownload")   }   return ForegroundInfo(ane, notification.build()) }        

Here is what'southward happening:

  1. This is a PendingIntent you'll use to cancel the piece of work.
  2. This is the bodily notification with an icon, championship and cancel action. The cancel activity is necessary for canceling work.
  3. You're creating a notification aqueduct for Android versions above Oreo. Then, you render ForegroundInfo, which you lot utilise to update your ongoing notification.

Resolve all import errors when prompted. You'll notice createChannel(notification, "workDownload") remains highlighted in blood-red. To resolve this, add together this method below createForegroundInfo():

@RequiresApi(Build.VERSION_CODES.O) individual fun createChannel(   notificationBuilder: NotificationCompat.Architect,    id: String ) {   val notificationManager =     context.getSystemService(Context.NOTIFICATION_SERVICE) as         NotificationManager   notificationBuilder.setDefaults(Notification.DEFAULT_VIBRATE)   val channel = NotificationChannel(     id,     "WorkManagerApp",     NotificationManager.IMPORTANCE_HIGH   )   channel.description = "WorkManagerApp Notifications"   notificationManager.createNotificationChannel(channel) }        

In the code above, you create a notification channel. The channel is necessary for devices with version Oreo and above. Add all imports as prompted by the IDE.

Now, to become the notification working, add this in doWork() above your telephone call to delay():

setForeground(createForegroundInfo())        

Here, you lot call setForeground() from CoroutineWorker to mark your work as long-running or important.

Build and run the app. Then tap on Showtime Paradigm DOWNLOAD.

WorkManager Foreground Notification

One time your download image task starts, you'll encounter a persistent notification. This informs the Android operating system that your task is long-running or important. The operating arrangement won't kill your chore once your app is in the background. Once WorkManager completes the task, the notification will disappear.

Requesting Diagnostic Data from WorkManager

WorkManager provides a way to become the following information:

  1. Requests that have been completed in the by 24 hours
  2. Requests that have been scheduled
  3. Running work requests

This information is available for debug builds. To go this information, run this command on your terminal:

adb beat out am broadcast -a "androidx.work.diagnostics.REQUEST_DIAGNOSTICS" -p "com.raywenderlich.android.workmanager"        

Your logcat displays the following data:

Diagnostic Worker Information

Where to Go From Hither?

Download the final version of this project using the Download Materials button at the top or bottom of this tutorial.

Congratulations! You learned how to use WorkManager to run one-fourth dimension, delayed, periodic, and long-running or important tasks in the background. You too learned how to write tests for your workers.

To learn more well-nigh WorkManager, check out the WorkManager official documentation.

I promise y'all enjoyed the tutorial. If you have whatsoever questions or comments, delight bring together the forum give-and-take below.

kincaidpell1941.blogspot.com

Source: https://www.raywenderlich.com/20689637-scheduling-tasks-with-android-workmanager

0 Response to "How to Read Your Schedule From Work"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel