ANR в Android: какво е, причини и методи за отстраняване

Автор: IT Sectr Публикувано: 2026-07-28 Време за четене: 9 мин

ANR (Application Not Responding) — е системно известие на Android, което се появява, когато приложението не реагира на въвеждане в продължение на 5 секунди. За разлика от гличовете (логически грешки без блокиране на UI) и лаговете (забавяне без пълно спиране), ANR е критична повреда, регистрирана от операционната система: Android показва диалог „Приложението не отговаря“ с предложение за затваряне или изчакване. Според Android Vitals Documentation, приложенията с ANR процент над 0,5% имат по-нисък рейтинг в Google Play и могат да бъдат скрити от препоръките. Диагностиката включва анализ на /data/anr/traces.txt, използване на StrictMode и профилиране на главната нишка.

Основни точки

  • ANR — системно известие на Android при блокиране на главната нишка за повече от 5 секунди, водещо до диалог „Приложението не отговаря“
  • Основни причини — блокиране на главната нишка (BroadcastReceiver, Service), deadlock между нишки, дълга операция в ContentProvider
  • Диагностика — анализ на /data/anr/traces.txt, Android Studio Profiler, Firebase Performance Monitoring
  • Отстраняване — прехвърляне на задачи към WorkManager, използване на Kotlin Coroutines с Dispatchers.IO, StrictMode за ранно откриване
  • Профилактика — ограничаване на времето на BroadcastReceiver до 10 секунди, Service до 20 секунди, ContentProvider до 15 секунди

Какво е ANR в Android

ANR (Application Not Responding) — е механизъм за защита на потребителя в Android, който се активира, когато приложението спре да реагира на въвеждане. Системта следи времето за обработка на събития: ако BroadcastReceiver не завърши onReceive в рамките на 10 секунди, Service не се върне от onCreate в рамките на 20 секунди, а ContentProvider не отговори в рамките на 15 секунди — Android генерира ANR.

Как изглежда ANR за потребителя

Когато възникне ANR, Android показва системен диалог над всички прозорци: „Приложението не отговаря. Да го затворите ли или да изчакате?“. Потребителят може да затвори приложението или да изчака възстановяването му. Ако ANR се повтаря често, потребителят изтрива приложението. Google Play взема предвид ANR процента — процента сесии с ANR — в алгоритмите за класиране.

Разлика между ANR и замръзванията на iOS

На iOS няма аналог на ANR със системен диалог. Вместо това Apple използва Watchdog, който прекратява процеса на приложението с код 0x8badf00d. Потребителят не вижда диалог — приложението просто се затваря към началния екран. Това прави ANR на Android по-забележим за потребителя, но дава на системата повече информация за диагностика.

Основни причини за ANR

ANR възниква, когато системата следи таймаут за един от четирите типа компоненти. Всеки компонент има свой собствен времеви лимит.

Блокиране в BroadcastReceiver

BroadcastReceiver се изпълнява в главната нишка. Ако onReceive стартира синхронна мрежова заявка, дълга операция за запис в базата данни или чака блокиране — след 10 секунди възниква ANR. Решение: използвайте goAsync() и WorkManager за фонова обработка. Типичен сценарий — получаване на Push известие от FCM и синхронно запазване в Room.

Дълга операция в Service

Service.onCreate и Service.onStartCommand имат лимит от 20 секунди. Ако услугата стартира тежка инициализация (зареждане на библиотеки, четене на конфигурация от мрежата) в главната нишка — ANR е неизбежен. Използвайте IntentService (остарял) или WorkManager за гарантирано изпълнение във фонова нишка.

ContentProvider с дълга инициализация

