Background: podstawy, praca aplikacji w tle na iOS i Android

Autor: IT Sectr Opublikowano: 2026-03-03 Czas czytania: 10 min

Background — stan cyklu życia aplikacji, w którym nadal działa, ale nie jest wyświetlany na ekranie. Wyjaśniamy podstawy pracy w tle na iOS i Android: ograniczenia, limity czasu, zadania w tle przez beginBackgroundTask, WorkManager i Service, a także najlepsze praktyki prawidłowego przetwarzania Background.

Najważniejsze

  • Background — aplikacja nie jest widoczna dla użytkownika, ale może wykonywać kod przez ograniczony czas
  • iOS background task — beginBackgroundTask(expirationHandler:) daje do 30 sekund na zakończenie pracy
  • Android Service — Foreground Service z powiadomieniem dla długich operacji w tle
  • WorkManager — zalecane API dla zadań w tle na Android z gwarancją wykonania
  • Ograniczenia — obie platformy zaostrzają zasady pracy w tle w celu oszczędzania baterii

Background — podstawy stanu tła

Background — stan aplikacji, w którym nadal istnieje w systemie operacyjnym, wykonuje kod i zużywa zasoby, ale nie jest wyświetlana na ekranie urządzenia. Użytkownik znajduje się na ekranie głównym, w innej aplikacji lub ekran urządzenia jest zablokowany. W iOS Background następuje po Inactive — łańcuch przejścia: Active → Inactive → Background. W Android onStop sygnalizuje przejście Activity do Background.

Obie platformy nakładają ścisłe ograniczenia na pracę w tle. iOS zapewnia ograniczone okno (zwykle 30 sekund) na wykonanie kodu po przejściu do Background, po czym aplikacja przechodzi w stan Suspended. Android jest bardziej elastyczny: Foreground Service z widocznym powiadomieniem może działać bez ograniczeń, ale zwykły Background Service jest ograniczony do kilku minut. Kluczowym zadaniem programisty jest poprawne zapisanie stanu i zaplanowanie kontynuacji pracy przez systemowe API zadań w tle.

System może zakończyć aplikację w tle w dowolnym momencie przy braku pamięci. W przypadku zakończenia wszystkie niezapisane dane są tracone. Dlatego krytycznie ważne jest zapisywanie stanu w applicationDidEnterBackground (iOS) lub onStop (Android). Po zakończeniu przy następnym uruchomieniu aplikacja startuje z Not Running z zimnym startem i przywraca zapisany stan.

Background vs Suspended

Ważne jest rozróżnienie Background i Suspended. Background — aplikacja aktywnie wykonuje kod. Suspended — aplikacja znajduje się w pamięci, ale nie wykonuje kodu — jest zamrożona. W iOS aplikacja przechodzi z Background do Suspended po zakończeniu zadań w tle. W Android nie ma Suspended — proces albo istnieje (w tym w tle), albo jest zakończony (Not Running). Jednak Android może wstrzymać wykonywanie wątków przez LMK (Low Memory Killer).

CharakterystykaiOS BackgroundAndroid Background
Kod jest wykonywanyTak, do 30 sekundTak, zależy od API
UI widocznyNieNie
Limit czasu domyślnie~30 sek (beginBackgroundTask)Kilka minut (Service)
Nieograniczona pracaTylko specjalne kategorie (audio, VoIP, nawigacja)Foreground Service z powiadomieniem
Gwarancja wykonaniaNie — system może zakończyć w dowolnym momencieWorkManager gwarantuje wykonanie
Wymagane uprawnienieTak — capabilities w Info.plistTak — FOREGROUND_SERVICE permission
Następny stanSuspended → Not RunningNot Running (lub restart)

Background w iOS: Swift, beginBackgroundTask i BGTaskScheduler

W iOS Background jest obsługiwany przez metodę delegata applicationDidEnterBackground. W tej metodzie programista powinien zapisać stan użytkownika, zwolnić zasoby i zakończyć zadania w tle. Do wykonywania kodu po przejściu do Background używany jest beginBackgroundTask(expirationHandler:) — API, które żąda od systemu dodatkowego czasu (zwykle 30 sekund). Jeśli zadanie nie zakończy się w tym czasie, wywoływany jest expirationHandler, a aplikacja jest przymusowo przełączana w stan Suspended.

