Android Background Task Specialist
Expert in Android background execution with WorkManager, Foreground Services, Doze mode handling, and battery-efficient processing.
Activation Triggers
Activate on: "WorkManager", "background task Android", "Foreground Service", "Doze mode", "battery optimization", "periodic work", "background sync", "JobScheduler", "background processing Android"
NOT for: iOS background tasks → swiftui-data-flow-expert | React Native background → mobile-offline-sync-architect | UI architecture → jetpack-compose-navigation-expert
Quick Start
- Choose the right API — WorkManager for deferrable work, Foreground Service for user-visible ongoing tasks, coroutines for short async work
- Define workers — extend
CoroutineWorker with suspend functions for clean async code
- Configure constraints — network type, battery level, storage requirements
- Handle Doze and App Standby — use WorkManager (not AlarmManager) for Doze-compatible scheduling
- Test with adb — force Doze mode and verify work executes when constraints are met
Core Capabilities
| Domain |
Technologies |
| Deferrable Work |
WorkManager 2.10, OneTimeWorkRequest, PeriodicWorkRequest |
| Foreground |
Foreground Service types (dataSync, location, mediaPlayback, shortService) |
| Constraints |
NetworkType, BatteryNotLow, StorageNotLow, DeviceIdle |
| Chaining |
WorkContinuation, parallel chains, unique work policies |
| Testing |
TestWorkerBuilder, TestListenableWorkerBuilder, WorkManagerTestInitHelper |
Architecture Patterns
WorkManager Decision Tree
Is the task user-initiated and needs to complete?
├─ YES → Is it short (< 10 min)?
│ ├─ YES → Foreground Service (shortService type)
│ └─ NO → Foreground Service (dataSync, location, etc.)
│
└─ NO → Is it deferrable?
├─ YES → WorkManager
│ ├─ One-time? → OneTimeWorkRequest
│ └─ Periodic? → PeriodicWorkRequest (min 15 min interval)
│
└─ NO → Is it while app is visible?
├─ YES → CoroutineScope (viewModelScope or lifecycleScope)
└─ NO → You probably need WorkManager anyway
CoroutineWorker with Retry and Progress
@HiltWorker
class SyncWorker @AssistedInject constructor(
@Assisted context: Context,
@Assisted params: WorkerParameters,
private val syncRepository: SyncRepository,
private val notificationHelper: NotificationHelper,
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
// Report progress for UI observation
setProgress(workDataOf("progress" to 0))
return try {
val pendingItems = syncRepository.getPendingChanges()
pendingItems.forEachIndexed { index, item ->
syncRepository.syncItem(item)
setProgress(workDataOf(
"progress" to ((index + 1) * 100 / pendingItems.size)
))
}
Result.success(workDataOf("synced" to pendingItems.size))
} catch (e: IOException) {
if (runAttemptCount < 3) {
Result.retry() // Exponential backoff by default
} else {
Result.failure(workDataOf("error" to e.message))
}
}
}
override suspend fun getForegroundInfo(): ForegroundInfo {
return ForegroundInfo(
NOTIFICATION_ID,
notificationHelper.createSyncNotification()
)
}
}
Scheduling with Constraints and Chaining
// Schedule periodic sync every 1 hour (minimum 15 min)
val syncRequest = PeriodicWorkRequestBuilder<SyncWorker>(1, TimeUnit.HOURS)
.setConstraints(
Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.build()
)
.setBackoffCriteria(
BackoffPolicy.EXPONENTIAL,
WorkRequest.MIN_BACKOFF_MILLIS,
TimeUnit.MILLISECONDS
)
.addTag("sync")
.build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
"periodic-sync",
ExistingPeriodicWorkPolicy.KEEP, // Don't restart if already scheduled
syncRequest
)
// Chain: download → process → upload (sequential)
WorkManager.getInstance(context)
.beginWith(downloadWork)
.then(processWork)
.then(uploadWork)
.enqueue()
Anti-Patterns
- AlarmManager for deferrable work — AlarmManager alarms are not Doze-compatible and drain battery. Use WorkManager which respects Doze, App Standby, and battery saver.
- Background Service without foreground notification — Android 12+ kills background services. Use Foreground Service with proper type declaration or WorkManager.
- PeriodicWork under 15 minutes — WorkManager enforces a minimum 15-minute interval. For more frequent work, use Foreground Service or coroutine with lifecycle awareness.
- Not declaring foreground service type — Android 14+ requires explicit
foregroundServiceType in manifest. Omitting it causes SecurityException.
- Ignoring work observation — starting work but not showing progress to users. Observe
WorkInfo via getWorkInfoByIdLiveData() or getWorkInfoByIdFlow() to update UI.
Quality Checklist
[ ] WorkManager used for deferrable background tasks (not AlarmManager)
[ ] Foreground Service declared with correct type in AndroidManifest
[ ] Constraints configured (network, battery, storage)
[ ] Retry policy with backoff for transient failures
[ ] Unique work policy set for periodic/one-time work
[ ] Work progress observable from UI
[ ] Doze mode tested via adb: `adb shell dumpsys deviceidle force-idle`
[ ] Battery optimization tested: `adb shell am set-inactive <package> true`
[ ] Workers tested with TestWorkerBuilder
[ ] Notification channels created for foreground service notifications
[ ] Work chains handle partial failure gracefully
[ ] Background work respects user's battery saver preference
1---2name: android-background-task-specialist3description: Android background task specialist for WorkManager, Foreground Services, Doze mode, and battery optimization. Activate on: WorkManager, background task Android, Foreground Service, Doze mode, battery optimization, periodic work, background sync Android, JobScheduler. NOT for: iOS background tasks (use swiftui-data-flow-expert), React Native background (use mobile-offline-sync-architect), UI architecture (use jetpack-compose-navigation-expert).4license: Apache-2.05---67# Android Background Task Specialist89Expert in Android background execution with WorkManager, Foreground Services, Doze mode handling, and battery-efficient processing.1011## Activation Triggers1213**Activate on:** "WorkManager", "background task Android", "Foreground Service", "Doze mode", "battery optimization", "periodic work", "background sync", "JobScheduler", "background processing Android"1415**NOT for:** iOS background tasks → `swiftui-data-flow-expert` | React Native background → `mobile-offline-sync-architect` | UI architecture → `jetpack-compose-navigation-expert`1617## Quick Start18191. **Choose the right API** — WorkManager for deferrable work, Foreground Service for user-visible ongoing tasks, coroutines for short async work202. **Define workers** — extend `CoroutineWorker` with suspend functions for clean async code213. **Configure constraints** — network type, battery level, storage requirements224. **Handle Doze and App Standby** — use WorkManager (not AlarmManager) for Doze-compatible scheduling235. **Test with adb** — force Doze mode and verify work executes when constraints are met2425## Core Capabilities2627| Domain | Technologies |28|--------|-------------|29| **Deferrable Work** | WorkManager 2.10, OneTimeWorkRequest, PeriodicWorkRequest |30| **Foreground** | Foreground Service types (dataSync, location, mediaPlayback, shortService) |31| **Constraints** | NetworkType, BatteryNotLow, StorageNotLow, DeviceIdle |32| **Chaining** | WorkContinuation, parallel chains, unique work policies |33| **Testing** | TestWorkerBuilder, TestListenableWorkerBuilder, WorkManagerTestInitHelper |3435## Architecture Patterns3637### WorkManager Decision Tree3839```40Is the task user-initiated and needs to complete?41 ├─ YES → Is it short (< 10 min)?42 │ ├─ YES → Foreground Service (shortService type)43 │ └─ NO → Foreground Service (dataSync, location, etc.)44 │45 └─ NO → Is it deferrable?46 ├─ YES → WorkManager47 │ ├─ One-time? → OneTimeWorkRequest48 │ └─ Periodic? → PeriodicWorkRequest (min 15 min interval)49 │50 └─ NO → Is it while app is visible?51 ├─ YES → CoroutineScope (viewModelScope or lifecycleScope)52 └─ NO → You probably need WorkManager anyway53```5455### CoroutineWorker with Retry and Progress5657```kotlin58@HiltWorker59class SyncWorker @AssistedInject constructor(60 @Assisted context: Context,61 @Assisted params: WorkerParameters,62 private val syncRepository: SyncRepository,63 private val notificationHelper: NotificationHelper,64) : CoroutineWorker(context, params) {6566 override suspend fun doWork(): Result {67 // Report progress for UI observation68 setProgress(workDataOf("progress" to 0))6970 return try {71 val pendingItems = syncRepository.getPendingChanges()7273 pendingItems.forEachIndexed { index, item ->74 syncRepository.syncItem(item)75 setProgress(workDataOf(76 "progress" to ((index + 1) * 100 / pendingItems.size)77 ))78 }7980 Result.success(workDataOf("synced" to pendingItems.size))81 } catch (e: IOException) {82 if (runAttemptCount < 3) {83 Result.retry() // Exponential backoff by default84 } else {85 Result.failure(workDataOf("error" to e.message))86 }87 }88 }8990 override suspend fun getForegroundInfo(): ForegroundInfo {91 return ForegroundInfo(92 NOTIFICATION_ID,93 notificationHelper.createSyncNotification()94 )95 }96}97```9899### Scheduling with Constraints and Chaining100101```kotlin102// Schedule periodic sync every 1 hour (minimum 15 min)103val syncRequest = PeriodicWorkRequestBuilder<SyncWorker>(1, TimeUnit.HOURS)104 .setConstraints(105 Constraints.Builder()106 .setRequiredNetworkType(NetworkType.CONNECTED)107 .setRequiresBatteryNotLow(true)108 .build()109 )110 .setBackoffCriteria(111 BackoffPolicy.EXPONENTIAL,112 WorkRequest.MIN_BACKOFF_MILLIS,113 TimeUnit.MILLISECONDS114 )115 .addTag("sync")116 .build()117118WorkManager.getInstance(context).enqueueUniquePeriodicWork(119 "periodic-sync",120 ExistingPeriodicWorkPolicy.KEEP, // Don't restart if already scheduled121 syncRequest122)123124// Chain: download → process → upload (sequential)125WorkManager.getInstance(context)126 .beginWith(downloadWork)127 .then(processWork)128 .then(uploadWork)129 .enqueue()130```131132## Anti-Patterns1331341. **AlarmManager for deferrable work** — AlarmManager alarms are not Doze-compatible and drain battery. Use WorkManager which respects Doze, App Standby, and battery saver.1352. **Background Service without foreground notification** — Android 12+ kills background services. Use Foreground Service with proper type declaration or WorkManager.1363. **PeriodicWork under 15 minutes** — WorkManager enforces a minimum 15-minute interval. For more frequent work, use Foreground Service or coroutine with lifecycle awareness.1374. **Not declaring foreground service type** — Android 14+ requires explicit `foregroundServiceType` in manifest. Omitting it causes `SecurityException`.1385. **Ignoring work observation** — starting work but not showing progress to users. Observe `WorkInfo` via `getWorkInfoByIdLiveData()` or `getWorkInfoByIdFlow()` to update UI.139140## Quality Checklist141142```143[ ] WorkManager used for deferrable background tasks (not AlarmManager)144[ ] Foreground Service declared with correct type in AndroidManifest145[ ] Constraints configured (network, battery, storage)146[ ] Retry policy with backoff for transient failures147[ ] Unique work policy set for periodic/one-time work148[ ] Work progress observable from UI149[ ] Doze mode tested via adb: `adb shell dumpsys deviceidle force-idle`150[ ] Battery optimization tested: `adb shell am set-inactive <package> true`151[ ] Workers tested with TestWorkerBuilder152[ ] Notification channels created for foreground service notifications153[ ] Work chains handle partial failure gracefully154[ ] Background work respects user's battery saver preference155```