ANR în dezvoltarea Android — ce este, cauzele și metode de remediere

Autor: IT Sectr Publicat: 2026-03-28 Timp de citire: 9 min

ANR (Application Not Responding) — este o notificare de sistem Android care apare atunci când aplicația nu mai răspunde la intrarea utilizatorului mai mult de 5 secunde. Potrivit Android Developers, cauza principală sunt operațiile lungi pe firul principal, care blochează procesarea atingerilor și randarea interfeței. Înțelegerea mecanismelor ANR este necesară pentru fiecare dezvoltator Android pentru a crea aplicații receptive.

Principalele puncte

  • ANR — avertisment de sistem Android la înghețarea aplicației mai mult de 5 secunde
  • Firul principal (firul UI) — singurul loc unde blocarea duce la ANR
  • InputDispatcher — componenta de sistem care înregistrează întârzierea intrării și inițiază ANR
  • traces.txt — fișierul cheie pentru diagnosticarea cauzei înghețării pe dispozitiv
  • StrictMode — instrumentul integrat Android pentru detectarea operațiilor lungi pe firul UI

Ce este ANR

ANR (Application Not Responding) — este o fereastră de dialog a sistemului de operare Android care apare atunci când aplicația nu mai răspunde la intrarea utilizatorului. Sistemul urmărește timpul de procesare a evenimentelor prin InputDispatcher: dacă o atingere sau apăsarea unui buton nu este procesată în 5 secunde, Android afișează un dialog cu propunerea de a închide sau aștepta aplicația.

Mecanismul ANR protejează experiența utilizatorului de aplicațiile înghețate. Android nu permite unei singure aplicații să blocheze înntregul sistem — spre deosebire de sistemele Desktop, platforma mobilă limitează forțat timpul de procesare a evenimentelor. BroadcastReceiver are o limită de 10 secunde, iar serviciul foreground — 20 de secunde.

ANR NU este o excepție în cod — este un mecanism de sistem la nivelul proceselor Linux. Android trimite semnalul SIGQUIT procesului, după care sistemul salvează stiva de apeluri a tuturor firelor în fișierul traces.txt. Dezvoltatorul primește ANR nu ca o excepție catch, ci ca un raport după repornirea aplicației. Pe Android 11+ a apărut API-ul ApplicationExitInfo, care permite obținerea programatică a cauzei de încheiere a procesului, inclusiv ANR — simplificând colectarea statisticilor fără parsarea manuală a traces.txt.

Cauzele principale ale ANR

Cinci categorii de operații duc constant la ANR în aplicațiile Android. Fiecare dintre ele blochează firul principal, împiedicând sistemul să proceseze evenimentele de intrare și să redeseneze ecranul.

Cereri de rețea pe firul principal

Cererile HTTP sincrone executate pe firul UI — cea mai frecventă cauză de ANR la dezvoltatorii începători. Chiar și o cerere rapidă la server poate dura 1–3 secunde, iar la o conexiune slabă — 30 de secunde sau mai mult. Android interzice explicit operațiile de rețea pe firul principal începând cu API 11, aruncând NetworkOnMainThreadException.

Utilizați Coroutines sau RxJava pentru apeluri asincrone. Corutinele cu dispatcherul Dispatchers.IO execută cererea în firul de fundal, iar rezultatul este transmis pe cel principal prin Dispatchers.Main. Aceasta elimină complet blocarea firului UI de către operațiile de rețea.

kotlin
fun fetchUserData() {
    CoroutineScope(Dispatchers.Main).launch {
        val result = withContext(Dispatchers.IO) {
            api.getUserData() // operație de fundal
        }
        updateUI(result) // rezultat pe firul principal
    }
}

Calcule intensive pe firul UI

Procesarea matricelor mari de date, analiza JSON sau XML, lucrul direct cu bitmap pe firul principal — a doua cauză ca frecvență a ANR. Chiar și 300 de milisecunde de lucru continuu pe firul UI fără revenirea la bucla de evenimente cauzează o întârziere vizibilă de randare, iar valoarea limită de 5 secunde este înregistrată ca ANR.

WorkManager și serviciile de fundal sunt concepute pentru a muta calculele grele de pe firul principal. Utilizați AsyncTask (învechit), ListenableFuture sau Kotlin Flow pentru a transmite date în porții, fără a bloca UI.

Blocări de sincronizare și Deadlock

