Android WorkManager example for periodic tasks
1. Added JAVA 1.8 compile options in the gradle file.
compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = "1.8" }
2. Add the workmanager dependency in the gradle file.
implementation "androidx.work:work-runtime-ktx:2.3.4"
3. Create a worker class MyWorker.kt that does nothing but to sleep for 10 seconds and show a notification before and after it sleeps.
import android.content.Context import androidx.work.Worker import androidx.work.WorkerParameters class MyWorker(ctx: Context, params: WorkerParameters) : Worker(ctx, params) { override fun doWork(): Result { val appContext = applicationContext makeStatusNotification("Worker started work.", appContext) sleep(10) makeStatusNotification("Worker finshed work.", appContext) return Result.success() } }
4. Run the worker. It can be run from anywhere in the app, in this case, we are running it when a button is clicked in MainActivity. It is set to run only when the phone is charging and battery is not low. It will be run once every 15 minute. It will run even if the activity is killed or the entire app is killed. To stop it, call WorkManager.getInstance().cancelAllWorkByTag("com.example.workmanagerexample.MyWorker");
The class path of the worker class is used as default TAG for the worker class if it is not set.
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) start_worker.setOnClickListener { startWork() } } fun createConstraints() = Constraints.Builder() .setRequiresCharging(true) .setRequiresBatteryNotLow(true) .build() fun createWorkRequest(data: Data) = PeriodicWorkRequestBuilder(15, TimeUnit.MINUTES) .setInputData(data) .setConstraints(createConstraints()) .setBackoffCriteria(BackoffPolicy.LINEAR, PeriodicWorkRequest.MIN_BACKOFF_MILLIS, TimeUnit.MILLISECONDS) .build() fun startWork() { val work = createWorkRequest(Data.EMPTY) WorkManager.getInstance(applicationContext).enqueueUniquePeriodicWork("Sleep work", ExistingPeriodicWorkPolicy.REPLACE, work) } }
The utility class for showing the notification WorkerUtil.kt
import android.app.NotificationChannel import android.app.NotificationManager import android.content.Context import android.os.Build import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import timber.log.Timber /** * Create a Notification that is shown as a heads-up notification if possible. * * For this codelab, this is used to show a notification so that you know when different steps * of the background work chain are starting * * @param message Message shown on the notification * @param context Context needed to create Toast */ fun makeStatusNotification(message: String, context: Context) { // Make a channel if necessary if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // Create the NotificationChannel, but only on API 26+ because // the NotificationChannel class is new and not in the support library val name = VERBOSE_NOTIFICATION_CHANNEL_NAME val description = VERBOSE_NOTIFICATION_CHANNEL_DESCRIPTION val importance = NotificationManager.IMPORTANCE_HIGH val channel = NotificationChannel(CHANNEL_ID, name, importance) channel.description = description // Add the channel val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager? notificationManager?.createNotificationChannel(channel) } // Create the notification val builder = NotificationCompat.Builder(context, CHANNEL_ID) .setSmallIcon(R.drawable.ic_launcher_foreground) .setContentTitle(NOTIFICATION_TITLE) .setContentText(message) .setPriority(NotificationCompat.PRIORITY_HIGH) .setVibrate(LongArray(0)) // Show the notification NotificationManagerCompat.from(context).notify(NOTIFICATION_ID, builder.build()) } /** * Method for sleeping for a fixed about of time to emulate slower work */ fun sleep(durationInSec: Long) { try { Thread.sleep(ONE_SECOND_IN_MILLIS * durationInSec, 0) } catch (e: InterruptedException) { Timber.e(e) } }
The constants used in the above classes, Constants.kt
// Name of Notification Channel for verbose notifications of background work @JvmField val VERBOSE_NOTIFICATION_CHANNEL_NAME: CharSequence = "Verbose WorkManager Notifications" const val VERBOSE_NOTIFICATION_CHANNEL_DESCRIPTION = "Shows notifications whenever work starts" @JvmField val NOTIFICATION_TITLE: CharSequence = "WorkRequest Starting" const val CHANNEL_ID = "VERBOSE_NOTIFICATION" const val NOTIFICATION_ID = 1 const val ONE_SECOND_IN_MILLIS: Long = 1000
References:
https://medium.com/androiddevelopers/workmanager-basics-beba51e94048
https://android.jlelse.eu/android-workmanager-manage-periodic-tasks-c13fa7744ebd
Search within Codexpedia
Search the entire web