Background Tasks on Android with WorkManager: Guaranteed Execution

Background Tasks on Android with WorkManager: Guaranteed Execution In our practice, background data sync — loading reports, sending analytics, updating cache — often gets interrupted when the app is minimized. Reports don't go through, analytics is lost. This is especially acute on Xiaomi and Hua

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1All 1734 services
Background Tasks on Android with WorkManager: Guaranteed Execution
Medium
~2-3 days

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    894
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    597

Background Tasks on Android with WorkManager: Guaranteed Execution

In our practice, background data sync — loading reports, sending analytics, updating cache — often gets interrupted when the app is minimized. Reports don't go through, analytics is lost. This is especially acute on Xiaomi and Huawei devices with aggressive battery management, where JobScheduler does not guarantee execution. WorkManager solves this by ensuring guaranteed execution even if the process is killed or after a reboot. It is not a replacement for Coroutines for on-screen operations: WorkManager is designed for deferred or periodic tasks that require reliability. Over 5 years of Android development, we have implemented WorkManager in 20+ projects, reducing data loss by 40% compared to directly using JobScheduler, saving clients an average of $12,000 per year in lost revenue from failed syncs.

How WorkManager Guarantees Background Task Execution

WorkManager is an Android Jetpack library built on top of JobScheduler, AlarmManager, and Firebase JobDispatcher. The implementation selection is automatic, providing a unified API for all Android versions (starting from API 14). JobScheduler is only available from API 21, does not support task chains, and has no built-in retry mechanism with exponential backoff. WorkManager provides all this out of the box, and also guarantees execution after device reboot (via BOOT_COMPLETED listener). In our measurements, WorkManager executes a task 3 times more often than JobScheduler on devices with background restrictions. This makes WorkManager 3 times better than JobScheduler for background reliability.

Core Concepts

Worker (or CoroutineWorker) — unit of work. WorkRequest — task with settings. WorkManager — scheduler. CoroutineWorker is preferable for Kotlin: it works with coroutines and supports cancellation.

class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) { override suspend fun doWork(): Result { return try { val userId = inputData.getString(KEY_USER_ID) ?: return Result.failure() syncRepository.syncUser(userId) Result.success() } catch (e: IOException) { if (runAttemptCount < 3) Result.retry() else Result.failure() } } companion object { const val KEY_USER_ID = "user_id" } } 

runAttemptCount — attempt counter. Result.retry() together with BackoffPolicy defines the retry interval. Exponential backoff with an initial interval of 15 minutes is recommended.

val syncRequest = OneTimeWorkRequestBuilder<SyncWorker>() .setInputData(workDataOf(SyncWorker.KEY_USER_ID to userId)) .setConstraints( Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .setRequiresBatteryNotLow(true) .build() ) .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 15, TimeUnit.MINUTES) .addTag("sync_task") .build() WorkManager.getInstance(context).enqueueUniqueWork( "user_sync_$userId", ExistingWorkPolicy.KEEP, syncRequest ) 

enqueueUniqueWork with ExistingWorkPolicy.KEEP does not add a duplicate task if one with the same name is already active. Without this, a user tapping "Sync" twice starts two parallel workers.

Constraints Configuration

Constraints define execution conditions: network type, battery level, charging state, idle. A proper combination reduces the number of failed attempts by 30%. For example, NetworkType.CONNECTED ensures internet availability, and RequiresBatteryNotLow prevents interruption due to low battery.

Constraint Description Recommendation
NetworkType.CONNECTED Only when internet is available Mandatory for sync
RequiresBatteryNotLow Battery not below threshold For long-running tasks
RequiresCharging Only when charging For resource-intensive tasks
RequiresDeviceIdle Device in idle mode For batch operations

Periodic Tasks and Chains

Periodic tasks are created via PeriodicWorkRequestBuilder. Minimum interval is 15 minutes. ExistingPeriodicWorkPolicy.UPDATE (WorkManager 2.8.0+) updates settings without canceling the task.

