ANR у развоју под Android — шта је, узроци и начини поправке

Аутор: IT Sectr Објављено: 2026-03-28 Време читања: 9 мин

ANR (Application Not Responding) — то је системско обавештење платформе Android које се појављује када апликација престане да реагује на кориснички унос дуже од 5 секунди. Према Android Developers, главни узрок су дугачке операције на главном нити, које блокирају обраду дотираја и исцртавање интерфејса. Разумевање механизама ANR-а је неопходно сваком Android програмеру за стварање пријемчивих апликација.

Главно

  • ANR — системско упозорење Android-а кад апликација замрзне дуже од 5 секунди
  • Главни нит (UI нит) — једино место где блокада води ка ANR-у
  • InputDispatcher — системска компонента која бележи кашњење уноса и покреће ANR
  • traces.txt — кључни фајл за дијагнозу узрока замрзавања на уређају
  • StrictMode — уграђени Android алат за откривање дугачких операција на UI нити

Шта је ANR

ANR (Application Not Responding) — то је дијалошки прозор оперативног система Android који се појављује када апликација престане да одговара на кориснички унос. Систем прати време обраде догађаја кроз InputDispatcher: ако дотир или притисак дугмета није обрађен за 5 секунди, Android приказује дијалог са предлогом да се апликација затвори или сачека.

Механизам ANR штити корисничко искуство од замрзлих апликација. Android не дозвољава једној апликацији да блокира цео систем — за разлику од десктоп система, мобилна платформа принудно ограничава време обраде догађаја. BroadcastReceiver има лимит од 10 секунди, а foreground сервис — 20 секунди.

ANR НИЈЕ изузетак у коду — то је системски механизам на нивоу Linux процеса. Android шаље SIGQUIT сигнал процесу, након чега систем сачува стак позива свих нити у датотеку traces.txt. Програмер добија ANR не као catch-изузетак, већ као извештај након поновног покретања апликације. На Android 11+ појавио се API ApplicationExitInfo који омогућава програмско добијање узрока завршетка процеса, укључујући ANR — то поједностављује прикупљање статистике без ручног парсирања traces.txt.

Главни узроци ANR-а

Пет категорија операција стабилно воде ка ANR-у у Android апликацијама. Свака од њих блокира главни нит, онемогућавајући систему обраду улазних догађаја и поновно исцртавање екрана.

Мрежни захтеви на главном ниту

Синхрони HTTP захтеви покренути на UI нити — најчешћи узрок ANR-а код почетних програмера. Чак и брзи захтев ка серверу може да траје 1–3 секунде, а при лошој вези — 30 секунди и више. Android експлицитно забрањује мрежне операције на главном ниту од API 11, бацајући NetworkOnMainThreadException.

За асинхроне позиве користите Coroutines или RxJava. Корутине са Dispatchers.IO диспечером извршавају захтев у позадини нити, а резултат преносе на главни кроз Dispatchers.Main. То потпуно елиминише блокаду UI нити мрежним операцијама.

kotlin
fun fetchUserData() {
    CoroutineScope(Dispatchers.Main).launch {
        val result = withContext(Dispatchers.IO) {
            api.getUserData() // позадинска операција
        }
        updateUI(result) // резултат на главном ниту
    }
}

Интензивне калкулације на UI ниту

Обрада великих низова података, парсирање JSON или XML-а, директан рад са bitmap-ом на главном ниту — други по учесталости узрок ANR-а. Чак 300 милисекунди непрекидног рада UI нити без повратка у петљу догађаја изазива приметно кашњење исцртавања, а гранична вредност од 5 секунди се бележи као ANR.

WorkManager и позадински сервиси су намењени за преношење тешких калкулација са главног нита. Користите AsyncTask (застарео), ListenableFuture или Kotlin Flow за преношење података у серијама, без блокирања UI-ја.

Синхронизационе блокаде и Deadlock

