ANR nello sviluppo Android — cos'è, cause e modi per risolverlo

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

ANR (Application Not Responding) è una notifica di sistema Android che appare quando un'applicazione smette di rispondere all'input dell'utente per più di 5 secondi. Secondo Android Developers, la causa principale sono le operazioni lunghe sul thread principale che bloccano l'elaborazione dei tocchi e il rendering dell'interfaccia. Comprendere i meccanismi di ANR è essenziale per ogni sviluppatore Android per creare applicazioni reattive.

Punti chiave

  • ANR — un avviso di sistema Android quando un'applicazione si blocca per più di 5 secondi
  • Thread principale (thread UI) — l'unico posto dove il blocco porta ad ANR
  • InputDispatcher — il componente di sistema che rileva il ritardo di input e attiva ANR
  • traces.txt — il file chiave per diagnosticare la causa del blocco su un dispositivo
  • StrictMode — uno strumento integrato Android per rilevare operazioni lunghe sul thread UI

Cos'è ANR

ANR (Application Not Responding) è una finestra di dialogo del sistema operativo Android che appare quando un'applicazione smette di rispondere all'input dell'utente. Il sistema traccia il tempo di elaborazione degli eventi tramite InputDispatcher: se un tocco o una pressione di un pulsante non viene gestito entro 5 secondi, Android mostra una finestra che offre di chiudere o attendere l'applicazione.

Il meccanismo ANR protegge l'esperienza utente dalle applicazioni bloccate. Android non permette a un'applicazione di bloccare l'intero sistema — a differenza dei sistemi operativi desktop, la piattaforma mobile limita forzatamente il tempo di elaborazione degli eventi. BroadcastReceiver ha un limite di 10 secondi e un servizio in primo piano ha 20 secondi.

ANR NON è un'eccezione nel codice — è un meccanismo di sistema a livello di processi Linux. Android invia un segnale SIGQUIT al processo, dopo di che il sistema salva lo stack di chiamate di tutti i thread nel file traces.txt. Lo sviluppatore non riceve ANR come eccezione catch, ma come report dopo il riavvio dell'applicazione. Su Android 11+, l'API ApplicationExitInfo permette di ottenere programmaticamente la ragione della terminazione del processo, incluso ANR — questo semplifica la raccolta di statistiche senza analisi manuale di traces.txt.

Cause principali di ANR

Cinque categorie di operazioni portano costantemente ad ANR nelle applicazioni Android. Ognuna di esse blocca il thread principale, impedendo al sistema di elaborare gli eventi di input e il ridisegno dello schermo.

Richieste di rete sul thread principale

Le richieste HTTP sincrone eseguite sul thread UI sono la causa più comune di ANR tra gli sviluppatori principianti. Anche una richiesta veloce a un server può richiedere 1–3 secondi, e con una connessione scadente — 30 secondi o più. Android vieta esplicitamente le operazioni di rete sul thread principale a partire dall'API 11, lanciando NetworkOnMainThreadException.

Utilizza Coroutines o RxJava per chiamate asincrone. Le coroutine con il dispatcher Dispatchers.IO eseguono la richiesta in un thread di background e passano il risultato al thread principale tramite Dispatchers.Main. Questo elimina completamente il blocco del thread UI da parte delle operazioni di rete.

kotlin
fun fetchUserData() {
    CoroutineScope(Dispatchers.Main).launch {
        val result = withContext(Dispatchers.IO) {
            api.getUserData() // operazione in background
        }
        updateUI(result) // risultato sul thread principale
    }
}

Calcoli intensivi sul thread UI

Elaborare grandi array di dati, analizzare JSON o XML, lavorare con bitmap direttamente sul thread principale — la seconda causa più frequente di ANR. Anche 300 millisecondi di lavoro continuo del thread UI senza tornare al ciclo di eventi causano un notevole ritardo nel rendering, e la soglia di 5 secondi viene registrata come ANR.

WorkManager e i servizi in background sono progettati per spostare i calcoli pesanti fuori dal thread principale. Utilizza AsyncTask (deprecato), ListenableFuture o Kotlin Flow per passare dati a blocchi senza bloccare la UI.

Blocchi di sincronizzazione e Deadlock

Un Deadlock si verifica quando due thread tengono blocchi e si aspettano a vicenda. Se uno dei thread è il thread principale, il sistema registra ANR esattamente dopo 5 secondi. Thread.join(), CountDownLatch.await() e blocchi synchronized chiamati dal thread UI comportano rischio di blocco.