Od iOS 13 Apple wprowadziło BGTaskScheduler — nowoczesne API do planowania zadań w tle. W przeciwieństwie do beginBackgroundTask, który daje czas tylko na zakończenie po przejściu w tło, BGTaskScheduler pozwala zaplanować wykonanie zadań w przyszłości — na przykład aktualizację treści raz na godzinę lub wysyłkę analityki w nocy. BGTaskScheduler to zalecane podejście dla nowych projektów, ponieważ jest bardziej wydajne pod względem baterii.

swift
import UIKit
import BackgroundTasks

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid

    // Aplikacja przeszła w tło — rozpoczynamy zadanie w tle
    func applicationDidEnterBackground(_ application: UIApplication) {
        saveAppState()
        startBackgroundTask()
    }

    private func startBackgroundTask() {
        backgroundTaskID = UIApplication.shared.beginBackgroundTask { [weak self] in
            // Czas minął — wymuszamy zakończenie
            self?.endBackgroundTask()
        }

        // Symulujemy pracę w tle (zapisywanie danych na serwer)
        DispatchQueue.global().async { [weak self] in
            uploadAnalyticsData()
            self?.endBackgroundTask()
        }
    }

    private func endBackgroundTask() {
        guard backgroundTaskID != .invalid else { return }
        UIApplication.shared.endBackgroundTask(backgroundTaskID)
        backgroundTaskID = .invalid
    }

    // Rejestracja 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)
        }
    }
}

Kod pokazuje pełną obsługę Background na iOS. applicationDidEnterBackground uruchamia zadanie w tle przez beginBackgroundTask z limitem czasu i expirationHandler. Równolegle rejestrowany jest BGTaskScheduler do okresowej aktualizacji treści. beginBackgroundTask jest używany do natychmiastowego zakończenia pracy, BGTaskScheduler — do długoterminowego planowania. Oba API wymagają prawidłowego zarządzania identyfikatorami zadań.

Background w Android: Kotlin, Service, WorkManager

W Android Background jest zarządzany przez kilka API. Tradycyjny Service pozwala wykonywać kod w tle, ale od Android 8+ (API 26) Background Service jest ograniczony: system kończy go po kilku minutach od przejścia aplikacji w tło. Foreground Service ze stałym powiadomieniem może działać bez ograniczeń. WorkManager to zalecane rozwiązanie dla zadań w tle z gwarancją wykonania nawet po ponownym uruchomieniu urządzenia.

Android, w przeciwieństwie do iOS, obsługuje długożyciowe procesy w tle. Foreground Service jest używany do zadań, które użytkownik powinien widzieć — odtwarzanie muzyki, nawigacja, nagrywanie treningu. JobScheduler i WorkManager — do zadań, które mogą być odroczone: synchronizacja danych, wysyłka logów, aktualizacja cache. Kluczowa różnica: Android pozwala planować zadania z warunkami — Wi-Fi, ładowanie, nieaktywność urządzenia, co oszczędza baterię i transfer danych.

kotlin
import android.app.Service
import android.content.Intent
import android.os.IBinder
import androidx.work.*

// 1. Foreground Service dla długiej pracy w tle
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 {
            // Synchronizacja danych z serwerem
            syncDataToServer()
            stopForeground(STOP_FOREGROUND_REMOVE)
            stopSelf()
        }.start()
    }

    override fun onBind(intent: Intent?): IBinder? = null
}

// 2. WorkManager dla odroczonych zadań w tle
class DataSyncWorker(
    private val context: Context,
    private val params: WorkerParameters
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        return try {
            // Wysyłka analityki na serwer
            uploadAnalytics()
            Result.success()
        } catch (e: Exception) {
            if (runAttemptCount < 3) Result.retry() else Result.failure()
        }
    }
}

// Planowanie zadania WorkManager
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)
}

