Завантаження даних, синхронізація вмісту, надсилання аналітики — багато завдань не потребують активної участі користувача. Однак мобільні пристрої обмежують фонову роботу для економії батареї та збереження продуктивності. Фонові завдання (background tasks) — це механізми, які дозволяють додатку виконувати код, коли користувач його не бачить. У цій статті розглянемо WorkManager, BGTaskScheduler, Foreground Service та особливості Doze Mode. Детальніше — в офіційній документації WorkManager.
Головне
Фонове завдання — це будь-який код, що виконується, коли додаток не знаходиться на передньому плані (активний екран). Це може бути: періодична синхронізація даних із сервером, завантаження великих файлів, обробка push-сповіщень, відстеження геолокації, оновлення віджетів. Кожна платформа має власні обмеження на фонову роботу: iOS більш сувора (10–30 хвилин фонового часу), Android лояльніший, але з версії 9 посилив правила.
Архітектура фонових завдань будується на трьох рівнях: (1) негайні завдання — виконуються прямо зараз (Foreground Service); (2) відкладені завдання — виконуються за відповідних умов (WorkManager, BGTaskScheduler); (3) періодичні завдання — повторюються із заданим інтервалом. Правильний вибір рівня визначає, чи буде завдання виконано вчасно і чи не призведе до блокування додатку магазином.
На обох платформах Google/Apple наполегливо рекомендують використовувати декларативні API замість прямого керування потоками у фоні. WorkManager на Android та BGTaskScheduler на iOS дозволяють системі оптимально розподіляти фонову роботу між додатками, групуючи завдання для економії енергії. У IT Sectr ми завжди починаємо проєктування фонової архітектури з аналізу вимог до частоти та терміновості оновлень.
iOS надає кілька механізмів для фонової роботи. Background Fetch — періодичне оновлення вмісту з інтервалом, який визначає система (не розробник). Додаток отримує вікно ~30 секунд для завантаження нових даних. Background Fetch вмикається через Capabilities → Background Modes → Background Fetch та реалізується в AppDelegate: application(_:performFetchWithCompletionHandler:).
BGTaskScheduler — сучасний API для iOS 13+, який замінює Background Fetch. Розробник реєструє завдання з ідентифікатором, а система запускає його за відповідних умов. BGAppRefreshTask — для коротких оновлень вмісту; BGProcessingTask — для тривалих завдань (очищення кешу, синхронізація бази даних). Завдання реєструються при запуску додатку, а система планує їх виконання з урахуванням стану батареї, мережі та активності користувача.
Background Modes — список режимів, які дозволяють фонову роботу для конкретних сценаріїв: Audio (фонове відтворення), Location (GPS-трекінг), VoIP (дзвінки через PushKit), BLE (підключення до Bluetooth-пристроїв), Processing (тривалі завдання через BGTaskScheduler). Кожен режим потребує обґрунтування при рев'ю App Store. Використання режимів без реальної потреби — часта причина відхилення додатку.
Significant Location Change — механізм для додатків, яким не потрібна постійна геолокація, але важливо знати про значне переміщення користувача (понад 500 метрів). Система сама пробуджує додаток при зміні вишки стільникового зв'язку. Цей механізм значно економить батарею порівняно з постійним GPS-трекінгом.
Android пропонує найбагатший набір API для фонових завдань, але з версії 8.0 (API 26) правила стали суворішими. WorkManager — рекомендоване рішення від Google для всіх типів фонових завдань. WorkManager гарантує виконання завдання навіть після перезавантаження пристрою (через BootReceiver) та підтримує ланцюжки завдань, спостережувані LiveData/Flow та зворотну сумісність до API 14.
WorkManager використовує Worker — базовий клас з методом doWork(). Constraints визначають умови виконання: NetworkType.CONNECTED, BatteryNotLow, StorageNotLow. PeriodicWorkRequest — для періодичних завдань з мінімальним інтервалом 15 хвилин. WorkManager автоматично адаптується до Doze Mode та App Standby, групуючи завдання у вікна обслуговування. Приклад простого Worker:
class SyncWorker(
context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
return try {
val repository =
Injection.provideRepository(applicationContext)
repository.syncData()
Result.success()
} catch (e: Exception) {
Result.retry()
}
}
}
// Запланировать задачу
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
val syncRequest = OneTimeWorkRequestBuilder<SyncWorker>()
.setConstraints(constraints)
.build()
WorkManager.getInstance(context)
.enqueue(syncRequest)
JobScheduler — старіший API (Android 5+, API 21). Планує завдання із зазначенням умов (мережа, зарядка, простоювання). Обмеження: не підтримує перезавантаження пристрою (потрібен BootReceiver) і не має спостережуваного стану. JobScheduler підходить для простих завдань у застарілих проєктах; для нових проєктів слід використовувати WorkManager.
Foreground Service — сервіс, який користувач бачить через постійне сповіщення (ongoing notification). Використовується для: відтворення музики, запису GPS-треку, завантаження великих файлів. Foreground Service має високий пріоритет — система не вб'є його при нестачі пам'яті. Починаючи з Android 13, потрібен дозвіл FOREGROUND_SERVICE_SPECIAL_USE для деяких типів. Альтернатива — WorkManager з ForegroundServiceOption (довгі завдання).
AlarmManager — для завдань, які мають виконатися в точний час (будильник, нагадування). AlarmManager може розбудити пристрій із Doze Mode (setAlarmClock). Не рекомендується для звичайної синхронізації через високе енергоспоживання. Для періодичних завдань використовуйте WorkManager, а AlarmManager — тільки коли точний час критичний.
| Сценарій | iOS | Android |
|---|---|---|
| Періодичне оновлення вмісту | BGAppRefreshTask (BGTaskScheduler) | WorkManager (PeriodicWorkRequest) |
| Тривале фонове завдання | BGProcessingTask | WorkManager + ForegroundService |
| Відтворення аудіо | Background Audio Mode | Foreground Service |
| GPS-трекінг | Significant Location Change / Background Location | Foreground Service + FusedLocationProvider |
| VoIP / Дзвінки | PushKit + CallKit | ConnectionService + Foreground Service |
| Точний час (будильник) | UNNotificationRequest (calendar) | AlarmManager |
| Обробка push (фоново) | Notification Service Extension | FirebaseMessagingService (onMessageReceived) |
Doze Mode — режим енергозбереження Android, що впливає на виконання фонових завдань. Введений в Android 6.0 (API 23). Коли пристрій не заряджається, екран вимкнено і пристрій нерухомий, Doze Mode забороняє мережеві запити, відкладає JobScheduler та WakeLock. Періодично Doze відкриває «вікна обслуговування» — короткі проміжки, коли додатки можуть виконати відкладені завдання. З версії Android 7.0 (API 24) Doze активується при вимкненому екрані, а не тільки в повній нерухомості.
App Standby — режим, при якому невикористовувані додатки переводяться в «очікування». Якщо додаток не має активного сповіщення і не відкривався кілька днів, він поміщається в Standby Bucket: активний (active), робочий (working), частий (frequent), рідкісний (rare). Чим рідше використовується додаток, тим сильніші обмеження: мережеві запити відкладаються, синхронізація блокується, JobScheduler не запускається.
WakeLock — механізм, що утримує пристрій в активному стані (не дає заснути). Використовується для завершення важливих операцій. WakeLock потрібно обов'язково відпускати (release) після виконання завдання, інакше батарея розрядиться за кілька годин. WakeLock не працює в Doze Mode — система ігнорує його. Робота з WakeLock на Android 8+ вимагає дозволу WAKE_LOCK та правильного керування життєвим циклом.
В IT Sectr ми враховуємо Doze Mode та App Standby на етапі проєктування. WorkManager автоматично обробляє ці режими, але для Foreground Service потрібно передбачити коректну обробку переходів у Doze. Рекомендується тестувати фонову роботу на реальних пристроях з увімкненим режимом енергозбереження та після тривалого простою.
При проєктуванні фонових завдань дотримуйтесь наступних порад. 1. Завжди використовуйте WorkManager для нових Android-проєктів. Він вирішує проблеми сумісності, Doze Mode та перезавантаження пристрою. 2. На iOS віддавайте перевагу BGTaskScheduler замість Background Fetch для iOS 13+. 3. Foreground Service використовуйте тільки коли завдання дійсно потребує видимого сповіщення. 4. Не зловживайте WakeLock — це вбиває батарею і може призвести до блокування додатку. 5. Тестуйте фонові завдання в Doze Mode: adb shell dumpsys deviceidle force-idle. 6. Завжди перевіряйте, що завдання виконалося, через логування та аналітику. 7. Пам'ятайте про ліміти: iOS дає ~30 секунд на Background Fetch та ~кілька хвилин на BGProcessingTask. Android WorkManager не гарантує точний час виконання.
Часті запитання
Background Service працює без видимого сповіщення і може бути вбитий системою в будь-який момент. Foreground Service зобов'язаний показати постійне сповіщення (ongoing notification) і має вищий пріоритет. Foreground Service використовується для відтворення музики та запису GPS-треку.
Doze Mode — режим енергозбереження Android, який вимикає мережевий доступ і відкладає JobScheduler/WakeLock, коли пристрій не використовується. WorkManager адаптується до Doze Mode автоматично.
На iOS фонові завдання виконуються через Background Fetch (періодичне оновлення), BGTaskScheduler (відкладені завдання) або Background Modes (аудіо, VoIP, BLE, місцезнаходження). BGTaskScheduler — сучасний API для iOS 13+, що замінює Background Fetch.
WorkManager — рекомендоване рішення від Google для всіх фонових завдань на Android. JobScheduler — старіший API, обмежений за можливостями. WorkManager підтримує ланцюжки завдань, спостережувані LiveData/Flow та зворотну сумісність до API 14.
App Standby — режим Android, при якому невикористовувані додатки переводяться в стан очікування: мережеві запити відкладаються, синхронізація призупиняється. Якщо додаток не використовується кілька днів, Android поміщає його в Standby Bucket (активний, робочий, частий, рідкісний).
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.