Deadlock apare atunci când două fire dețin blocări și se așteaptă reciproc. Dacă unul dintre fire este cel principal, sistemul înregistrează ANR exact după 5 secunde. Thread.join(), CountDownLatch.await() și blocurile synchronized apelate de pe firul UI comportă risc de blocare.

Evitați orice operații de blocare pe firul principal. În loc de synchronized utilizați ConcurrentHashMap, în loc de Thread.join() — corutine cu async/await. Această regulă este valabilă pentru orice limbaj în Android: Java, Kotlin sau C++ prin JNI.

Funcționarea lungă a BroadcastReceiver

BroadcastReceiver se execută implicit pe firul principal. Dacă onReceive() este ocupat mai mult de 10 secunde, Android afișează ANR. Încărcarea datelor din baza de date sau rețea în interiorul onReceive este o cale garantată spre înghețare.

Utilizați goAsync() în interiorul BroadcastReceiver pentru a comuta pe firul de fundal sau registerReceiver cu getBackgroundBroadcastReceiver(). Aceasta permite procesarea evenimentelor fără blocarea UI.

ContentProvider și SQLite pe firul principal

Interogările grele către ContentProvider sau lucrul direct cu SQLite pe firul UI — o cauză mai puțin evidentă, dar frecventă de ANR. La migrarea bazei de date sau inserarea în masă a miilor de înregistrări, timpul de execuție poate depăși limita de 5 secunde.

Mutați toate operațiile cu baza de date în firele de fundal prin Room cu funcții suspend. Room verifică automat dacă interogarea nu se execută pe firul principal și aruncă o excepție în caz de încălcare.

Cum să diagnosticăm ANR

Diagnosticarea ANR diferă de depanarea excepțiilor obișnuite — nu puteți prinde ANR în try-catch. Sursa principală de informații este fișierul traces.txt, pe care Android îl creează în momentul înghețării.

traces.txt conține stiva de apeluri a tuturor firelor aplicației la momentul ANR. Pentru a citi fișierul de pe un dispozitiv real, executați comanda adb bugreport, care colectează un raport complet al sistemului, inclusiv toate ANR-urile recente. Pentru emulator, fișierul este disponibil în /data/anr/traces.txt. Stiva de apeluri arată ce metodă se executa pe firul principal în momentul blocării.

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

Google Play Console oferă secțiunea ANR & Crash cu rapoarte agregate și frecvențe de erori. Pentru fiecare ANR este afișată stiva de apeluri și statistici pe dispozitive: model, versiune Android, regiune. Aceasta permite identificarea ANR-urilor care depind de dispozitive sau versiuni specifice de sistem.

Android Studio din 2021 conține ANR Watchdog în profilator. Acesta înregistrează automat dump-ul firelor dacă firul principal nu răspunde mai mult decât timpul prag. Instrumentul arată axa temporală a evenimentelor: ce operații au fost lansate, ce metode au fost executate și în ce etapă a avut loc blocarea.

Cum să prevenim ANR

Prevenirea ANR se bazează pe o singură regulă fundamentală: firul principal trebuie să proceseze doar evenimentele UI. Orice operație care durează mai mult de 16 milisecunde (timpul unui cadru) trebuie executată în firul de fundal.

StrictMode — verificare automată

StrictMode — instrumentul integrat Android pentru detectarea ANR-urilor potențiale în faza de dezvoltare. Activați-l în Application.onCreate() cu flaguri pentru operații de disc și rețea. La încălcare, StrictMode aruncă o excepție sau scrie în logcat.

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

Modele asincrone: Coroutines și RxJava

Kotlin Coroutines — metoda standard de lucru asincron în aplicațiile Android moderne. Principiul de bază: operațiile de intrare-ieșire se execută pe Dispatchers.IO, rezultatul este transmis pe Dispatchers.Main pentru actualizarea UI. Pentru scenarii Flow, utilizați Dispatchers.Default pentru sarcini intensive CPU.

RxJava rămâne popular în proiectele vechi. subscribeOn(Schedulers.io()) și observeOn(AndroidSchedulers.mainThread()) — setul minim pentru prevenirea ANR. Aceeași regulă: niciun Observable sau Flowable nu ar trebui să emită date de pe firul principal.

Monitorizare în producție