Kod pokazuje dwa podejścia do pracy w tle na Android. SyncService — Foreground Service z powiadomieniem do natychmiastowej i długiej pracy w tle. DataSyncWorker — WorkManager dla zadań odroczonych z warunkami (Wi-Fi, ładowanie). WorkManager gwarantuje wykonanie nawet po ponownym uruchomieniu urządzenia i obsługuje exponential backoff dla ponownych prób. Foreground Service wymaga stałego powiadomienia w pasku statusu.

Ograniczenia pracy w tle na iOS i Android

Obie platformy mobilne stale zaostrzają zasady pracy w tle. W iOS każde nowe pokolenie systemu operacyjnego skraca czas pracy w tle i dodaje nowe ograniczenia. W Android Google wprowadza coraz bardziej rygorystyczne tryby oszczędzania energii (Doze, App Standby). Programista musi być na bieżąco z aktualnymi ograniczeniami, aby aplikacja nie została przedwcześnie zakończona przez system.

W iOS począwszy od iOS 13, system wyłącza zadania w tle dla aplikacji, które nadużywają czasu w tle. Każda aplikacja otrzymuje określone limity na podstawie zachowania użytkownika. BGTaskScheduler planuje wykonanie na optymalny czas — na przykład gdy urządzenie jest podłączone do Wi-Fi i się ładuje. Aplikacje, które prawidłowo używają BGTaskScheduler, otrzymują więcej czasu w tle.

W Android począwszy od Android 9 (API 28) praca w tle jest ograniczona trybem Doze, który aktywuje się przy bezczynności urządzenia. Aplikacje w Doze nie mogą wykonywać zadań w tle, sieć jest wyłączona, JobScheduler i WorkManager odkładają zadania do wyjścia z Doze. Foreground Service to jedyny sposób na obejście Doze, ale nadużywanie prowadzi do zablokowania aplikacji przez użytkownika i usunięcia uprawnień.

OgraniczenieiOSAndroid
Limit czasu zadania w tle~30 sekund (beginBackgroundTask)Kilka minut (JobScheduler)
Nieograniczone tłoAudio, VoIP, nawigacja, BluetoothForeground Service + powiadomienie
Oszczędzanie energiiLow Power Mode — wyłącza zadania w tleDoze, App Standby, Battery Optimization
PlanowanieBGTaskScheduler (iOS 13+)WorkManager (Android Jetpack)
Po ponownym uruchomieniuTylko push powiadomienieWorkManager zachowuje zadania
Maks. czas wykonania~30 minut (audio)Bez ograniczeń (Foreground Service)

Najlepsze praktyki pracy w tle

Pierwsza zasada — minimalizuj zużycie zasobów w tle. Większość zadań w tle można odroczyć na czas, gdy urządzenie się ładuje i jest podłączone do Wi-Fi. Używaj BGTaskScheduler (iOS) i WorkManager (Android) do planowania zadań z warunkami. Nie uruchamiaj ciężkich obliczeń w tle — to rozładowuje baterię i prowadzi do throttlingu CPU.

Druga zasada — zawsze określaj expirationHandler dla beginBackgroundTask. Jeśli aplikacja nie zakończy zadania w wyznaczonym czasie, system przymusowo przełączy ją w Suspended lub zakończy. ExpirationHandler to ostatnia szansa na zapisanie danych i poprawne zakończenie pracy. W Android używaj setForegroundAsync w WorkManager do przekształcenia zwykłego zadania w foreground, jeśli wymagany jest dłuższy czas.

Trzecia zasada — sprawdzaj ograniczenia pracy w tle przed uruchomieniem. W iOS używaj UIApplication.shared.backgroundTimeRemaining do sprawdzenia pozostałego czasu. W Android sprawdź ActivityManager.isBackgroundRestricted() — jeśli true, aplikacja nie będzie mogła uruchamiać zadań w tle i należy zaproponować użytkownikowi usunięcie ograniczeń w ustawieniach. Jest to szczególnie ważne dla aplikacji z krytycznymi funkcjami w tle — budziki, kalendarze, synchronizacja.

Czwarta zasada — testuj zadania w tle na rzeczywistym urządzeniu. Symulator i emulator nie odtwarzają rzeczywistych ograniczeń pracy w tle. W iOS używaj Debug → Simulate Background Fetch w Xcode. W Android — adb shell am broadcast -a android.intent.action.ACTION_BOOT_COMPLETED do testowania WorkManager po ponownym uruchomieniu. Rzeczywiste testy na urządzeniu z niskim poziomem baterii ujawniają większość problemów pracy w tle.