Evita qualsiasi operazione bloccante sul thread principale. Invece di synchronized, usa ConcurrentHashMap; invece di Thread.join() — coroutine con async/await. Questa regola si applica a qualsiasi linguaggio in Android: Java, Kotlin o C++ tramite JNI.

BroadcastReceiver di lunga durata

BroadcastReceiver viene eseguito sul thread principale per impostazione predefinita. Se onReceive() è occupato per più di 10 secondi, Android mostra ANR. Caricare dati da un database o rete all'interno di onReceive è una strada garantita verso il blocco.

Utilizza goAsync() all'interno di BroadcastReceiver per passare a un thread di background, o registerReceiver con getBackgroundBroadcastReceiver(). Questo permette di gestire gli eventi senza bloccare la UI.

ContentProvider e SQLite sul thread principale

Query pesanti a ContentProvider o lavoro diretto con SQLite sul thread UI — una causa meno ovvia ma comune di ANR. Durante la migrazione del database o l'inserimento in massa di migliaia di record, il tempo di esecuzione può superare il limite di 5 secondi.

Sposta tutte le operazioni di database in thread di background usando Room con funzioni suspend. Room verifica automaticamente che la query non venga eseguita sul thread principale e lancia un'eccezione in caso di violazione.

Come diagnosticare ANR

Diagnosticare ANR differisce dal debugging delle eccezioni normali — non puoi catturare ANR in un blocco try-catch. La principale fonte di informazione è il file traces.txt, che Android crea al momento del blocco.

traces.txt contiene lo stack di chiamate di tutti i thread dell'applicazione al momento dell'ANR. Per leggere il file da un dispositivo reale, esegui il comando adb bugreport, che raccoglie un report completo di sistema includendo tutti gli ANR recenti. Per un emulatore, il file è disponibile in /data/anr/traces.txt. Lo stack di chiamate mostra quale metodo era in esecuzione sul thread principale al momento del blocco.

text
adb bugreport bugreport.zip
unzip -p bugreport.zip "*traces*" > traces.txt

Google Play Console fornisce la sezione ANR & Crash con report aggregati e frequenze di errore. Per ogni ANR, vengono mostrati lo stack di chiamate e le statistiche del dispositivo: modello, versione Android, regione. Questo permette di identificare ANR che dipendono da dispositivi o versioni di sistema specifici.

Android Studio dal 2021 include ANR Watchdog nel profiler. Registra automaticamente dump dei thread se il thread principale non risponde per più di un tempo soglia. Lo strumento mostra una timeline degli eventi: quali operazioni sono state avviate, quali metodi sono stati eseguiti e in quale fase si è verificato il blocco.

Come prevenire ANR

La prevenzione di ANR si basa su una regola fondamentale: il thread principale dovrebbe gestire solo eventi UI. Qualsiasi operazione più lunga di 16 millisecondi (tempo di un frame) dovrebbe essere eseguita in un thread di background.

StrictMode — controllo automatico

StrictMode è uno strumento integrato Android per rilevare potenziali ANR durante lo sviluppo. Attivalo in Application.onCreate() con flag per operazioni su disco e rete. In caso di violazione, StrictMode lancia un'eccezione o scrive in logcat.

kotlin
if (BuildConfig.DEBUG) {
    StrictMode.ThreadPolicy.Builder()
        .detectDiskReads()
        .detectDiskWrites()
        .detectNetwork()
        .penaltyLog()
        .build()
        .let { StrictMode.setThreadPolicy(it) }
}

Pattern asincroni: Coroutines e RxJava

Kotlin Coroutines — il modo standard di lavoro asincrono nelle applicazioni Android moderne. L'approccio principale: le operazioni di I/O vengono eseguite su Dispatchers.IO, il risultato viene passato a Dispatchers.Main per gli aggiornamenti UI. Per scenari simili a Flow, usa Dispatchers.Default per attività intensive di CPU.

RxJava rimane popolare nei progetti legacy. subscribeOn(Schedulers.io()) e observeOn(AndroidSchedulers.mainThread()) — il set minimo per prevenire ANR. La regola principale è la stessa: nessun Observable o Flowable dovrebbe emettere dati dal thread principale.

Monitoraggio in produzione