Firebase Crashlytics de la versiunea SDK 18.4.0 acceptă monitorizarea ANR din cutie. Pentru Android 11+ Crashlytics folosește API-ul de sistem ApplicationExitInfo, care oferă cauza exactă de încheiere: ANR, Crash sau uciderea de către sistem. Activați chei personalizate cu parametri de ecran și stare pentru analiza contextuală.

Instrumente de detectare ANR

Cinci instrumente acoperă toate etapele de lucru cu ANR: de la depanare pe stația de lucru până la monitorizare în producție. Fiecare instrument își rezolvă sarcina și oferă date pentru diferite scenarii.

InstrumentScopFormat date
StrictModeDetectare în faza de dezvoltareLogcat / Exception
ANR Watchdog (Android Studio)Urmărire în timp realThread dump + timeline
Google Play ConsoleStatistici agregateANR rate + stack traces
Firebase CrashlyticsMonitorizare producțieApplicationExitInfo
adb bugreportRaport complet de sistemtraces.txt + logcat + dmesg

Fiecare instrument are propria sa nișă: StrictMode prinde încălcările evidente în stadiile incipiente, Crashlytics arată frecvența reală a ANR la utilizatori, iar adb bugreport oferă cea mai completă imagine pentru cazurile complexe. Combinați-le pentru o acoperire completă.

Firebase Performance Monitoring

Firebase Performance urmărește timpul de răspuns al firului UI și creează automat trasee pentru operațiile suspect de lungi. Dacă firul principal se blochează mai mult de 500 ms, Performance înregistrează un trasou personalizat cu numele metodei vinovate. Aceasta permite detectarea scenariilor ANR fără participarea utilizatorului și înainte ca acestea să devină critice.

Integrarea cu Firebase Crashlytics oferă o imagine completă: Performance arată încetinirile înainte de ANR, iar Crashlytics — însuși faptul înghețării. Configurați alerte în Firebase Console pentru evenimentul ANR rate peste 0.1% și veți primi notificări despre probleme noi înaintea plângerilor în masă ale utilizatorilor.

întrebări frecvente

Cu ce se deosebește ANR de Crash?

ANR — este o înghețare în care aplicația nu răspunde, dar rămâne în memorie. Crash — încheierea completă de urgență cu ieșirea din proces. ANR poate fi supraviețuit dacă sistemul sau utilizatorul așteaptă răspunsul, iar Crash încheie întotdeauna aplicația.

Se poate prinde ANR cu try-catch?

Nu. ANR nu este o excepție Java/Kotlin, ci un semnal de sistem la nivel de procese (SIGQUIT). Dezvoltatorul nu poate să-l proceseze în codul aplicației. Singurul mod de a reacționa la ANR este să analizați rapoartele după repornire.

De ce ANR apare pe unele dispozitive, dar nu și pe altele?

Performanța dispozitivului, versiunea Android, încărcarea CPU și numărul de procese de fundal influențează probabilitatea ANR. Pe dispozitivele slabe, aceeași operație poate dura de 2–3 ori mai mult, depășind limita de 5 secunde.

Care este limita de timp a BroadcastReceiver până la ANR?

10 secunde pentru BroadcastReceiver obișnuit în onReceive(). Pentru serviciile foreground limita este de 20 de secunde, iar pentru ContentProvider nu există o limită explicită, dar blocarea firului principal mai mult de 5 secunde tot provoacă ANR.

Ce să faceți dacă ANR apare rar și nu poate fi reprodus?

Activați StrictMode în toate build-urile de debug, adăugați monitorizare prin Firebase Crashlytics și utilizați adb bugreport când apare ANR. ANR-urile neregulate sunt adesea legate de condiții de cursă (race condition) sau stări specifice de rețea.

Rezumat

  • ANR — mecanism de sistem Android care se activează la blocarea firului principal mai mult de 5 secunde
  • Firul principal trebuie să se ocupe doar de UI — toate celelalte operații sunt mutate în firele de fundal
  • Diagnosticarea ANR se face prin traces.txt, Google Play Console și Firebase Crashlytics
  • StrictMode detectează ANR-urile potențiale în faza de dezvoltare fără rulare pe un dispozitiv real
  • Coroutines cu Dispatchers.IO — metoda standard de lucru asincron în proiectele Android moderne
  • BroadcastReceiver necesită goAsync() sau înregistrator de fundal pentru lucrul mai mult de 10 secunde
  • ANR în producție se monitorizează prin Crashlytics și API-ul integrat ApplicationExitInfo pe Android 11 și mai sus

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și