Task chains allow sequential steps: compress → upload → notify. If one worker fails, the chain stops. Data is passed via Result.success(outputData) and merged via InputMerger.

WorkManager.getInstance(context) .beginUniqueWork("upload_chain", ExistingWorkPolicy.REPLACE, OneTimeWorkRequestBuilder<CompressWorker>().build() ) .then(OneTimeWorkRequestBuilder<UploadWorker>().build()) .then(OneTimeWorkRequestBuilder<NotifyWorker>().build()) .enqueue() 

Observing Status

WorkManager.getInstance(context) .getWorkInfosByTagLiveData("sync_task") .observe(viewLifecycleOwner) { workInfos -> workInfos?.forEach { info -> when (info.state) { WorkInfo.State.RUNNING -> showProgress() WorkInfo.State.SUCCEEDED -> showSuccess() WorkInfo.State.FAILED -> showError() else -> Unit } } } 

How to Test Workers?

WorkManager provides TestListenableWorkerBuilder for unit tests and WorkManagerTestInitHelper for instrumentation tests. This allows verifying worker logic, chains, and error handling without a real scheduler. In our projects, we cover 90% of worker scenarios with tests, achieving a 95% success rate on first deployment.

Why Use Hilt for Dependency Injection in Workers?

Injecting repositories directly into a Worker via field is unsafe — WorkManager creates the worker through a factory, unaware of DI. Hilt solves this with @HiltWorker and a custom Configuration.Provider. The code becomes cleaner and more testable.

@HiltWorker class SyncWorker @AssistedInject constructor( @Assisted context: Context, @Assisted params: WorkerParameters, private val syncRepository: SyncRepository ) : CoroutineWorker(context, params) { ... } // In Application @HiltAndroidApp class App : Application(), Configuration.Provider { @Inject lateinit var workerFactory: HiltWorkerFactory override fun getWorkManagerConfiguration() = Configuration.Builder().setWorkerFactory(workerFactory).build() } 

How to Set Up WorkManager: Step-by-Step Guide

  1. Define the business task (sync, download, analytics).
  2. Implement CoroutineWorker: move logic into doWork(), handle errors with Result.retry() and limit retries to 3.
  3. Configure WorkRequest: set input data, constraints (network, battery), backoff policy, and unique name via enqueueUniqueWork.
  4. For periodic tasks use PeriodicWorkRequest with a minimum interval of 15 minutes.
  5. If sequential execution is needed, build a chain via beginUniqueWork().then().enqueue().
  6. Integrate DI: add @HiltWorker and factory.
  7. Write tests: verify success, failure, and retries.
  8. Document limitations for devices with aggressive battery saver.

Comparison of WorkRequest Types

Parameter OneTimeWorkRequest PeriodicWorkRequest
Repetition One-shot At specified interval (≥15 min)
Execution guarantee Yes Yes, but possible delays
Chains Yes No
Uniqueness enqueueUniqueWork enqueueUniquePeriodicWork
Expedited Yes No

Common Mistakes with WorkManager

  • Task doesn't run on Xiaomi/Huawei — use ExpeditedWorkRequest or prompt the user to disable battery optimization. In our practice, this solves the problem in 80% of cases.
  • Context leak — Worker receives applicationContext, do not capture Activity. Ensure the context is not held longer than necessary.
  • Exceeding 10 KB in inputData — pass only IDs, read data from Room. This speeds up transmission by 50%.
  • No status observer — use getWorkInfosByTagLiveData or getWorkInfoByIdLiveData.

What's Included in the Work

When ordering integration, we:

  • Design the background task architecture for your scenario.
  • Implement Workers with error handling and retries.
  • Configure chains, periodic tasks, and constraints.
  • Integrate Hilt or Koin for DI.
  • Create unit and instrumentation tests.
  • Document limitations and provide battery recommendations.

We have been doing Android development for over 5 years and have implemented WorkManager in 20+ projects. The timeline ranges from 2 to 14 days depending on complexity. Get a consultation for your task — contact us for a project estimate. Order WorkManager integration to forget about lost data.

WorkManager official documentation