Saturday, July 24, 2021

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<MyWorker>(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

https://github.com/googlecodelabs/android-workmanager

1 comment:


  1. Thanks for this information. it is helpfull and worthy
    Laptop Repair Center offers quality service for your laptop at a reasonable cost. We offer doorstep support, 24*7 onsite support, repair all brand laptops, have an expert team for onsite support, and much more. for more contact us on 7291903784
    laptop repair center in Delhi

    ReplyDelete