ContentProvider.onCreate се изпълнява преди извикването на Application.onCreate и има лимит от 15 секунди. Ако доставчикът извършва миграция на база данни, зареждане на речници или инициализация на SDK от мрежата — това причинява ANR при стартиране на приложението. Решение: ленива инициализация, прехвърляне на тежки операции към WorkManager.

  • BroadcastReceiver — 10 секунди за onReceive; използвайте goAsync() за фонова обработка
  • Service — 20 секунди за onCreate/onStartCommand; използвайте WorkManager или CoroutineWorker
  • ContentProvider — 15 секунди за onCreate; преместете инициализацията в Application.onCreate със закъснял старт
  • UI нишка — 5 секунди без обработка на събития; всяко блокиране по-дълго от 5 секунди причинява ANR

Как да диагностицираме ANR

Android предоставя няколко инструмента за анализ на ANR: от системни логове до специализирани библиотеки.

Анализ на traces.txt

При всеки ANR Android запазва файла /data/anr/traces.txt с дамп на стековете на всички нишки на приложението. Намерете нишката „main“ — последният метод в стека показва причината. Типични модели: Thread.sleep(), InputStream.read(), BinderProxy.transact(). За извличане на файла от устройството използвайте adb със суперпотребителски права.

Firebase Crashlytics с ANR отчети

Firebase Crashlytics автоматично събира ANR и ги показва в таблото за управление заедно с проследяване. За Android 11+ ANR отчетите идват с пълен стек на главната нишка. Интеграцията изисква добавяне на зависимост и инициализация на FirebaseApp в Application.onCreate.

Android Studio Profiler с проследяване на нишки

CPU Profiler в Android Studio ви позволява да запишете проследяване на работата на приложението и да видите кои методи заемат процесорно време. Включете „Record with method traces“ и възпроизведете сценария, причиняващ ANR. На времевата линия ще бъде видимо кои методи са се изпълнявали в главната нишка в момента на замръзване.

Пример за интеграция на Firebase Crashlytics за събиране на ANR на Android:

kotlin
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        FirebaseApp.initializeApp(this)
        FirebaseCrashlytics.getInstance()
            .setCrashlyticsCollectionEnabled(true)
        StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder()
            .detectAll()
            .penaltyLog()
            .build())
    }
}

Методи за отстраняване на ANR

Отстраняването на ANR означава преди всичко прехвърляне на всички дълги операции от главната нишка към фоновите нишки. Нека разгледаме конкретни техники за всеки тип компонент.

Използване на WorkManager за фонови задачи

WorkManager — препоръчителното от Google решение за фонова работа. Гарантира изпълнение на задачата във фонова нишка, като взема предвид състоянието на устройството. За разлика от Service, WorkManager не блокира главната нишка и е устойчив на рестартиране на приложението. За BroadcastReceiver използвайте goAsync() и предайте резултата PendingResult на WorkManager.

Kotlin Coroutines с правилни диспечери

Стартирайте всички мрежови заявки, работа с база данни и файлови операции с Dispatchers.IO. Главната нишка трябва само да актуализира UI. Използвайте viewModelScope за автоматично отмяна на корутините при унищожаване на Activity. Избягвайте runBlocking() в какъвто и да е контекст — това е синхронно блокиране на текущата нишка.

Ленива инициализация на ContentProvider

Ако ContentProvider извършва дълга инициализация, използвайте механизъм за закъсняло зареждане: създайте доставчик, който незабавно връща данни, и стартирайте тежката инициализация чрез WorkManager със закъснение. Това предотвратява ANR при стартиране на приложението, когато системата е най-чувствителна към закъснения.

Пример за правилно използване на BroadcastReceiver с goAsync в Android:

kotlin
class FcmReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        val pendingResult = goAsync()
        WorkManager.getInstance(context!!)
            .enqueue(OneTimeWorkRequest.from(NotificationWorker::class.java))
        pendingResult.finish()
    }
}

Профилактика на ANR в разработката

Най-добрият начин за борба с ANR е предотвратяването на появата им в етапа на разработка чрез инструменти и архитектурни решения.

StrictMode за откриване на блокирания на главната нишка

