Реализация WorkManager для фоновых задач в Android-приложении

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Реализация WorkManager для фоновых задач в Android-приложении
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Реализация WorkManager для фоновых задач в Android-приложении

WorkManager — стандартный API для фоновых задач, которые должны выполняться гарантированно: загрузка файлов, синхронизация данных, отправка аналитики. Это не замена Coroutines для разовых операций — WorkManager нужен там, где задача должна завершиться даже если приложение убито или устройство перезагружено.

Основные концепции

Worker / CoroutineWorker — единица работы. WorkRequest — задача с настройками. WorkManager — планировщик, реализованный поверх JobScheduler (API 23+), AlarmManager (старые версии) и Firebase JobDispatcher (если доступен). Выбор между ними — автоматический.

CoroutineWorker — предпочтительный вариант для Kotlin:

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 — счётчик попыток. Result.retry() вместе с BackoffPolicy определяет, через сколько времени WorkManager повторит задачу.

Настройка задачи

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 с ExistingWorkPolicy.KEEP — не добавляет дублирующую задачу, если уже есть активная с тем же именем. Без этого пользователь, тапнувший кнопку «Синхронизировать» дважды, запускает два параллельных воркера.

Периодические задачи

val periodicRequest = PeriodicWorkRequestBuilder<SyncWorker>(1, TimeUnit.HOURS)
    .setConstraints(
        Constraints.Builder()
            .setRequiredNetworkType(NetworkType.UNMETERED)
            .build()
    )
    .build()

WorkManager.getInstance(context).enqueueUniquePeriodicWork(
    "hourly_sync",
    ExistingPeriodicWorkPolicy.UPDATE,
    periodicRequest
)

Минимальный интервал для PeriodicWorkRequest — 15 минут. Короче — система игнорирует и запускает по своему расписанию. ExistingPeriodicWorkPolicy.UPDATE (появился в WorkManager 2.8.0) обновляет настройки существующей периодической задачи, не отменяя её.

Цепочки задач

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

Если CompressWorker возвращает Result.failure() — цепочка останавливается, UploadWorker не запускается. Result.success(outputData) передаёт данные в следующий воркер через inputMerger.

Наблюдение за статусом

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
            }
        }
    }

Проблемы, с которыми сталкиваются в проектах

Задача не запускается на китайских устройствах (Xiaomi, Huawei). Агрессивные battery saver убивают фоновые процессы. WorkManager использует JobScheduler, который эти производители переопределяют. Единственный надёжный обходной путь — setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) для задач, критичных к задержке, и документирование ограничений в README. Обещать пользователю точное время выполнения фоновой задачи на этих устройствах — невозможно.

Утечка контекста. Worker получает applicationContext, но разработчики иногда захватывают Activity через лямбды. Воркер живёт дольше Activity — крэш при обращении к уничтоженному контексту.

Слишком большой объём данных в inputData. Лимит — 10 КБ. Передавать ID, а не сериализованные объекты. Данные читать из Room или SharedPreferences внутри воркера.

Интеграция с Hilt

@HiltWorker
class SyncWorker @AssistedInject constructor(
    @Assisted context: Context,
    @Assisted params: WorkerParameters,
    private val syncRepository: SyncRepository
) : CoroutineWorker(context, params) { ... }

// В Application
@HiltAndroidApp
class App : Application(), Configuration.Provider {
    @Inject lateinit var workerFactory: HiltWorkerFactory

    override fun getWorkManagerConfiguration() =
        Configuration.Builder().setWorkerFactory(workerFactory).build()
}

Без кастомной Configuration.Provider Hilt не может инжектировать зависимости в Worker — WorkManager создаёт воркеры через свою фабрику по умолчанию.

Реализация WorkManager с базовым набором задач — 2-4 дня. Сложные цепочки с обработкой ошибок, синхронизацией и тестами — до 2 недель. Стоимость рассчитывается индивидуально.