Firebase Crashlytics dalla versione SDK 18.4.0 supporta il monitoraggio ANR nativamente. Per Android 11+, Crashlytics utilizza l'API di sistema ApplicationExitInfo, che fornisce la ragione esatta della terminazione: ANR, Crash o kill di sistema. Attiva chiavi personalizzate con parametri di schermo e stato per analisi contestuale.

Strumenti per il rilevamento di ANR

Cinque strumenti coprono tutte le fasi del lavoro con ANR: dal debugging su una workstation al monitoraggio in produzione. Ogni strumento risolve il proprio compito e fornisce dati per diversi scenari.

StrumentoScopoFormato dati
StrictModeRilevamento durante lo sviluppoLogcat / Exception
ANR Watchdog (Android Studio)Tracciamento in tempo realeThread dump + timeline
Google Play ConsoleStatistiche aggregateANR rate + stack traces
Firebase CrashlyticsMonitoraggio in produzioneApplicationExitInfo
adb bugreportReport completo di sistematraces.txt + logcat + dmesg

Ogni strumento ha la propria nicchia: StrictMode cattura violazioni evidenti nelle fasi iniziali, Crashlytics mostra la frequenza reale di ANR tra gli utenti, e adb bugreport fornisce il quadro più completo per casi complessi. Combinali per una copertura totale.

Firebase Performance Monitoring

Firebase Performance traccia il tempo di risposta del thread UI e crea automaticamente trace per operazioni sospettosamente lunghe. Se il thread principale si blocca per più di 500 ms, Performance registra una trace personalizzata con il nome del metodo colpevole. Questo permette di rilevare scenari ANR senza coinvolgimento dell'utente e prima che diventino critici.

L'integrazione con Firebase Crashlytics fornisce un quadro completo: Performance mostra i rallentamenti prima dell'ANR, e Crashlytics mostra il blocco stesso. Imposta avvisi in Firebase Console per un tasso ANR superiore allo 0.1% e riceverai notifiche sui nuovi problemi prima di reclami massivi degli utenti.

Domande frequenti

In cosa si differenzia ANR da Crash?

ANR è un blocco in cui l'applicazione non risponde ma rimane in memoria. Crash è una terminazione anomala completa con uscita dal processo. ANR può essere “sopravvissuto” se il sistema o l'utente aspettano una risposta, mentre Crash termina sempre l'applicazione.

Si può catturare ANR con try-catch?

No. ANR non è un'eccezione Java/Kotlin, ma un segnale di sistema a livello di processi (SIGQUIT). Uno sviluppatore non può gestirlo nel codice dell'applicazione. L'unico modo per rispondere ad ANR è analizzare i report dopo il riavvio.

Perché ANR appare su alcuni dispositivi ma non su altri?

Le prestazioni del dispositivo, la versione Android, il carico della CPU e il numero di processi in background influenzano la probabilità di ANR. Su dispositivi deboli, la stessa operazione può richiedere da 2 a 3 volte più tempo, superando il limite di 5 secondi.

Qual è il limite di tempo di BroadcastReceiver prima di ANR?

10 secondi per un BroadcastReceiver normale in onReceive(). Per i servizi in primo piano, il limite è di 20 secondi, e per ContentProvider — non c'è un limite esplicito, ma bloccare il thread principale per più di 5 secondi causa comunque ANR.

Cosa fare se ANR si verifica raramente e non è riproducibile?

Attiva StrictMode in tutte le build di debug, aggiungi monitoraggio tramite Firebase Crashlytics e usa adb bugreport quando ANR si verifica. ANR irregolari sono spesso correlati a condizioni di competizione o stati di rete specifici.

Riepilogo

  • ANR — un meccanismo di sistema Android attivato quando il thread principale si blocca per più di 5 secondi
  • Il thread principale dovrebbe gestire solo UI — tutte le altre operazioni vengono spostate in thread di background
  • La diagnosi di ANR viene effettuata tramite traces.txt, Google Play Console e Firebase Crashlytics
  • StrictMode rileva potenziali ANR durante lo sviluppo senza esecuzione su un dispositivo reale
  • Coroutines con Dispatchers.IO — il modo standard di lavoro asincrono nei progetti Android moderni
  • BroadcastReceiver richiede goAsync() o un registrar di background per funzionare più di 10 secondi
  • ANR in produzione viene monitorato tramite Crashlytics e l'API integrata ApplicationExitInfo su Android 11 e superiori

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