Deadlock настаје када два нита држе блокаде и чекају један другог. Ако је један од нити главни, систем бележи ANR тачно након 5 секунди. Thread.join(), CountDownLatch.await() и synchronized блокови позвани са UI нити носе ризик блокаде.

Избегавајте сваке блокирајуће операције на главном ниту. Уместо synchronized користите ConcurrentHashMap, уместо Thread.join() — корутине са async/await. Ово правило важи за сваки језик у Android-у: Java, Kotlin или C++ путем JNI-ја.

Дуг рад BroadcastReceiver-а

BroadcastReceiver се подразумевано извршава на главном ниту. Ако је onReceive() заузет дуже од 10 секунди, Android приказује ANR. Учитавање података из базе података или мреже унутар onReceive-а је гарантован пут ка замрзавању.

Унутар BroadcastReceiver-а за пребацивање на позадински нит користите goAsync() или registerReceiver са getBackgroundBroadcastReceiver(). То омогућава обраду догађаја без блокирања UI-ја.

ContentProvider и SQLite на главном ниту

Тешки упити ка ContentProvider-у или директан рад са SQLite-ом на UI ниту — мање очигледан, али чест узрок ANR-а. При миграцији базе података или групном уметању хиљада записа, време извршавања може премашити лимит од 5 секунди.

Пренесите све операције са базом података у позадинске нитове кроз Room са suspend функцијама. Room аутоматски проверава да ли се упит извршава на главном ниту и баца изузетак при кршењу.

Како дијагностирати ANR

Дијагноза ANR-а се разликује од дебагирања обичних изузетака — не можете ухватити ANR у try-catch-у. Главни извор информација је датотека traces.txt, коју Android креира у тренутку замрзавања.

traces.txt садржи стак позива свих нити апликације у тренутку ANR-а. Да бисте прочитали датотеку са стварног уређаја, извршите команду adb bugreport која прикупља потпуни системски извештај, укључујући све ANR-ове из последњег времена. За емулатор, датотека је доступна у /data/anr/traces.txt. Стак позива показује која се метода извршавала на главном ниту у тренутку блокаде.

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

Google Play Console пружа секцију ANR & Crash са агрегираним извештајима и учесталошћама грешака. За сваки ANR приказан је стак позива и статистика по уређајима: модел, верзија Android-а, регија. То омогућава идентификацију ANR-ова који зависе од одређених уређаја или верзија система.

Android Studio од 2021. године садржи ANR Watchdog у профилеру. Он аутоматски снима думп нити ако главни нит не одговара дуже од праг времена. Алат приказује временску линију догађаја: које су операције покренуте, који су методи извршени и у којој фази се блокада догодила.

Како превенити ANR

Превенција ANR-а се заснива на једном основном правилу: главни нит мора да обрађује само UI догађаје. Свака операција која траје дуже од 16 милисекунди (време једног кадра) мора да се извршава у позадинском ниту.

StrictMode — аутоматска провера

StrictMode — уграђени Android алат за откривање потенцијалних ANR-ова у фази развоја. Укључите га у Application.onCreate() са заставицама за диск и мрежне операције. При кршењу, StrictMode баца изузетак или пише у logcat.

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

Асинхрони обрасци: Coroutines и RxJava

Kotlin Coroutines — стандардни начин асинхроног рада у савременим Android апликацијама. Основни принцип: улазно-излазне операције се извршавају на Dispatchers.IO, резултат се преноси на Dispatchers.Main за ажурирање UI-ја. За Flow сценарије користите Dispatchers.Default за CPU интензивне задатке.

RxJava остаје популаран у старијим пројектима. subscribeOn(Schedulers.io()) и observeOn(AndroidSchedulers.mainThread()) — минималан скуп за превенцију ANR-а. Исто правило: ниједан Observable или Flowable не би требало да емитује податке са главног нита.

Мониторинг у производњи

Firebase Crashlytics од верзије SDK 18.4.0 подржава мониторинг ANR-а из кутије. За Android 11+ Crashlytics користи системски API ApplicationExitInfo који пружа тачан узрок завршетка: ANR, Crash или убијање од стране система. Укључите прилагођене кључеве са параметрима екрана и стања за контекстуалну анализу.

