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
CoroutineWorkerand implementdoWork() - Return
Result.success(),.failure(), or.retry() - Use
OneTimeWorkRequestfor single runs,PeriodicWorkRequestfor recurring - Add
Constraintsfor 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
- Retrofit & REST APIs
- Loading Images with Coil
- Error Handling & UX
- Push Notifications
- WorkManager & Background Tasks
- Publishing to Play Store