Background: fondamenti, funzionamento dell'app in background su iOS e Android

Autore: IT Sectr Pubblicato: 2026-03-03 Tempo di lettura: 10 min

Background è uno stato del ciclo di vita dell'app in cui continua a essere eseguita ma non viene visualizzata sullo schermo. Spieghiamo le basi del lavoro in background su iOS e Android: limitazioni, timeout, attività in background tramite beginBackgroundTask, WorkManager e Service, e le migliori pratiche per la corretta gestione di Background.

Punti Chiave

  • Background — l'app non è visibile all'utente ma può eseguire codice per un tempo limitato
  • Attività in background iOS — beginBackgroundTask(expirationHandler:) dà fino a 30 secondi per terminare il lavoro
  • Android Service — Foreground Service con notifica per operazioni lunghe in background
  • WorkManager — API consigliata per attività in background su Android con garanzia di esecuzione
  • Limitazioni — entrambe le piattaforme inaspriscono le regole sul lavoro in background per risparmiare batteria

Background — fondamenti dello stato di background

Background è uno stato dell'app in cui continua a esistere nel sistema operativo, esegue codice e consuma risorse, ma non viene visualizzata sullo schermo del dispositivo. L'utente si trova sulla schermata Home, in un'altra app o lo schermo del dispositivo è bloccato. Su iOS, Background segue Inactive — la catena di transizione è: Active → Inactive → Background. Su Android, onStop segnala la transizione di un Activity in Background.

Entrambe le piattaforme impongono restrizioni severe al lavoro in background. iOS fornisce una finestra limitata (di solito 30 secondi) per eseguire codice dopo essere entrato in Background, dopodiché l'app passa a Suspended. Android è più flessibile: un Foreground Service con una notifica visibile può funzionare indefinitamente, ma un normale Background Service è limitato a pochi minuti. Il compito principale dello sviluppatore è salvare correttamente lo stato e pianificare la continuazione del lavoro tramite le API di sistema per attività in background.

Il sistema può terminare un'app in background in qualsiasi momento quando la memoria è scarsa. Alla terminazione, tutti i dati non salvati vengono persi. È quindi fondamentale salvare lo stato in applicationDidEnterBackground (iOS) o onStop (Android). Dopo la terminazione, il successivo avvio parte da Not Running con un avvio a freddo e ripristina lo stato salvato.

Background vs Suspended

È importante distinguere Background da Suspended. Background — l'app sta eseguendo attivamente codice. Suspended — l'app è in memoria ma non esegue codice — è congelata. Su iOS, l'app passa da Background a Suspended dopo aver completato le attività in background. Android non ha Suspended — il processo esiste (incluso Background) o è terminato (Not Running). Tuttavia, Android può sospendere l'esecuzione dei thread tramite LMK (Low Memory Killer).

CaratteristicaiOS BackgroundAndroid Background
Codice eseguitoSì, fino a 30 secondiSì, dipende dall'API
UI visibileNoNo
Timeout predefinito~30 sec (beginBackgroundTask)Diversi minuti (Service)
Lavoro illimitatoSolo categorie speciali (audio, VoIP, navigazione)Foreground Service con notifica
Garanzia di esecuzioneNo — il sistema può terminare in qualsiasi momentoWorkManager garantisce l'esecuzione
Permesso richiestoSì — capabilities in Info.plistSì — permesso FOREGROUND_SERVICE
Stato successivoSuspended → Not RunningNot Running (o riavvio)

Background su iOS: Swift, beginBackgroundTask e BGTaskScheduler

Su iOS, Background viene gestito tramite il metodo delegato applicationDidEnterBackground. In questo metodo, lo sviluppatore deve salvare lo stato dell'utente, liberare risorse e completare le attività in background. Per eseguire codice dopo essere entrati in Background, si utilizza beginBackgroundTask(expirationHandler:) — un'API che richiede tempo aggiuntivo al sistema (di solito 30 secondi). Se l'attività non viene completata entro questo tempo, viene chiamato expirationHandler e l'app viene forzata a passare a Suspended.

Con iOS 13, Apple ha introdotto BGTaskScheduler — un'API moderna per pianificare attività in background. A differenza di beginBackgroundTask, che dà solo tempo per terminare dopo essere andati in background, BGTaskScheduler consente di pianificare l'esecuzione di attività nel futuro — ad esempio, aggiornare il contenuto una volta all'ora o caricare analisi di notte. BGTaskScheduler è l'approccio consigliato per nuovi progetti, poiché è più efficiente in termini di batteria.

swift
import UIKit
import BackgroundTasks

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid

    // L'app è andata in background — avvio attività in background
    func applicationDidEnterBackground(_ application: UIApplication) {
        saveAppState()
        startBackgroundTask()
    }

    private func startBackgroundTask() {
        backgroundTaskID = UIApplication.shared.beginBackgroundTask { [weak self] in
            // Tempo scaduto — terminazione forzata
            self?.endBackgroundTask()
        }

        // Simulazione lavoro in background (salvataggio dati sul server)
        DispatchQueue.global().async { [weak self] in
            uploadAnalyticsData()
            self?.endBackgroundTask()
        }
    }

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

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

