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 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

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