Background — tillstånd i appens livscykel där den fortsätter att köras men inte visas på skärmen. Vi förklarar grunderna för bakgrundsarbete på iOS och Android: begränsningar, timeout, bakgrundsuppgifter via beginBackgroundTask, WorkManager och Service, samt bästa praxis för korrekt hantering av Background.
Huvudpunkter
Background — appens tillstånd där den fortsätter att finnas i operativsystemet, köra kod och förbruka resurser, men visas inte på enhetens skärm. Användaren befinner sig på startskärmen, i en annan app eller enhetens skärm är låst. På iOS följer Background efter Inactive — övergångskedjan: Active → Inactive → Background. På Android signalerar onStop att Activity övergår till Background.
Båda plattformarna inför strikta begränsningar för bakgrundsarbete. iOS ger ett begränsat fönster (vanligtvis 30 sekunder) för att köra kod efter övergång till Background, varefter appen försätts i Suspended. Android är mer flexibelt: Foreground Service med synlig notis kan fungera obegränsat, men vanlig Background Service är begränsad till några minuter. Utvecklarens nyckeluppgift — att spara tillståndet korrekt och planera fortsatt arbete via systemets API:er för bakgrundsuppgifter.
Systemet kan avsluta bakgrundsappen när som helst vid minnesbrist. Vid avslutning går alla osparade data förlorade. Därför är det kritiskt att spara tillstånd i applicationDidEnterBackground (iOS) eller onStop (Android). Efter avslutning startar appen vid nästa lansering från Not Running med en kallstart och återställer det sparade tillståndet.
Det är viktigt att skilja mellan Background och Suspended. Background — appen kör aktivt kod. Suspended — appen finns i minnet men kör inte kod — den är frusen. På iOS går appen från Background till Suspended efter att bakgrundsuppgifter slutförts. På Android finns inget Suspended — processen finns antingen (inklusive bakgrund) eller är avslutad (Not Running). Android kan dock pausa exekveringen av trådar via LMK (Low Memory Killer).
| Egenskap | iOS Background | Android Background |
|---|---|---|
| Kod körs | Ja, upp till 30 sekunder | Ja, beror på API |
| UI synligt | Nej | Nej |
| Standard timeout | ~30 sek (beginBackgroundTask) | Några minuter (Service) |
| Obegränsat arbete | Endast särskilda kategorier (ljud, VoIP, navigation) | Foreground Service med notis |
| Körningsgaranti | Nej — systemet kan avsluta när som helst | WorkManager garanterar körning |
| Kräver tillstånd | Ja — capabilities i Info.plist | Ja — FOREGROUND_SERVICE tillstånd |
| Nästa tillstånd | Suspended → Not Running | Not Running (eller omstart) |
I iOS hanteras Background via delegatmetoden applicationDidEnterBackground. I denna metod bör utvecklaren spara användarens tillstånd, frigöra resurser och slutföra bakgrundsuppgifter. För att köra kod efter övergång till Background används beginBackgroundTask(expirationHandler:) — ett API som begär extra tid (vanligtvis 30 sekunder) från systemet. Om uppgiften inte slutförs inom denna tid anropas expirationHandler och appen försätts tvångsmässigt i Suspended.
Från och med iOS 13 introducerade Apple BGTaskScheduler — ett modernt API för att schemalägga bakgrundsuppgifter. Till skillnad från beginBackgroundTask, som bara ger tid för slutförande efter övergång till bakgrunden, gör BGTaskScheduler det möjligt att schemalägga framtida körningar av uppgifter — till exempel uppdatering av innehåll en gång i timmen eller uppladdning av analysdata på natten. BGTaskScheduler är det rekommenderade tillvägagångssättet för nya projekt eftersom det är mer batterieffektivt.
import UIKit
import BackgroundTasks
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid
// Appen gick till bakgrunden — startar bakgrundsuppgift
func applicationDidEnterBackground(_ application: UIApplication) {
saveAppState()
startBackgroundTask()
}
private func startBackgroundTask() {
backgroundTaskID = UIApplication.shared.beginBackgroundTask { [weak self] in
// Tiden har gått ut — tvångsavslutar
self?.endBackgroundTask()
}
// Simulerar bakgrundsarbete (spara data på server)
DispatchQueue.global().async { [weak self] in
uploadAnalyticsData()
self?.endBackgroundTask()
}
}
private func endBackgroundTask() {
guard backgroundTaskID != .invalid else { return }
UIApplication.shared.endBackgroundTask(backgroundTaskID)
backgroundTaskID = .invalid
}
// Registrering av BGTaskScheduler
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
BGTaskScheduler.shared.register(
forTaskWithIdentifier: "com.example.refresh",
using: nil
) { task in
handleAppRefresh(task: task as! BGAppRefreshTask)
}
return true
}
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "com.example.refresh")
request.earliestBeginDate = Date(timeIntervalSinceNow: 3600)
try? BGTaskScheduler.shared.submit(request)
}
func handleAppRefresh(task: BGAppRefreshTask) {
scheduleAppRefresh()
task.expirationHandler = { task.setTaskCompleted(success: false) }
fetchLatestData { result in
task.setTaskCompleted(success: result)
}
}
}Koden visar fullständig hantering av Background i iOS. applicationDidEnterBackground startar en bakgrundsuppgift via beginBackgroundTask med timeout och expirationHandler. Parallellt registreras BGTaskScheduler för periodisk innehållsuppdatering. beginBackgroundTask används för omedelbart slutförande av arbete, BGTaskScheduler — för långsiktig schemaläggning. Båda API:erna kräver korrekt hantering av uppgiftsidentifierare.
I Android hanteras Background via flera API:er. Traditionell Service gör det möjligt att köra kod i bakgrunden, men från Android 8+ (API 26) är Background Service begränsad: systemet avslutar den några minuter efter att appen går till bakgrunden. Foreground Service med permanent notis kan fungera obegränsat. WorkManager — den rekommenderade lösningen för bakgrundsuppgifter med körningsgaranti även efter omstart av enheten.
Android, till skillnad från iOS, stöder långlivade bakgrundsprocesser. Foreground Service används för uppgifter som användaren måste se — musikuppspelning, navigering, träningsinspelning. JobScheduler och WorkManager — för uppgifter som kan skjutas upp: datasynkronisering, logguppladdning, cacheuppdatering. Den viktigaste skillnaden: Android gör det möjligt att schemalägga uppgifter med villkor — Wi-Fi, laddning, enhetens inaktivitet, vilket sparar batteri och datatrafik.
import android.app.Service
import android.content.Intent
import android.os.IBinder
import androidx.work.*
// 1. Foreground Service för långt bakgrundsarbete
class SyncService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val notification = createNotification()
startForeground(NOTIFICATION_ID, notification)
performBackgroundWork()
return START_STICKY
}
private fun performBackgroundWork() {
Thread {
// Synkronisera data med server
syncDataToServer()
stopForeground(STOP_FOREGROUND_REMOVE)
stopSelf()
}.start()
}
override fun onBind(intent: Intent?): IBinder? = null
}
// 2. WorkManager för uppskjutna bakgrundsuppgifter
class DataSyncWorker(
private val context: Context,
private val params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
return try {
// Ladda upp analysdata till server
uploadAnalytics()
Result.success()
} catch (e: Exception) {
if (runAttemptCount < 3) Result.retry() else Result.failure()
}
}
}
// Schemaläggning av WorkManager-uppgift
fun scheduleBackgroundSync(context: Context) {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.build()
val request = OneTimeWorkRequestBuilder<DataSyncWorker>()
.setConstraints(constraints)
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 30, TimeUnit.SECONDS)
.build()
WorkManager.getInstance(context).enqueue(request)
}Koden visar två tillvägagångssätt för bakgrundsarbete i Android. SyncService — Foreground Service med notis för omedelbart och långt bakgrundsarbete. DataSyncWorker — WorkManager för uppskjutna uppgifter med villkor (Wi-Fi, laddning). WorkManager garanterar körning även efter omstart av enheten och stöder exponential backoff för återförsök. Foreground Service kräver en permanent notis i statusfältet.
Båda mobila plattformarna skärper ständigt reglerna för bakgrundsarbete. På iOS förkortar varje ny generation av operativsystem tiden för bakgrundsarbete och lägger till nya begränsningar. På Android inför Google allt strängare energisparlägen (Doze, App Standby). Utvecklaren måste vara medveten om aktuella begränsningar så att appen inte avslutas i förtid av systemet.
På iOS från och med iOS 13 stänger systemet av bakgrundsuppgifter för appar som missbrukar bakgrundstiden. Varje app får specifika gränser baserat på användarens beteende. BGTaskScheduler schemalägger körning vid optimal tid — till exempel när enheten är ansluten till Wi-Fi och laddas. Appar som använder BGTaskScheduler korrekt får mer bakgrundstid.
På Android från och med Android 9 (API 28) begränsas bakgrundsarbete av Doze-läget, som aktiveras vid enhetens inaktivitet. Appar i Doze kan inte köra bakgrundsuppgifter, nätverket stängs av, JobScheduler och WorkManager skjuter upp uppgifter tills Doze lämnas. Foreground Service är det enda sättet att kringgå Doze, men missbruk leder till blockering av appen av användaren och borttagning av tillstånd.
| Begränsning | iOS | Android |
|---|---|---|
| Timeout bakgrundsuppgift | ~30 sekunder (beginBackgroundTask) | Några minuter (JobScheduler) |
| Obegränsad bakgrund | Ljud, VoIP, navigation, Bluetooth | Foreground Service + notis |
| Energibesparing | Low Power Mode — stänger av bakgrundsuppgifter | Doze, App Standby, Battery Optimization |
| Schemaläggning | BGTaskScheduler (iOS 13+) | WorkManager (Android Jetpack) |
| Efter omstart | Endast push-notis | WorkManager behåller uppgifter |
| Max. körtid | ~30 minuter (ljud) | Obegränsad (Foreground Service) |
Första regeln — minimera resursförbrukningen i bakgrunden. De flesta bakgrundsuppgifter kan skjutas upp till när enheten laddas och är ansluten till Wi-Fi. Använd BGTaskScheduler (iOS) och WorkManager (Android) för att schemalägga uppgifter med villkor. Kör inte tunga beräkningar i bakgrunden — detta tömmer batteriet och leder till CPU-begränsning.
Andra regeln — ange alltid expirationHandler för beginBackgroundTask. Om appen inte slutför uppgiften inom den tilldelade tiden kommer systemet tvångsmässigt att försätta den i Suspended eller avsluta den. ExpirationHandler är den sista chansen att spara data och avsluta arbetet korrekt. På Android använd setForegroundAsync i WorkManager för att omvandla en vanlig uppgift till foreground om mer tid behövs.
Tredje regeln — kontrollera begränsningarna för bakgrundsarbete innan start. På iOS använd UIApplication.shared.backgroundTimeRemaining för att kontrollera återstående tid. På Android kontrollera ActivityManager.isBackgroundRestricted() — om det är true kan appen inte starta bakgrundsuppgifter och du bör föreslå att användaren tar bort begränsningarna i inställningarna. Detta är särskilt viktigt för appar med kritiska bakgrundsfunktioner — väckarklockor, kalendrar, synkronisering.
Fjärde regeln — testa bakgrundsuppgifter på en verklig enhet. Simulatorn och emulatorn återger inte de verkliga begränsningarna för bakgrundsarbete. På iOS använd Debug → Simulate Background Fetch i Xcode. På Android — adb shell am broadcast -a android.intent.action.ACTION_BOOT_COMPLETED för att testa WorkManager efter omstart. Verkliga tester på en enhet med låg batterinivå avslöjar de flesta problem med bakgrundsarbete.
import UIKit
final class BackgroundTaskManager {
static let shared = BackgroundTaskManager()
private var tasks: [String: UIBackgroundTaskIdentifier] = [:]
func startTask(name: String, expiration: @escaping () -> Void) {
let remaining = UIApplication.shared.backgroundTimeRemaining
print("Återstående tid i bakgrunden: \(remaining) sek")
let task = UIApplication.shared.beginBackgroundTask { [weak self] in
print("Tiden har gått ut för uppgiften: \(name)")
expiration()
self?.endTask(name: name)
}
tasks[name] = task
}
func endTask(name: String) {
guard let task = tasks.removeValue(forKey: name),
task != .invalid
else { return }
UIApplication.shared.endBackgroundTask(task)
}
}Koden visar en bakgrundsuppgiftshanterare som spårar återstående tid och hanterar identifierare. backgroundTimeRemaining returnerar antalet sekunder till tvångsavslutning — om värdet är oändligt fungerar appen utan begränsning (ljud, navigation). Hanteraren gör det möjligt att köra flera bakgrundsuppgifter med olika namn och avsluta varje korrekt. Detta tillvägagångssätt förhindrar läckage av bakgrundsuppgifter och garanterar att systemet inte avslutar appen på grund ofullbordade uppgifter.
Vanliga frågor
Ja, för ett begränsat antal kategorier: ljud (AVAudioSession kategori .playback), VoIP (PushKit), navigation (CLLocationManager med allowsBackgroundLocationUpdates), Bluetooth (centralt bakgrundsläge), bakgrundsuppdatering (BGTaskScheduler). För alla andra — maximalt 30 sekunder. I iOS 16+ har Apple skärpt kraven även för tillåtna kategorier.
beginBackgroundTask — synkront API för att förlänga appens livslängd med ~30 sekunder efter övergång till bakgrunden. Anropas i applicationDidEnterBackground. BGTaskScheduler — asynkront API för att schemalägga framtida uppgifter via systemutlösare (tid, plats, innehållsuppdatering). BGTaskScheduler är det moderna tillvägagångssättet som rekommenderas av Apple för iOS 13+.
Från och med Android 8 (API 26) avslutas Background Service några minuter efter att appen går till bakgrunden. Lösning: använd Foreground Service med notis för långa operationer eller WorkManager för uppskjutna uppgifter. Kontrollera Battery Optimization för din app i inställningarna — om den är optimerad kan systemet skjuta upp eller avbryta bakgrundsuppgifter.
Tryck på Cmd+Shift+H för att gå till startskärmen. I Xcode använd Debug → Simulate Background Fetch. För att kontrollera beginBackgroundTask öppna konsolen (Shift+Cmd+C) och anropa e UIApplication.shared.backgroundTimeRemaining. I Xcode 15+ finns Background Execution-scenariot tillgängligt på fliken Diagnostics i simulatorn.
Process Death — avslutning av en Android-process av systemet vid resursbrist eller inaktivitet i bakgrunden. Till skillnad från iOS har Android inget Suspended — processen är antingen levande (kan vara i bakgrunden) eller död (Not Running). Process Death är normalt beteende hos operativsystemet och appen bör återställa tillståndet korrekt efter det via SavedStateHandle, onSaveInstanceState eller DataStore.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också