Quando il thread dell'interfaccia utente di un'app per Android viene bloccato per troppo tempo, viene attivato un errore "L'applicazione non risponde" (ANR). Se l'app è in primo piano, il sistema mostra all'utente una finestra di dialogo, come mostrato nella figura 1. La finestra di dialogo ANR offre all'utente la possibilità di forzare l'uscita dall'app.
Gli errori ANR sono un problema perché il thread principale dell'app, responsabile dell'aggiornamento dell'interfaccia utente, non può elaborare gli eventi di input dell'utente o disegnare, causando frustrazione all'utente. Per ulteriori informazioni sul thread principale dell'app, consulta la panoramica di processi e thread.
Un errore ANR viene attivato per la tua app quando si verifica una delle seguenti condizioni:
- Input dispatching timed out: se la tua app non ha risposto a un evento di input (ad esempio una pressione di un tasto o un tocco dello schermo) entro 5 secondi.
- Executing service: se un servizio dichiarato dalla tua app non riesce a completare l'esecuzione di
Service.onCreateeService.onStartCommand/Service.onBindentro pochi secondi. Service.startForegroundnot called: se la tua app utilizzaContext.startForegroundServiceper avviare un nuovo servizio in primo piano ma il servizio non chiamastartForegroundentro 5 secondi.- Broadcast of intent: se un
BroadcastReceivernon ha terminato l'esecuzione entro un determinato periodo di tempo. Se l'app ha un'attività in primo piano, questo timeout è di 5 secondi. JobSchedulerinterazioni: se unJobServicenon restituisce daJobService.onStartJoboJobService.onStopJobentro pochi secondi oppure se un job avviato dall'utente viene avviato e la tua app non chiamaJobService.setNotificationentro pochi secondi dalla chiamata diJobService.onStartJob. Per le app che hanno come target Android 13 e versioni precedenti, gli errori ANR sono silenziosi e non vengono segnalati all'app. Per le app che hanno come target Android 14 e versioni successive, gli errori ANR sono espliciti e vengono segnalati all'app.
Se la tua app riscontra errori ANR, puoi utilizzare le indicazioni riportate in questo documento per diagnosticare e risolvere il problema.
Rilevare il problema
Se hai già pubblicato la tua app, puoi utilizzare Android vitals per visualizzare le informazioni sugli errori ANR per la tua app. Puoi utilizzare altri strumenti per rilevare gli errori ANR sul campo, ma tieni presente che gli strumenti di terze parti non possono segnalare gli errori ANR su Android 10 e versioni precedenti, a differenza di Android vitals.
Android vitals
Android vitals può aiutarti a monitorare e migliorare la percentuale di ANR della tua app. Android vitals misura diverse percentuali di errori ANR:
- Percentuale di ANR: la percentuale di utenti attivi giornalieri che hanno riscontrato qualsiasi tipo di ANR.
- Percentuale di ANR percepiti dagli utenti: la percentuale di utenti attivi giornalieri che hanno riscontrato almeno un errore ANR percepito dall'utente. Al momento, solo gli errori ANR di tipo
Input dispatching timed outsono considerati percepiti dall'utente. - Percentuale di errori ANR multipli: la percentuale di utenti attivi giornalieri che hanno riscontrato almeno due errori ANR.
Un utente attivo giornaliero è un utente unico che utilizza la tua app in un solo giorno su un singolo dispositivo, potenzialmente in più sessioni. Se un utente utilizza la tua app su più dispositivi in un solo giorno, ogni dispositivo contribuirà al numero di utenti attivi per quel giorno.
La percentuale di ANR percepiti dagli utenti è una metrica vitals essenziale, ovvero influisce sulla rilevabilità della tua app su Google Play. È importante perché gli errori ANR che conta si verificano sempre quando gli utenti interagiscono con l'app, causando così il maggior numero di interruzioni.
Play ha definito due soglie relative alle prestazioni scadenti per questa metrica:
- Soglia relativa alle prestazioni scadenti complessiva: almeno lo 0, 47% degli utenti attivi giornalieri ha riscontrato un errore ANR percepito dall'utente su tutti i modelli di dispositivi.
- Soglia relativa alle prestazioni scadenti per dispositivo: almeno l'8% degli utenti giornalieri ha riscontrato un errore ANR percepito dall'utente su un singolo modello di dispositivo.
Se la tua app supera la soglia relativa alle prestazioni scadenti complessiva, è probabile che sia meno rilevabile su tutti i dispositivi. Se la tua app supera la soglia relativa alle prestazioni scadenti per dispositivo su alcuni dispositivi, è probabile che sia meno rilevabile su questi dispositivi e potrebbe essere mostrato un avviso nella tua scheda dello Store.
Android vitals può avvisarti tramite Play Console quando la tua app presenta un numero eccessivo di errori ANR.
Per informazioni su come Google Play raccoglie i dati Android vitals, consulta la Play Console documentazione.
Diagnosticare gli errori ANR
Esistono alcuni pattern comuni da cercare quando si diagnosticano gli errori ANR:
- L'app esegue operazioni lente che coinvolgono I/O sul thread principale.
- L'app esegue un calcolo lungo sul thread principale.
- Il thread principale esegue una chiamata binder sincrona a un altro processo e quest'ultimo impiega molto tempo per restituire un valore.
- Il thread principale è bloccato in attesa di un blocco sincronizzato per un'operazione lunga che si verifica su un altro thread.
- Il thread principale si trova in una situazione di deadlock con un altro thread, nel tuo processo o tramite una chiamata binder. Il thread principale non è solo in attesa del completamento di un'operazione lunga, ma si trova in una situazione di deadlock.
Le seguenti tecniche possono aiutarti a determinare la causa degli errori ANR.
HealthStats
HealthStats fornisce metriche sull'integrità di un'applicazione acquisendo il tempo totale dell'utente e del sistema, il tempo della CPU, le statistiche di rete e radio, il tempo di accensione/spegnimento dello schermo e gli allarmi di riattivazione. Questo può aiutarti a misurare l'utilizzo complessivo della CPU e il consumo della batteria.
Debug
Debug ti aiuta a ispezionare le applicazioni Android durante lo sviluppo, inclusi i conteggi di traccia e allocazione per identificare jank e ritardi nelle app.
Puoi anche utilizzare Debug per ottenere contatori di memoria nativa e di runtime e metriche di memoria che possono aiutarti a identificare il footprint della memoria di un determinato processo.
ApplicationExitInfo
ApplicationExitInfo è disponibile su Android 11 (livello API 30) o versioni successive e fornisce informazioni sul motivo dell'uscita dell'applicazione. Sono inclusi errori ANR, memoria insufficiente, arresti anomali delle app, utilizzo eccessivo della CPU, interruzioni dell'utente, interruzioni del sistema e modifiche delle autorizzazioni di runtime.
Modalità StrictMode
L'utilizzo di StrictMode ti aiuta a trovare operazioni di I/O accidentali sul thread principale durante lo sviluppo dell'app. Puoi utilizzare StrictMode a livello di applicazione o attività.
Attivare le finestre di dialogo ANR in background
Android mostra le finestre di dialogo ANR per le app che impiegano troppo tempo per elaborare il messaggio di trasmissione solo se l'opzione Mostra tutti gli errori ANR è attivata in Opzioni sviluppatore del dispositivo. Per questo motivo, le finestre di dialogo ANR in background non vengono sempre mostrate all'utente, anche quando l'app riscontra problemi di prestazioni.
Colli di bottiglia di ricomposizione
Utilizza Android Studio Profiler e Layout Inspector per individuare i colli di bottiglia di ricomposizione. Per ulteriori informazioni, consulta la sezione Rendimento di Jetpack Compose.
Estrarre un file di tracce
Android memorizza le informazioni di traccia quando si verifica un errore ANR. Nelle versioni precedenti del sistema operativo, sul dispositivo è presente un singolo file /data/anr/traces.txt. Nelle versioni più recenti del sistema operativo, sono presenti più file /data/anr/anr_*. Puoi accedere alle tracce ANR
da un dispositivo o un emulatore utilizzando Android Debug Bridge (adb) come
root:
adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>
Puoi acquisire un report sui bug da un dispositivo fisico utilizzando l'opzione sviluppatore Apri segnalazione bug sul dispositivo o il comando adb bugreport sulla macchina di sviluppo. Per ulteriori informazioni, consulta
Acquisire e leggere i report sui bug.
Risolvere i problemi
Dopo aver identificato il problema, puoi utilizzare i suggerimenti in questa sezione per risolvere i problemi più comuni.
Codice lento sul thread principale
Identifica i punti del codice in cui il thread principale dell'app è occupato per più di 5 secondi. Cerca i casi d'uso sospetti nella tua app e prova a riprodurre l'errore ANR.
Un problema comune è un'attività a lunga esecuzione direttamente in un elemento componibile:
@Composable
fun BadList(rawStrings: List<String>) {
// Math or sorting inside the composable runs on EVERY recomposition pass!
val heavilyProcessedList = rawStrings
.filter { it.isNotBlank() }
.map { it.uppercase().reversed() }
.map { it.computationallyHeavyFunction() }
.sortedBy { it.length }
LazyColumn { items(sortedList) { Text(it) } }
}
// Modern Compose-first fix
@Composable
fun GoodList(viewModel: MyViewModel = viewModel()) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
// UI simply renders state; no heavy processing allowed here
LazyColumn { items(uiState.sortedData) { Text(it) } }
}
I/O sul thread principale
L'esecuzione di operazioni di I/O sul thread principale è una causa comune di operazioni lente sul thread principale, che possono causare errori ANR. In Compose, gli sviluppatori spesso attivano accidentalmente le letture del disco (ad esempio SharedPreferences o chiamate di database) mentre cercano di derivare lo stato iniziale.
Esegui operazioni di I/O a lunga esecuzione al di fuori del livello dell'interfaccia utente. Utilizza
withContext(Dispatchers.IO) in un ViewModel o, meglio ancora, utilizza un
Repository sul livello dati.
Deadlock
Si verifica un deadlock quando un thread entra in uno stato di attesa perché una risorsa richiesta è mantenuta da un altro thread, che è anche in attesa di una risorsa mantenuta dal primo thread. Se il thread principale dell'app si trova in questa situazione, è probabile che si verifichino errori ANR.
I deadlock sono un fenomeno ben studiato nell'informatica ed esistono algoritmi di prevenzione dei deadlock che puoi utilizzare per evitarli.
Per ulteriori informazioni, consulta gli articoli Deadlock e Algoritmi di prevenzione dei deadlock su Wikipedia.
Quando utilizzi Kotlin e Compose, puoi sostituire i blocchi primitivi con
i mutex di coroutine non bloccanti (Mutex.withLock) per impedire il blocco dei thread
sospendendo il contesto di esecuzione anziché bloccare il thread dell'interfaccia utente. Ad esempio:
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
// Modern non-blocking concurrency state architecture
class SecureDataRepository {
private val mutex = Mutex()
suspend fun safeUIAccess() {
// If locked, the main thread suspends seamlessly, preventing an ANR
mutex.withLock {
performSafeOperation()
}
}
}
Broadcast receiver lenti
Le app possono rispondere ai messaggi di trasmissione, ad esempio attivando o disattivando la modalità aereo o una modifica dello stato della connettività, tramite i broadcast receiver. Si verifica un errore ANR quando un'app impiega troppo tempo per elaborare l'annuncio.
Si verifica un errore ANR nei seguenti casi:
- Un broadcast receiver non ha terminato l'esecuzione del metodo
onReceiveentro un periodo di tempo considerevole. - Un broadcast receiver chiama
goAsynce non chiamafinishsull'oggettoPendingResult.
L'app deve eseguire solo operazioni brevi nel onReceive metodo
di un BroadcastReceiver. Tuttavia, se la tua app richiede un'elaborazione più complessa a seguito di un annuncio, devi rimandare l'attività a un ViewModel (sfruttando la potenza delle coroutine, degli ambiti e dei dispatcher Kotlin) se l'attività dovrebbe richiedere al massimo pochi secondi, a qualsiasi tipo di contenitore di stato, o a WorkManager per le attività che dovrebbero richiedere più di pochi secondi.
GameActivity
La libreria GameActivity ha ridotto gli errori ANR negli studi di casi di
giochi e app scritti in C o C++. Se sostituisci l'attività nativa esistente con GameActivity, puoi ridurre il blocco del thread dell'interfaccia utente ed evitare che si verifichino alcuni
errori ANR.
Per ulteriori informazioni sugli errori ANR, consulta la pagina Mantieni la reattività della tua app. Per ulteriori informazioni sui thread, consulta la pagina Migliorare il rendimento tramite i thread.
Risorse aggiuntive
Visualizzare i contenuti
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Wakeup eccessivi