ANR в Android: що це, причини та методи усунення

Автор: IT Sectr Опубліковано: 2026-07-28 Час читання: 9 хв

ANR (Application Not Responding) — це системне сповіщення Android, яке з'являється, коли додаток не реагує на введення протягом 5 секунд. На відміну від глюків (логічні помилки без блокування UI) та лагів (уповільнення без повної зупинки), ANR — це критична несправність, яку фіксує операційна система: Android відображає діалог «Додаток не відповідає» з пропозицією закрити або зачекати. Згідно з Android Vitals Documentation, додатки з ANR rate вище 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 rate — відсоток сесій з 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 при запуску додатка. Рішення: lazy-ініціалізація, винесення важких операцій в 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. На часовій шкалі буде видно, які методи виконувалися в main thread в момент зависання.

Приклад інтеграції 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() в будь-якому контексті — це синхронне блокування поточного потоку.

Lazy-ініціалізація 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 rate вважається прийнятним?

Google Play рекомендує ANR rate менше 0.5% — тобто не більше 5 ANR на 1000 сесій. Додаток з rate вище 1% отримує попередження в Google Play Console та може бути прихований з рекомендацій. В ідеалі ANR rate повинен бути нижче 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, lazy-ініціалізація ContentProvider
  • Профілактика — StrictMode з penaltyDeath, Firebase Performance Monitoring, тестування з затримками мережі
  • Google Play рекомендує ANR rate < 0.5%; при rate > 1% додаток підпадає під обмеження видимості
  • Рекомендація: налаштуйте Firebase Crashlytics та Performance для збору ANR в продакшні та встановіть алерти при перевищенні порогу 0.3%

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також