Skip to content

WorkManager ​

Hub › Android › Advanced › WorkManager

Goal

Schedule a periodic background sync with WorkManager that refreshes the item list even when the app is not in the foreground.

Prerequisites

Why WorkManager ​

WorkManager handles deferrable, guaranteed background work. It respects Doze mode, battery optimizations, and API level differences:

ScenarioWhat happens
App in foregroundWork runs immediately
App in backgroundWork runs when constraints are met
Device dozingWorkManager batches and defers
Device rebootWork is rescheduled automatically

SyncWorker ​

Create SyncWorker.kt:

kotlin
import android.content.Context
import androidx.hilt.work.HiltWorker
import androidx.work.*
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject

@HiltWorker
class SyncWorker @AssistedInject constructor(
    @Assisted context: Context,
    @Assisted workerParams: WorkerParameters,
    private val repository: ItemRepository
) : CoroutineWorker(context, workerParams) {

    override suspend fun doWork(): Result {
        return try {
            repository.refresh()
            Result.success()
        } catch (e: Exception) {
            if (runAttemptCount < 3) Result.retry() else Result.failure()
        }
    }
}

Hilt WorkManager integration ​

kotlin
// app-level build.gradle.kts
dependencies {
    implementation("androidx.hilt:hilt-work:1.2.0")
    kapt("androidx.hilt:hilt-compiler:1.2.0")
}

Schedule periodic sync ​

Create a scheduling helper:

kotlin
import androidx.work.*

object SyncScheduler {
    private const val WORK_NAME = "periodic_sync"

    fun schedule(context: Context) {
        val constraints = Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build()

        val request = PeriodicWorkRequestBuilder<SyncWorker>(
            15, TimeUnit.MINUTES
        ).setConstraints(constraints)
            .setBackoffCriteria(
                BackoffPolicy.EXPONENTIAL,
                1, TimeUnit.MINUTES
            )
            .build()

        WorkManager.getInstance(context).enqueueUniquePeriodicWork(
            WORK_NAME,
            ExistingPeriodicWorkPolicy.KEEP,
            request
        )
    }
}

Call from the Application class:

kotlin
@HiltAndroidApp
class App : Application(), Configuration.Provider {
    override fun onCreate() {
        super.onCreate()
        SyncScheduler.schedule(this)
    }

    // Required for Hilt + WorkManager
    override val workManagerConfiguration: Configuration
        get() = Configuration.Builder()
            .setWorkerFactory(HiltWorkFactory(this))
            .build()
}

Observe sync state ​

kotlin
WorkManager.getInstance(context)
    .getWorkInfosForUniqueWorkLiveData(WORK_NAME)
    .observe(owner) { infos ->
        val state = infos.firstOrNull()?.state
        // RUNNING, SUCCEEDED, FAILED
    }

Checkpoint ​

bash
# Run app, background it (Home button)
# WorkManager syncs every 15 minutes in background
# Kill app, reopen — items from latest sync visible immediately

Next: Unit tests — JUnit, Turbine for Flow, Room in-memory.