swift
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("Pozostało czasu w tle: \(remaining) sek")

        let task = UIApplication.shared.beginBackgroundTask { [weak self] in
            print("Czas zakończył się dla zadania: \(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)
    }
}

Kod pokazuje menedżera zadań w tle, który śledzi pozostały czas i zarządza identyfikatorami. backgroundTimeRemaining zwraca liczbę sekund do przymusowego zakończenia — jeśli wartość jest nieskończona, aplikacja działa bez ograniczenia (audio, nawigacja). Menedżer pozwala uruchamiać wiele zadań w tle z różnymi nazwami i poprawnie zakończyć każde. Takie podejście zapobiega wyciekowi zadań w tle i gwarantuje, że system nie zakończy aplikacji z powodu niezamkniętych zadań.

Często zadawane pytania

Czy aplikacja iOS może działać w tle wiecznie?

Tak, dla ograniczonej liczby kategorii: audio (AVAudioSession kategoria .playback), VoIP (PushKit), nawigacja (CLLocationManager z allowsBackgroundLocationUpdates), Bluetooth (central background mode), aktualizacja w tle (BGTaskScheduler). Dla wszystkich pozostałych — maksymalnie 30 sekund. W iOS 16+ Apple zaostrzyła wymagania nawet dla dozwolonych kategorii.

Czym beginBackgroundTask różni się od BGTaskScheduler?

beginBackgroundTask — synchroniczne API do przedłużenia życia aplikacji na ~30 sekund po przejściu w tło. Wywoływane w applicationDidEnterBackground. BGTaskScheduler — asynchroniczne API do planowania zadań w przyszłości przez wyzwalacze systemowe (czas, lokalizacja, aktualizacja treści). BGTaskScheduler to nowoczesne podejście zalecane przez Apple dla iOS 13+.

Dlaczego Android zabija mój Background Service?

Od Android 8 (API 26), Background Service jest kończony po kilku minutach od przejścia aplikacji w tło. Rozwiązanie: użyj Foreground Service z powiadomieniem dla długich operacji lub WorkManager dla zadań odroczonych. Sprawdź Battery Optimization dla swojej aplikacji w ustawieniach — jeśli jest zoptymalizowana, system może odroczyć lub anulować zadania w tle.

Jak przetestować Background na symulatorze iOS?

Naciśnij Cmd+Shift+H aby przejść do ekranu głównego. W Xcode użyj Debug → Simulate Background Fetch. Aby sprawdzić beginBackgroundTask otwórz konsolę (Shift+Cmd+C) i wywołaj e UIApplication.shared.backgroundTimeRemaining. W Xcode 15+ dostępny jest scenariusz Background Execution w zakładce Diagnostics symulatora.

Czym jest process death na Android?

Process Death — zakończenie procesu Android przez system przy braku zasobów lub przy bezczynności w tle. W przeciwieństwie do iOS, Android nie ma Suspended — proces albo żyje (może być w tle), albo jest martwy (Not Running). Process Death to normalne zachowanie systemu operacyjnego, a aplikacja powinna poprawnie przywracać stan po nim przez SavedStateHandle, onSaveInstanceState lub DataStore.

Podsumowanie

  • Background — aplikacja nie jest widoczna na ekranie, ale wykonuje kod, w przeciwieństwie do Suspended (zamrożona)
  • iOS — beginBackgroundTask (do 30 sek) i BGTaskScheduler do planowania przyszłych zadań
  • Android — Foreground Service dla długich operacji, WorkManager dla zadań odroczonych z gwarancją
  • Ograniczenia — obie platformy zaostrzają zasady pracy w tle: Doze, Low Power Mode, App Standby
  • Zapisywanie — applicationDidEnterBackground i onStop — ostatnia szansa na zapisanie danych przed Suspended/Not Running
  • Planowanie — BGTaskScheduler i WorkManager działają z warunkami (Wi-Fi, ładowanie, czas)
  • Foreground Service — jedyny sposób nieograniczonej pracy w tle na obu platformach

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również