Алати за откривање ANR-а

Пет алата покрива све фазе рада са ANR-ом: од дебагирања на радној станици до мониторинга у производњи. Сваки алат решава свој задатак и пружа податке за различите сценарије.

АлатНаменаФормат података
StrictModeОткривање у фази развојаLogcat / Exception
ANR Watchdog (Android Studio)Праћење у реалном временуThread dump + timeline
Google Play ConsoleАгрегирана статистикаANR rate + stack traces
Firebase CrashlyticsМониторинг у производњиApplicationExitInfo
adb bugreportПотпун системски извештајtraces.txt + logcat + dmesg

Сваки алат има своју нишу: StrictMode хвата очигледне кршења у раним фазама, Crashlytics показује стварну учесталост ANR-а код корисника, а adb bugreport пружа најпотпунију слику за сложене случајеве. Комбинујте их за потпуно покривање.

Firebase Performance Monitoring

Firebase Performance прати време одговора UI нити и аутоматски креира трагове за сумњиво дугачке операције. Ако се главни нит блокира на више од 500 ms, Performance бележи прилагођени траг са називом методе кривца. То омогућава откривање ANR сценарија без учешћа корисника и пре него што постану критични.

Интеграција са Firebase Crashlytics даје потпуну слику: Performance показује успоравања пре ANR-а, а Crashlytics — сам факт замрзавања. Поставите аларме у Firebase Console за догађај ANR rate изнад 0,1% и добијаћете обавештења о новим проблемима пре него што почну масовне жалбе корисника.

Често постављана питања

По чему се ANR разликује од Crash-а?

ANR — то је замрзавање при којем апликација не одговара, али остаје у меморији. Crash — потпуно хаваријско завршавање са изласком из процеса. ANR се може преживети ако систем или корисник сачекају одговора, а Crash увијек завршава апликацију.

Може ли се ANR ухватити кроз try-catch?

Не. ANR није Java/Kotlin изузетак, већ системски сигнал на нивоу процеса (SIGQUIT). Програмер не може да га обради у коду апликације. Једини начин реаговања на ANR је анализирање извештаја након поновног покретања.

Зашто се ANR појављује на једним уређајима, али не на другима?

Перформансе уређаја, верзија Android-а, оптерећење CPU-а и број позадинских процеса утичу на вероватноћу ANR-а. На слабим уређајима иста операција може да траје 2–3 пута дуже, прелазећи лимит од 5 секунди.

Који је временски лимит BroadcastReceiver-а пре ANR-а?

10 секунди за обичани BroadcastReceiver у onReceive(). За foreground сервисе лимит је 20 секунди, а за ContentProvider нема експлицитног лимита, али блокада главног нита дужа од 5 секунди ипак изазива ANR.

Шта радити ако се ANR јавља ретко и не може да се репродукује?

Укључите StrictMode у свим debug издањима, додајте мониторинг кроз Firebase Crashlytics и користите adb bugreport кад се ANR догоди. Нерегуларни ANR-ови често су повезани са условима трке (race condition) или специфичним стањима мреже.

Резиме

  • ANR — системски механизам Android-а који се активира при блокади главног нита дужој од 5 секунди
  • Главни нит треба да се бави само UI-јем — све остале операције се преносе у позадинске нитове
  • Дијагноза ANR-а се врши кроз traces.txt, Google Play Console и Firebase Crashlytics
  • StrictMode открива потенцијалне ANR-ове у фази развоја без покретања на стварном уређају
  • Coroutines са Dispatchers.IO — стандардни начин асинхроног рада у савременим Android пројектима
  • BroadcastReceiver захтева goAsync() или позадинског регистратора за рад дужи од 10 секунди
  • ANR у производњи се прати кроз Crashlytics и уграђени API ApplicationExitInfo на Android 11 и више

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође