Data loading, content synchronization, analytics sending — many tasks don't require active user participation. However, mobile devices limit background work to save battery and maintain performance. Background tasks are mechanisms that allow an app to execute code when the user isn't looking at it. In this article, we'll cover WorkManager, BGTaskScheduler, Foreground Service, and the specifics of Doze Mode. For more details, see the official WorkManager documentation.
Key Takeaways
A background task is any code that runs when the app is not in the foreground (active screen). This can include: periodic data synchronization with the server, downloading large files, processing push notifications, geolocation tracking, widget updates. Each platform has its own restrictions on background work: iOS is stricter (10–30 minutes of background time), Android is more lenient but has tightened rules since version 9.
The architecture of background tasks is built on three levels: (1) immediate tasks — execute right now (Foreground Service); (2) deferred tasks — execute under suitable conditions (WorkManager, BGTaskScheduler); (3) periodic tasks — repeat at a set interval. Choosing the right level determines whether the task will be completed on time and whether it will lead to app store rejection.
On both platforms, Google/Apple strongly recommend using declarative APIs instead of directly managing threads in the background. WorkManager on Android and BGTaskScheduler on iOS allow the system to optimally distribute background work between apps, grouping tasks to save energy. At IT Sectr, we always start designing background architecture by analyzing requirements for update frequency and urgency.
iOS provides several mechanisms for background work. Background Fetch — periodic content updates with an interval determined by the system (not the developer). The app gets a ~30-second window to download new data. Background Fetch is enabled via Capabilities → Background Modes → Background Fetch and implemented in AppDelegate: application(_:performFetchWithCompletionHandler:).
BGTaskScheduler is the modern API for iOS 13+, replacing Background Fetch. The developer registers a task with an identifier, and the system runs it when conditions are suitable. BGAppRefreshTask — for short content updates; BGProcessingTask — for long-running tasks (cache cleaning, database synchronization). Tasks are registered at app launch, and the system schedules them considering battery state, network, and user activity.
Background Modes — a list of modes that allow background work for specific scenarios: Audio (background playback), Location (GPS tracking), VoIP (calls via PushKit), BLE (Bluetooth device connection), Processing (long tasks via BGTaskScheduler). Each mode requires justification during App Store review. Using modes without real need is a common reason for app rejection.
Significant Location Change — a mechanism for apps that don't need constant geolocation but need to know about significant user movement (over 500 meters). The system wakes the app when the cellular tower changes. This mechanism significantly saves battery compared to constant GPS tracking.
Android offers the richest set of APIs for background tasks, but since version 8.0 (API 26), the rules have become stricter. WorkManager is the recommended solution from Google for all types of background tasks. WorkManager guarantees task execution even after device reboot (via BootReceiver) and supports task chains, observable LiveData/Flow, and backward compatibility down to API 14.
WorkManager uses Worker — a base class with the doWork() method. Constraints define execution conditions: NetworkType.CONNECTED, BatteryNotLow, StorageNotLow. PeriodicWorkRequest — for periodic tasks with a minimum interval of 15 minutes. WorkManager automatically adapts to Doze Mode and App Standby, grouping tasks into maintenance windows. Example of a simple 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 — an older API (Android 5+, API 21). It schedules tasks with specified conditions (network, charging, idle). Limitation: it doesn't support device reboot (needs BootReceiver) and has no observable state. JobScheduler is suitable for simple tasks in legacy projects; for new projects, use WorkManager.
Foreground Service — a service that the user sees through a persistent notification (ongoing notification). Used for: music playback, GPS tracking, downloading large files. Foreground Service has high priority — the system won't kill it when memory is low. Starting from Android 13, FOREGROUND_SERVICE_SPECIAL_USE permission is required for some types. An alternative is WorkManager with ForegroundServiceOption (long tasks).
AlarmManager — for tasks that must run at an exact time (alarm, reminder). AlarmManager can wake the device from Doze Mode (setAlarmClock). Not recommended for regular synchronization due to high power consumption. For periodic tasks, use WorkManager, and AlarmManager only when exact time is critical.
| Scenario | iOS | Android |
|---|---|---|
| Periodic content update | BGAppRefreshTask (BGTaskScheduler) | WorkManager (PeriodicWorkRequest) |
| Long background task | BGProcessingTask | WorkManager + ForegroundService |
| Audio playback | Background Audio Mode | Foreground Service |
| GPS tracking | Significant Location Change / Background Location | Foreground Service + FusedLocationProvider |
| VoIP / Calls | PushKit + CallKit | ConnectionService + Foreground Service |
| Exact time (alarm) | UNNotificationRequest (calendar) | AlarmManager |
| Push processing (background) | Notification Service Extension | FirebaseMessagingService (onMessageReceived) |
Doze Mode is a power-saving mode in Android that affects background task execution. Introduced in Android 6.0 (API 23). When the device is not charging, the screen is off, and the device is stationary, Doze Mode blocks network requests, defers JobScheduler and WakeLock. Periodically, Doze opens maintenance windows — short intervals when apps can execute deferred tasks. Since Android 7.0 (API 24), Doze activates when the screen is off, not only when completely stationary.
App Standby — a mode where unused apps are put into standby. If an app has no active notification and hasn't been opened for several days, it is placed into a Standby Bucket: active, working, frequent, rare. The less an app is used, the stricter the restrictions: network requests are deferred, synchronization is blocked, JobScheduler doesn't run.
WakeLock — a mechanism that keeps the device awake (prevents it from sleeping). Used to complete important operations. WakeLock must be released after the task is done, otherwise the battery will drain in a few hours. WakeLock doesn't work in Doze Mode — the system ignores it. Working with WakeLock on Android 8+ requires the WAKE_LOCK permission and proper lifecycle management.
At IT Sectr, we consider Doze Mode and App Standby at the design stage. WorkManager automatically handles these modes, but for Foreground Service, correct handling of Doze transitions must be planned. It is recommended to test background work on real devices with power-saving mode enabled and after prolonged idle periods.
When designing background tasks, follow these tips. 1. Always use WorkManager for new Android projects. It solves compatibility issues, Doze Mode, and device reboot problems. 2. On iOS, prefer BGTaskScheduler over Background Fetch for iOS 13+. 3. Use Foreground Service only when the task really requires a visible notification. 4. Don't abuse WakeLock — it kills the battery and can lead to app rejection. 5. Test background tasks in Doze Mode: adb shell dumpsys deviceidle force-idle. 6. Always verify task completion through logging and analytics. 7. Remember the limits: iOS gives ~30 seconds for Background Fetch and ~a few minutes for BGProcessingTask. Android WorkManager doesn't guarantee exact execution time.
Frequently Asked Questions
Background Service runs without a visible notification and can be killed by the system at any time. Foreground Service must show a persistent notification (ongoing notification) and has a higher priority. Foreground Service is used for music playback and GPS tracking.
Doze Mode is an Android power-saving mode that disables network access and defers JobScheduler/WakeLock when the device is not in use. WorkManager adapts to Doze Mode automatically.
On iOS, background tasks run through Background Fetch (periodic updates), BGTaskScheduler (deferred tasks) or Background Modes (audio, VoIP, BLE, location). BGTaskScheduler is the modern API for iOS 13+, replacing Background Fetch.
WorkManager is Google's recommended solution for all background tasks on Android. JobScheduler is an older API with limited capabilities. WorkManager supports task chains, observable LiveData/Flow, and backward compatibility down to API 14.
App Standby is an Android mode where unused apps are put into a standby state: network requests are deferred, synchronization is paused. If an app is not used for several days, Android places it into a Standby Bucket (active, working, frequent, rare).
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.