ANR (Application Not Responding) è una notifica di sistema in Android che appare quando un’app non risponde all’input entro 5 secondi. A differenza di glitch (errori logici senza blocco dell’interfaccia) e lag (rallentamento senza arresto completo), l’ANR è un errore critico registrato dal sistema operativo: Android mostra un dialogo “L’app non risponde” con l’opzione di chiudere o attendere. Secondo Android Vitals Documentation, le app con un tasso di ANR superiore allo 0,5% ricevono una valutazione più bassa su Google Play e possono essere nascoste dai consigli. La diagnosi include l’analisi di /data/anr/traces.txt, l’uso di StrictMode e la profilazione del thread principale.
Punti chiave
ANR (Application Not Responding) è un meccanismo di protezione dell’utente in Android che si attiva quando l’app smette di rispondere all’input. Il sistema tiene traccia del tempo di elaborazione degli eventi: se BroadcastReceiver non completa onReceive entro 10 secondi, Service non torna da onCreate entro 20 secondi, o ContentProvider non risponde entro 15 secondi — Android genera un ANR.
Quando si verifica un ANR, Android mostra un dialogo di sistema sopra tutte le finestre: “L’app non risponde. Chiudere o attendere?” L’utente può chiudere l’app o attendere il suo ripristino. Se gli ANR si verificano frequentemente, l’utente disinstalla l’app. Google Play considera il tasso di ANR — la percentuale di sessioni con ANR — nei suoi algoritmi di classificazione.
iOS non ha un equivalente di ANR con un dialogo di sistema. Invece, Apple usa Watchdog, che termina il processo con codice di uscita 0x8badf00d. L’utente non vede un dialogo — l’app si chiude semplicemente alla schermata home. Questo rende l’ANR su Android più visibile per l’utente, ma dà al sistema più informazioni diagnostiche.
L’ANR si verifica quando il sistema tiene traccia di un timeout per uno dei quattro tipi di componenti. Ogni componente ha il proprio limite di tempo.
BroadcastReceiver viene eseguito nel thread principale. Se onReceive avvia una richiesta di rete sincrona, una scrittura lunga nel database, o attende un blocco — si verifica un ANR entro 10 secondi. Soluzione: usa goAsync() e WorkManager per l’elaborazione in background. Uno scenario tipico è ricevere una notifica Push da FCM e salvarla in modo sincrono in Room.
Service.onCreate e Service.onStartCommand hanno un limite di 20 secondi. Se il servizio avvia un’inizializzazione pesante (caricamento librerie, lettura configurazione dalla rete) nel thread principale — l’ANR è inevitabile. Usa IntentService (obsoleto) o WorkManager per un’esecuzione garantita in background.
ContentProvider.onCreate viene eseguito prima di Application.onCreate e ha un limite di 15 secondi. Se il provider esegue una migrazione del database, carica dizionari, o inizializza SDK dalla rete — questo causa ANR all’avvio dell’app. Soluzione: inizializzazione pigra, scaricare operazioni pesanti su WorkManager.
Android fornisce diversi strumenti per l’analisi degli ANR: dai log di sistema alle librerie specializzate.
A ogni ANR, Android salva il file /data/anr/traces.txt con un dump dello stack di tutti i thread dell’app. Trova il thread “main” — l’ultimo metodo nello stack indica la causa. Pattern tipici: Thread.sleep(), InputStream.read(), BinderProxy.transact(). Per estrarre il file dal dispositivo, usa adb con privilegi di superutente.
Firebase Crashlytics raccoglie automaticamente gli ANR e li mostra nella dashboard con tracce. Per Android 11+, i report ANR arrivano con lo stack completo del thread principale. L’integrazione richiede l’aggiunta di una dipendenza e l’inizializzazione di FirebaseApp in Application.onCreate.
CPU Profiler in Android Studio permette di registrare tracce dell’app e vedere quali metodi consumano tempo CPU. Abilita “Record with method traces” e riproduci lo scenario che causa l’ANR. La timeline mostrerà quali metodi erano in esecuzione nel thread principale al momento del blocco.
Esempio di integrazione di Firebase Crashlytics per la raccolta ANR su Android:
class App : Application() {
override fun onCreate() {
super.onCreate()
FirebaseApp.initializeApp(this)
FirebaseCrashlytics.getInstance()
.setCrashlyticsCollectionEnabled(true)
StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog()
.build())
}
}
Risolvere ANR significa principalmente spostare tutte le operazioni lunghe dal thread principale ai thread in background. Vediamo tecniche specifiche per ogni tipo di componente.
WorkManager è la soluzione raccomandata da Google per il lavoro in background. Garantisce l’esecuzione del compito in un thread in background considerando lo stato del dispositivo. A differenza di Service, WorkManager non blocca il thread principale ed è resiliente ai riavvii dell’app. Per BroadcastReceiver, usa goAsync() e passa il PendingResult a WorkManager.
Esegui tutte le richieste di rete, le operazioni del database e l’I/O dei file con Dispatchers.IO. Il thread principale dovrebbe solo aggiornare l’interfaccia. Usa viewModelScope per la cancellazione automatica delle coroutine quando l’Activity viene distrutta. Evita runBlocking() in qualsiasi contesto — blocca in modo sincrono il thread corrente.
Se ContentProvider esegue un’inizializzazione lenta, usa un meccanismo di caricamento pigro: crea un provider che restituisca i dati immediatamente e avvia l’inizializzazione pesante tramite WorkManager con un ritardo. Questo previene ANR all’avvio dell’app, quando il sistema è più sensibile ai ritardi.
Esempio di uso corretto di BroadcastReceiver con goAsync in Android:
class FcmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val pendingResult = goAsync()
WorkManager.getInstance(context!!)
.enqueue(OneTimeWorkRequest.from(NotificationWorker::class.java))
pendingResult.finish()
}
}
Il modo migliore per combattere gli ANR è prevenirli durante lo sviluppo attraverso strumenti e decisioni architetturali.
StrictMode con le politiche detectNetwork() e detectDiskReads()/detectDiskWrites() abilitate identifica potenziali ANR durante lo sviluppo. Nelle build Debug, imposta penaltyDeath — qualsiasi violazione causerà un crash immediato e lo sviluppatore vedrà il problema prima del commit.
Firebase Performance tiene traccia del tempo di esecuzione delle operazioni chiave e mostra quali scenari superano la soglia ANR. Imposta tracce personalizzate per ogni schermata e richiesta di rete. Se il tempo di esecuzione supera i 3 secondi — è un potenziale ANR che richiede ottimizzazione.
Simula condizioni lente: limita la velocità della rete usando Network Link Conditioner su iOS o Android Emulator. Rallenta la lettura del disco tramite emulazione di memoria lenta. ANR spesso si manifesta proprio in queste condizioni; sui dispositivi di sviluppo veloci sono invisibili.
Domande frequenti
Android tiene traccia esplicitamente del tempo di elaborazione degli eventi sul thread principale e mostra un dialogo ANR. iOS usa Watchdog, che chiude forzatamente l’app quando si blocca per più di 10–20 secondi. ANR è una caratteristica dell’architettura Android dove diversi componenti (BroadcastReceiver, Service) hanno timeout rigorosi.
Su Android 11+ puoi ottenere il dump ANR tramite adb shell dumpsys dropbox --print data_app_anr. Su Android 10 e precedenti, senza accesso root a /data/anr/traces.txt. Usa Firebase Crashlytics — raccoglie automaticamente i report ANR per Android 11+.
Google Play raccomanda un tasso di ANR inferiore allo 0,5% — non più di 5 ANR ogni 1000 sessioni. Un’app con tasso superiore all’1% riceve un avviso in Google Play Console e può essere nascosta dai consigli. Idealmente, il tasso di ANR dovrebbe essere inferiore allo 0,1%.
Una coroutine di per sé non blocca il thread. Ma se all’interno di una coroutine esegui runBlocking sul thread principale o la coroutine viene lanciata con Dispatchers.Main ed esegue una lunga operazione CPU — questo causerà ANR. Usa Dispatchers.IO per I/O e Dispatchers.Default per i calcoli.
Usa Android Emulator con un profilo “Slow Network” o scrivi un test che chiami Thread.sleep(6000) sul thread principale. Avvia l’app tramite Debug e dopo 5 secondi vedrai il dialogo ANR. Verifica che logcat mostri un record ANR con traccia.
Riepilogo
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.
Leggi anche