last update
Jun 2, 2026
license
MITv1.0.0
format
SKILL.md
- Install
// Downloads SKILL.md into ~/.claude/skills/android-workmanager-jobs/
$ curl -fsSL --create-dirs -o ~/.claude/skills/android-workmanager-jobs/SKILL.md https://claudeskil.com/skills/android-workmanager-jobs/SKILL.md - Invoke
// Inside Claude Code, type the skill name as a slash command
> /android-workmanager-jobs help me ship this - Or copy this from the README
// extracted kotlin block
$ @HiltWorker class UploadWorker @AssistedInject constructor( @Assisted ctx: Context, @Assisted params: WorkerParameters, private val repo: MediaRepo, ) : CoroutineWorker(ctx, params) {
- name:
- Android WorkManager Jobs
- slug:
- android-workmanager-jobs
- version:
- v1.0.0
- license:
- MIT
- author:
- @chiragthummar16
- categories:
- tags:
- #workmanager#background-jobs#kotlin#scheduling#hilt
- description:
Background jobs done right — constraints, retries, chains, periodic work, expedited jobs, foreground service.
README.md
Android WorkManager Jobs
Production-grade scaffolding for deferrable background work on Android using Jetpack WorkManager. This skill helps you pick the right worker type, wire constraints and backoff correctly, inject dependencies into workers with Hilt, and test the whole thing deterministically. It's aimed at Android engineers who keep getting bitten by jobs that never run, run twice, or get killed under Doze.
When to use it
- You need work to survive process death and reboots — uploads, log syncs, cache cleanup, DB compaction.
- A task must wait for conditions:
NetworkType.UNMETERED, charging, battery-not-low, or storage-not-low. - You're chaining steps where one worker's output feeds the next (compress → upload → notify).
- You need a user-visible long task (large download) via an expedited/foreground job.
- You're ripping out the deprecated Firebase JobDispatcher or
GcmNetworkManagerand consolidating on WorkManager.
How it works
The skill generates CoroutineWorker (or Worker) subclasses returning Result.success(), Result.retry(), or Result.failure(), plus the request builders that schedule them:
- OneTimeWorkRequestBuilder vs PeriodicWorkRequestBuilder (15-minute minimum interval, optional flex window).
- Constraints.Builder with
setRequiredNetworkType,setRequiresCharging, etc. - Backoff via
setBackoffCriteria(BackoffPolicy.EXPONENTIAL, ...). - Uniqueness with
enqueueUniqueWork(... ExistingWorkPolicy.KEEP/REPLACE)andenqueueUniquePeriodicWork(... ExistingPeriodicWorkPolicy.UPDATE). - Chains through
WorkManager.beginWith(a).then(b)andData/workDataOfpassing. - Hilt via
@HiltWorker,@AssistedInject, and aHiltWorkerFactoryregistered throughConfiguration.Provider(disable the default initializer in the manifest). - Expedited jobs with
setExpedited(OutOfQuotaPolicy...)andsetForegroundAsync/getForegroundInfo.
Example
curl -fsSL --create-dirs -o ~/.claude/skills/android-workmanager-jobs/SKILL.md https://claudeskil.com/skills/android-workmanager-jobs/SKILL.md
@HiltWorker
class UploadWorker @AssistedInject constructor(
@Assisted ctx: Context,
@Assisted params: WorkerParameters,
private val repo: MediaRepo,
) : CoroutineWorker(ctx, params) {
override suspend fun doWork(): Result =
runCatching { repo.upload(inputData.getString("uri")!!) }
.fold({ Result.success() }, { if (runAttemptCount < 3) Result.retry() else Result.failure() })
}
val req = OneTimeWorkRequestBuilder<UploadWorker>()
.setConstraints(Constraints.Builder().setRequiredNetworkType(NetworkType.UNMETERED).build())
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 30, TimeUnit.SECONDS)
.build()
WorkManager.getInstance(ctx).enqueueUniqueWork("upload", ExistingWorkPolicy.KEEP, req)
Tips & gotchas
- Periodic work can't be expedited and won't fire more often than every 15 minutes — the OS coalesces it.
- If you use
@HiltWorker, you must remove the defaultWorkManagerInitializerprovider in the manifest, or the custom factory is ignored. - Read
runAttemptCountto cap retries;Result.retry()alone loops forever under your backoff curve. - Expedited quota is finite — pick
RUN_AS_NON_EXPEDITED_WORK_REQUESTas the fallback policy to avoid silent failures.
FAQ
Why does my unique periodic work not pick up new constraints? Use ExistingPeriodicWorkPolicy.UPDATE (API since WorkManager 2.8) so the request is replaced in place rather than kept.
How do I test workers without a real device clock? The skill scaffolds WorkManagerTestInitHelper.initializeTestWorkManager, then drives execution with TestDriver.setAllConstraintsMet, setPeriodDelayMet, and setInitialDelayMet.
Can I observe results? Yes — getWorkInfoByIdLiveData / getWorkInfosForUniqueWorkFlow expose WorkInfo.State and the output Data.
authored by
@chiragthummar16Android Jetpack Pro
Ship Jetpack Compose screens, ViewModels, and Gradle config with idiomatic best practices baked in.
0iOS SwiftUI Architect
Design SwiftUI apps with clean architecture: MV pattern, @Observable, and Swift Concurrency.
0PPT Deck Designer
Turn a rough outline into a visually polished pitch deck with on-brand layouts and speaker notes.
0Video Cut Assistant
Produce edit decision lists, trim plans, and subtitle cues from raw footage transcripts.
0
$ cat reviews/