StrictMode с активирани политики detectNetwork() и detectDiskReads()/detectDiskWrites() открива потенциални ANR в етапа на разработка. В Debug компилация задайте penaltyDeath — всяко нарушение ще доведе до незабавен срив и разработчикът ще види проблема преди комитване.

Firebase Performance Monitoring за производствени метрики

Firebase Performance следи времето за изпълнение на ключови операции и показва кои сценарии надхвърлят прага на ANR. Настройте персонализирани проследявания за всеки екран и мрежова заявка. Ако времето за изпълнение надвишава 3 секунди — това е потенциален ANR, който изисква оптимизация.

Тестване със закъснения на мрежа и диск

Симулирайте бавни условия: ограничете скоростта на мрежата чрез Network Link Conditioner на iOS или Android Emulator. Забавете четенето от диска чрез емулация на бавна памет. ANR често се появява точно при такива условия, на бързите устройства на разработчика не е видим.

  • BroadcastReceiver — винаги използвайте goAsync() за обработка по-дълга от 1 секунда
  • Service — заменете с WorkManager или CoroutineWorker с фонов диспечер
  • ContentProvider — избягвайте мрежа и база данни в onCreate, използвайте lazy-init с WorkManager
  • UI нишка — StrictMode с penaltyDeath в Debug, Firebase Performance за производствен мониторинг

Често задавани въпроси

Защо ANR възниква на Android, но не и на iOS?

Android изрично следи времето за обработка на събития в главната нишка и показва диалог ANR. iOS използва Watchdog, който принудително затваря приложението при замръзване за повече от 10–20 секунди. ANR е характеристика на архитектурата на Android, където няколко компонента (BroadcastReceiver, Service) имат строги таймаути.

Как да намерим traces.txt на устройство без root?

На Android 11+ можете да получите ANR дамп чрез adb shell dumpsys dropbox --print data_app_anr. На Android 10 и по-долу без root няма достъп до /data/anr/traces.txt. Използвайте Firebase Crashlytics — автоматично събира ANR отчети за Android 11+.

Какъв ANR процент се счита за приемлив?

Google Play препоръчва ANR процент под 0,5% — тоест не повече от 5 ANR на 1000 сесии. Приложение с процент над 1% получава предупреждение в Google Play Console и може да бъде скрито от препоръки. В идеалния случай ANR процентът трябва да бъде под 0,1%.

Може ли корутина да причини ANR?

Корутината сама по себе си не блокира нишката. Но ако вътре в корутината се изпълнява runBlocking на главната нишка или корутината е стартирана с Dispatchers.Main и извършва дълга CPU операция — това ще причини ANR. Използвайте Dispatchers.IO за вход-изход и Dispatchers.Default за изчисления.

Как да тестваме ANR в емулатор?

Използвайте Android Emulator с профил „Slow Network“ или напишете тест, който извиква Thread.sleep(6000) на главната нишка. Стартирайте приложението чрез Debug и след 5 секунди ще видите диалог ANR. Проверете дали в logcat се е появил запис за ANR с проследяване.

Обобщение

  • ANR — системно известие на Android при блокиране на главната нишка за повече от 5 секунди или надвишаване на таймаутите на компоненти
  • Таймаути: BroadcastReceiver — 10 с, Service — 20 с, ContentProvider — 15 с, UI — 5 с
  • Диагностика — /data/anr/traces.txt, Firebase Crashlytics, CPU Profiler в Android Studio
  • Отстраняване — WorkManager, goAsync(), Kotlin Coroutines с Dispatchers.IO, ленива инициализация на ContentProvider
  • Профилактика — StrictMode с penaltyDeath, Firebase Performance Monitoring, тестване със закъснения на мрежа
  • Google Play препоръчва ANR процент < 0,5%; при процент > 1% приложението подлежи на ограничения на видимостта
  • Препоръка: конфигурирайте Firebase Crashlytics и Performance за събиране на ANR в продукция и задайте предупреждения при надвишаване на прага от 0,3%

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също