Il codice mostra la gestione completa di Background su iOS. applicationDidEnterBackground avvia un'attività in background tramite beginBackgroundTask con un timeout e expirationHandler. Parallelamente, BGTaskScheduler viene registrato per aggiornamenti periodici dei contenuti. beginBackgroundTask viene utilizzato per attività di spegnimento immediato, BGTaskScheduler per la pianificazione a lungo termine. Entrambe le API richiedono una corretta gestione degli identificatori delle attività.

Background su Android: Kotlin, Service, WorkManager

Su Android, Background viene gestito tramite diverse API. Il Service tradizionale consente di eseguire codice in background, ma da Android 8+ (API 26), il Background Service è limitato: il sistema lo termina pochi minuti dopo che l'app va in background. Un Foreground Service con una notifica persistente può funzionare indefinitamente. WorkManager è la soluzione consigliata per attività in background con garanzia di esecuzione anche dopo il riavvio del dispositivo.

Android, a differenza di iOS, supporta processi in background di lunga durata. Foreground Service viene utilizzato per attività che l'utente deve vedere — riproduzione musicale, navigazione, tracciamento degli allenamenti. JobScheduler e WorkManager vengono utilizzati per attività che possono essere rinviate: sincronizzazione dati, caricamento log, aggiornamento cache. La differenza chiave: Android consente di pianificare attività con condizioni — Wi-Fi, ricarica, inattività del dispositivo — risparmiando batteria e traffico.

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

// 1. Foreground Service per lavoro in background prolungato
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 {
            // Sincronizzazione dati con il server
            syncDataToServer()
            stopForeground(STOP_FOREGROUND_REMOVE)
            stopSelf()
        }.start()
    }

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

// 2. WorkManager per attività in background rinviate
class DataSyncWorker(
    private val context: Context,
    private val params: WorkerParameters
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        return try {
            // Caricamento analisi sul server
            uploadAnalytics()
            Result.success()
        } catch (e: Exception) {
            if (runAttemptCount < 3) Result.retry() else Result.failure()
        }
    }
}

// Pianificazione attività 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)
}

Il codice mostra due approcci al lavoro in background su Android. SyncService — un Foreground Service con notifica per lavoro immediato e prolungato in background. DataSyncWorker — WorkManager per attività rinviate con condizioni (Wi-Fi, ricarica). WorkManager garantisce l'esecuzione anche dopo il riavvio del dispositivo e supporta il backoff esponenziale per i tentativi. Foreground Service richiede una notifica persistente nella barra di stato.

Limitazioni del lavoro in background su iOS e Android

Entrambe le piattaforme mobili stanno costantemente inasprendo le regole sul lavoro in background. Su iOS, ogni nuova generazione di OS riduce il tempo di esecuzione in background e aggiunge nuove restrizioni. Su Android, Google introduce modalità di risparmio energetico sempre più severe (Doze, App Standby). Gli sviluppatori devono rimanere aggiornati sulle limitazioni correnti per evitare che l'app venga terminata prematuramente dal sistema.

Su iOS, a partire da iOS 13, il sistema disabilita le attività in background per le app che abusano del tempo in background. Ogni app riceve determinati limiti basati sul comportamento dell'utente. BGTaskScheduler pianifica l'esecuzione in momenti ottimali — ad esempio, quando il dispositivo è connesso al Wi-Fi e in carica. Le app che utilizzano correttamente BGTaskScheduler ottengono più tempo in background.

Su Android, a partire da Android 9 (API 28), il lavoro in background è limitato dalla modalità Doze, che si attiva quando il dispositivo è inattivo. Le app in Doze non possono eseguire attività in background, la rete viene disconnessa, JobScheduler e WorkManager rimandano le attività fino all'uscita da Doze. Foreground Service è l'unico modo per bypassare Doze, ma l'abuso porta al blocco dell'app da parte dell'utente e alla revoca dei permessi.

LimitazioneiOSAndroid
Timeout attività in background~30 secondi (beginBackgroundTask)Diversi minuti (JobScheduler)
Background illimitatoAudio, VoIP, navigazione, BluetoothForeground Service + notifica
Risparmio energeticoLow Power Mode — disabilita attività in backgroundDoze, App Standby, Ottimizzazione batteria
PianificazioneBGTaskScheduler (iOS 13+)WorkManager (Android Jetpack)
Dopo riavvioSolo notifica pushWorkManager conserva le attività
Tempo massimo di esecuzione~30 minuti (audio)Illimitato (Foreground Service)

Migliori pratiche per il lavoro in background

Prima regola — minimizzare il consumo di risorse in background. La maggior parte delle attività in background può essere rimandata a quando il dispositivo è in carica e connesso al Wi-Fi. Utilizzare BGTaskScheduler (iOS) e WorkManager (Android) per pianificare attività con condizioni. Non eseguire calcoli pesanti in background — questo scarica la batteria e porta alla limitazione della CPU.

Seconda regola — specificare sempre un expirationHandler per beginBackgroundTask. Se l'app non completa l'attività nel tempo assegnato, il sistema la forzerà a passare a Suspended o la terminerà. L'expirationHandler è l'ultima possibilità per salvare dati e terminare correttamente il lavoro. Su Android, utilizzare setForegroundAsync in WorkManager per convertire un'attività normale in primo piano se è necessario più tempo.

Terza regola — verificare le restrizioni al lavoro in background prima di avviare. Su iOS, utilizzare UIApplication.shared.backgroundTimeRemaining per controllare il tempo rimanente. Su Android, verificare ActivityManager.isBackgroundRestricted() — se true, l'app non può eseguire attività in background e si dovrebbe suggerire all'utente di rimuovere le restrizioni nelle impostazioni. Questo è particolarmente importante per le app con funzioni critiche in background — sveglie, calendari, sincronizzazione.

Quarta regola — testare le attività in background su un dispositivo reale. I simulatori e gli emulatori non riproducono le reali restrizioni del lavoro in background. Su iOS, utilizzare Debug → Simulate Background Fetch in Xcode. Su Android, utilizzare adb shell am broadcast -a android.intent.action.ACTION_BOOT_COMPLETED per testare WorkManager dopo il riavvio. Test reali su un dispositivo con batteria scarica rivelano la maggior parte dei problemi del lavoro in background.

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("Tempo rimanente in background: \(remaining) sec")

        let task = UIApplication.shared.beginBackgroundTask { [weak self] in
            print("Tempo scaduto per l'attività: \(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)
    }
}

Il codice mostra un gestore di attività in background che traccia il tempo rimanente e gestisce gli identificatori. backgroundTimeRemaining restituisce il numero di secondi prima della terminazione forzata — se il valore è infinito, l'app è in esecuzione senza restrizioni (audio, navigazione). Il gestore consente di avviare più attività in background con nomi diversi e completare ciascuna correttamente. Questo approccio previene perdite di attività in background e garantisce che il sistema non termini l'app a causa di attività non chiuse.

Domande Frequenti

Un'app iOS può funzionare in background per sempre?

Sì, per un numero limitato di categorie: audio (categoria AVAudioSession .playback), VoIP (PushKit), navigazione (CLLocationManager con allowsBackgroundLocationUpdates), Bluetooth (modalità background centrale), aggiornamento in background (BGTaskScheduler). Per tutte le altre — massimo 30 secondi. In iOS 16+, Apple ha inasprito i requisiti anche per le categorie consentite.

In cosa differisce beginBackgroundTask da BGTaskScheduler?

beginBackgroundTask è un'API sincrona per estendere la vita dell'app di circa 30 secondi dopo essere andata in background. Viene chiamato in applicationDidEnterBackground. BGTaskScheduler è un'API asincrona per pianificare attività nel futuro tramite trigger di sistema (tempo, posizione, aggiornamento contenuto). BGTaskScheduler è l'approccio moderno, raccomandato da Apple per iOS 13+.

Perché Android uccide il mio Background Service?

A partire da Android 8 (API 26), un Background Service viene terminato pochi minuti dopo che l'app va in background. Soluzione: utilizzare un Foreground Service con notifica per operazioni lunghe o WorkManager per attività rinviate. Controllare l'Ottimizzazione della batteria per la propria app nelle impostazioni — se ottimizzata, il sistema potrebbe rimandare o annullare le attività in background.

Come testare Background sul simulatore iOS?

Premere Cmd+Shift+H per andare alla schermata Home. In Xcode, utilizzare Debug → Simulate Background Fetch. Per verificare beginBackgroundTask, aprire la console (Shift+Cmd+C) e chiamare e UIApplication.shared.backgroundTimeRemaining. In Xcode 15+, uno scenario Background Execution è disponibile nella scheda Diagnostics del simulatore.

Cos'è process death su Android?

Process Death è la terminazione di un processo Android da parte del sistema quando le risorse sono scarse o quando è inattivo in background. A differenza di iOS, Android non ha Suspended — il processo è vivo (può essere in background) o morto (Not Running). Process Death è un comportamento normale del OS e l'app deve ripristinare correttamente lo stato dopo tramite SavedStateHandle, onSaveInstanceState o DataStore.

Riepilogo

  • Background — l'app non è visibile sullo schermo ma esegue codice, a differenza di Suspended (congelata)
  • iOS — beginBackgroundTask (fino a 30 sec) e BGTaskScheduler per pianificare attività future
  • Android — Foreground Service per operazioni lunghe, WorkManager per attività rinviate con garanzia
  • Limitazioni — entrambe le piattaforme inaspriscono le regole: Doze, Low Power Mode, App Standby
  • Salvataggio — applicationDidEnterBackground e onStop sono l'ultima possibilità prima di Suspended/Not Running
  • Pianificazione — BGTaskScheduler e WorkManager funzionano con condizioni (Wi-Fi, ricarica, tempo)
  • Foreground Service — l'unico modo per lavoro in background illimitato su entrambe le piattaforme

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche