0Pricing
Android Academy · Lesson

WorkManager & Background Tasks

Schedule guaranteed background work with WorkManager. Use OneTimeWorkRequest, PeriodicWorkRequest, constraints, data passing, and work chaining.

WorkManager & Background Tasks is a free Android Academy lesson on CoddyKit — lesson 5 of 6. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Android Academy learning path, one of 6 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Background Work in Android

Android aggressively restricts background work to save battery. Before WorkManager, developers used:

  • AsyncTask (deprecated)
  • AlarmManager (not reliable across reboots/Doze)
  • JobScheduler (complex API)
  • Services (can be killed, no retry)

WorkManager is the recommended solution for deferrable, guaranteed background work.

What Is WorkManager?

WorkManager guarantees your work runs even if the app is killed or the device reboots. It:

  • Persists work across reboots
  • Automatically retries on failure
  • Supports constraints (WiFi only, charging only, etc.)
  • Works on API 14+
  • Integrates with Kotlin Coroutines via CoroutineWorker

Setup

Add WorkManager to app/build.gradle:

dependencies {
    implementation 'androidx.work:work-runtime-ktx:2.9.0'
}

Creating a Worker

Extend CoroutineWorker and implement doWork(). Return Result.success(), Result.failure(), or Result.retry():

class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        return try {
            // This runs on a background coroutine
            val repo = UserRepository(applicationContext)
            repo.syncFromNetwork()
            Result.success()
        } catch (e: Exception) {
            if (runAttemptCount < 3) Result.retry()
            else Result.failure()
        }
    }
}

OneTimeWorkRequest

Schedule a one-time task and enqueue it:

val syncWork = OneTimeWorkRequestBuilder<SyncWorker>()
    .setInitialDelay(10, TimeUnit.MINUTES)  // optional delay
    .build()

WorkManager.getInstance(context).enqueue(syncWork)

// With a unique name (prevents duplicates):
WorkManager.getInstance(context).enqueueUniqueWork(
    "sync_work",
    ExistingWorkPolicy.KEEP,   // don't enqueue if already pending
    syncWork
)

PeriodicWorkRequest

Schedule repeating tasks. Minimum interval is 15 minutes:

val periodicSync = PeriodicWorkRequestBuilder<SyncWorker>(
    repeatInterval = 1, TimeUnit.HOURS
).build()

WorkManager.getInstance(context).enqueueUniquePeriodicWork(
    "hourly_sync",
    ExistingPeriodicWorkPolicy.KEEP,
    periodicSync
)

Constraints

Run work only when conditions are met — battery not low, WiFi connected, etc.:

val constraints = Constraints.Builder()
    .setRequiredNetworkType(NetworkType.UNMETERED)  // WiFi only
    .setRequiresBatteryNotLow(true)
    .setRequiresCharging(false)
    .build()

val work = OneTimeWorkRequestBuilder<SyncWorker>()
    .setConstraints(constraints)
    .build()

WorkManager.getInstance(context).enqueue(work)

Input & Output Data

Pass data in and out of a Worker using Data objects:

// Enqueue with input data:
val inputData = workDataOf("user_id" to 42)
val work = OneTimeWorkRequestBuilder<SyncWorker>()
    .setInputData(inputData)
    .build()

// Inside the Worker:
class SyncWorker(...) : CoroutineWorker(...) {
    override suspend fun doWork(): Result {
        val userId = inputData.getInt("user_id", -1)

        // Pass output data back:
        val output = workDataOf("synced_count" to 10)
        return Result.success(output)
    }
}

Observing Work Status

Observe work progress using getWorkInfoByIdLiveData:

val workRequest = OneTimeWorkRequestBuilder<SyncWorker>().build()
WorkManager.getInstance(this).enqueue(workRequest)

WorkManager.getInstance(this)
    .getWorkInfoByIdLiveData(workRequest.id)
    .observe(this) { info ->
        when (info?.state) {
            WorkInfo.State.RUNNING   -> binding.tvStatus.text = "Syncing..."
            WorkInfo.State.SUCCEEDED -> binding.tvStatus.text = "Done!"
            WorkInfo.State.FAILED    -> binding.tvStatus.text = "Failed"
            else                     -> {}
        }
    }

Chaining Work

Run tasks sequentially or in parallel using work chains:

val downloadWork  = OneTimeWorkRequestBuilder<DownloadWorker>().build()
val processWork   = OneTimeWorkRequestBuilder<ProcessWorker>().build()
val uploadWork    = OneTimeWorkRequestBuilder<UploadWorker>().build()

// Sequential: download → process → upload
WorkManager.getInstance(context)
    .beginWith(downloadWork)
    .then(processWork)
    .then(uploadWork)
    .enqueue()

// Parallel then merge:
WorkManager.getInstance(context)
    .beginWith(listOf(downloadWork, processWork))  // both run in parallel
    .then(uploadWork)                              // runs after both finish
    .enqueue()

WorkManager vs Alternatives

When to use what:

  • WorkManager — deferrable, guaranteed, constraint-based work. Best for syncs, uploads, cleanup.
  • Coroutines / ViewModel — work tied to the app being open. Stops when app is killed.
  • AlarmManager — exact-time alarms (calendar reminders). Needs careful battery handling.
  • Foreground Service — long-running tasks the user is aware of (music playback, navigation).

Quick Check

What is the minimum repeat interval for a PeriodicWorkRequest?

Recap: WorkManager

WorkManager is the right tool for guaranteed background work:

  • Extend CoroutineWorker and implement doWork()
  • Return Result.success(), .failure(), or .retry()
  • Use OneTimeWorkRequest for single runs, PeriodicWorkRequest for recurring
  • Add Constraints for WiFi-only, battery conditions, etc.
  • Pass data with workDataOf()
  • Chain tasks with beginWith().then().enqueue()

Next: Material Design components for beautiful UIs.

Frequently asked questions

Is the “WorkManager & Background Tasks” lesson free?

Yes — the full text of “WorkManager & Background Tasks” is free to read here on the web, and the Android Academy course includes 6 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Android Academy course, upgrade to CoddyKit PRO.

What will I learn in “WorkManager & Background Tasks”?

Schedule guaranteed background work with WorkManager. Use OneTimeWorkRequest, PeriodicWorkRequest, constraints, data passing, and work chaining. You practise Android Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Android Academy?

No prior experience is required. Android Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 5 of 6, so you can start here or from the beginning and move at your own pace.

How long does the “WorkManager & Background Tasks” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Android Academy lesson?

Yes. Every Android Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Retrofit & REST APIs
  2. Loading Images with Coil
  3. Error Handling & UX
  4. Push Notifications
  5. WorkManager & Background Tasks
  6. Publishing to Play Store
← Back to Android Academy