Когда пользователь открывает приложение, нажимает на кнопку — и ничего не происходит несколько секунд, Android начинает считать, что “приложение не отвечает”. Через 5 секунд на главном потоке система показывает диалог:
“Приложение не отвечает. Закрыть?”
Это и есть ANR (Application Not Responding).

Как Android определяет ANR
ANR — это не исключение и не crash. Это watchdog-механизм системы, который следит за тем, что главный поток (UI thread) не блокируется дольше допустимого времени:
Сценарий |
Таймаут |
UI-операция (например, нажатие кнопки) |
5 секунд |
BroadcastReceiver |
10 секунд |
Service |
20 секунд |
Когда время превышено, система пишет traces.txt, где сохраняется stacktrace всех потоков, особенно главного (main).
Типичные причины ANR
Тяжёлая операция в UI-потоке -> Парсинг JSON, чтение из БД, сетевой вызов.
Синхронные вызовы в onCreate / onResume -> Инициализация SDK, feature-флагов, heavy DI.
Долгий BroadcastReceiver или Service -> Например, обработка пуша внутри BroadcastReceiver вместо JobIntentService.
Мёртвые блокировки (deadlocks) -> Несогласованные synchronized или mutex между потоками.
UI thread starvation -> Flood event loop’а — много post() или invalidate().
Как анализировать ANR
1. Через Google Play Console
Раздел Android Vitals → ANRs
Фильтры по версии, устройству, стеку.
2. Через traces.txt
Файл находится по пути: /data/anr/traces.txt или в логе: E/ActivityManager: ANR in <package>
3. Через Firebase / Sentry
Подключите anr мониторинг (Performance Monitoring / ANR Handler)
Можно собирать stacktrace в реальном времени и привязывать к аналитическим событиям.
Best Practices: как не попасть в ANR
. Держите UI-поток чистым
Все тяжёлые операции → Dispatchers.IO или Default.
Пример:
viewModelScope.launch(Dispatchers.IO) {
val result = repository.loadData()
withContext(Dispatchers.Main) { updateUi(result) }
}
2. Не инициализируйте SDK синхронно
Любые внешние SDK, Firebase, Remote Config, Ads — инициализировать асинхронно или через App Startup.
3. Избегайте runBlocking и Thread.sleep()
Особенно в onCreate и onResume.
Вместо этого — suspend функции и delay().
4. Избегайте deadlock
Никогда не держите synchronized между main и background thread.
Используйте Mutex и withLock.
Библиотеки и инструменты для работы с ANR
ANR‑WatchDog
Что это: простая библиотека-watchdog, которая запускает отдельный поток, ставит задачу на UI-потоке и проверяет, был ли UI-поток заблокирован дольше заданного таймаута.
Преимущества:
Быстро подключается (new ANRWatchDog().start();)
-
При срабатывании выдаёт исключение ANRError с снепшотом всех потоков и стеков — удобно передать в Crashlytics или другой репортинг.
Как использовать: можно как дополнительный внутренний контроль, особенно полезен в debug/alpha-сборках, чтобы поймать “потенциальные” ANR-ситуации до того, как они попадут в продакшн.
ANR‑Spy
Что это: библиотека, ориентированная на обнаружение блокировок UI-потока (“приближающихся ANR”), с возможностью интеграции с Firebase Crashlytics и отправки событий перед тем, как система покажет диалог ANR.
Преимущества:
Позволяет задать свой таймаут (например, 3-4 секунд) и фиксировать блокировки.
-
Можно настроить “раннее предупреждение” — сработать до того, как Google Play сочтёт это плохим поведением.
Минусы / моменты:
Это не “официальный” механизм системы, может не покрывать все случаи ANR на всех версиях Android.
-
Требует настройки: интеграция с репортингом, сбор стеков.
Когда использовать: как часть internal monitoring SDK, особенно если хочешь ловить “почти ANR” и реагировать до того, как пользователь увидит диалог.
Firebase Crashlytics (и встроенный ANR-репортинг)
Что это: не библиотека исключительно для ANR, но мощный инструмент для отчётности и диагностики ANR-событий в продакшн-приложениях. Документация подробно описывает, как Crashlytics маркирует потоки с тегами Triggered ANR, Deadlocked и помогает разобраться с причинами.
Почему стоит:
Удобно интегрируется с остальными crash/bug-репортами — один канал мониторинга для всех ошибок, включая ANR.
-
Позволяет связывать ANR с конкретными версиями, устройствами, и видеть статистику.
Лучшее применение: сочетать с internal monitoring (например, ANR-WatchDog или ANR-Spy) + визуализацией (через ClickHouse → Grafana) + линией репортов в Crashlytics.
Как выбрать и комбинировать библиотеки
Цель |
Инструмент |
Почему |
Обнаружить блокировки UI-потока до ANR |
ANR-Spy |
Позволяет оперативно реагировать |
Поддержка мониторинга в debug/internal сборках |
ANR-WatchDog |
Лёгкая и быстрая проверка |
Сбор статистики ANR в продакшн, репорты |
Firebase Crashlytics |
Интеграция + аналитика |
Визуализация и дашборд (не библиотека, но важно) |
ClickHouse + Grafana |
Связь с бизнес-метриками |
Рекомендация:
Включи ANR-WatchDog в debug/alpha-сборках — пусть ранние проверки ловят потенциальные блокировки.
В продакшн-версии подключи ANR-Spy + Crashlytics — чтобы фиксировать и анализировать реальные случаи.
Собирай метрики (ANR rate, block time, версия) в вашу систему (ClickHouse) и выводи в дашборде Grafana. Это даёт вам “радар” производительности и связь с бизнес-метриками.
Как обучить тестировщиков находить ANR
Одна из самых частых проблем — тестировщики замечают “зависание”, но не понимают, что это ANR, и не фиксируют его корректно.
Задача разработчика — дать QA понятный чек-лист и инструменты, чтобы они могли не просто заметить фриз, а воспроизвести, зафиксировать и отправить диагностические данные.
1. Как отличить ANR от обычного лага
Признак |
ANR |
Просто лаг |
Интерфейс полностью “застыл”, кнопки не нажимаются |
✅ |
⚠️ может реагировать |
Через 5–10 секунд появляется системное окно “Приложение не отвечает” |
✅ |
❌ |
После этого приложение закрывается или “оживает” |
✅ |
⚠️ иногда да |
В логах есть “ANR in com.example.app” |
✅ |
❌ |
2.Как правильно заводить баг - Пример шаблона тикета для QA:
Название: [ANR] Зависание экрана PDP после открытия карточки товара
Шаги:
Открыть приложение
Перейти в “Категории → Телефоны”
Выбрать любой товар
Наблюдать зависание 5–6 секунд
Ожидаемый результат: экран отображается мгновенно.
Фактический результат: приложение не реагирует, через 5 секунд — системный диалог ANR.
Дополнительно:
traces.txt из bugreport
версия приложения
устройство и Android API
лог “E/ActivityManager: ANR in …”
Обучение QA команде
Проведите короткий воркшоп:
Объяснить механику ANR (5s / 10s / 20s таймаут)
Показать примеры на тестовом экране — искусственно заблокировать Thread.sleep(6000)
Научить собирать bugreport и логи
Объяснить бизнес-ценность: ANR = потерянная сессия пользователя
Как встроить в QA-процессы
Этап |
Действие |
Ответственный |
Smoke тестирование |
Проверить ключевые экраны на лаги > 4 сек |
QA |
Regression |
Проверить старые ANR-тикеты перед релизом |
QA Lead |
Post-release |
Отслеживать новые ANR в Crashlytics / Grafana |
QA + Dev |
Еженедельный отчёт |
ANR rate на 1000 сессий |
QA Analyst |
Как связать ANR с бизнес-метриками
ANR = снижение session length и retention.
Пользователь, увидевший ANR, с вероятностью 60 % не откроет приложение в течение 7 дней.
ANR rate > 0.47 % — Google Play может понизить внутренний рейтинг качества.
Поэтому снижение ANR rate — это инвестиция в удержание пользователей.
Интеграция с Performance Dashboard
Если у вас уже есть дашборд по производительности (например, в Grafana), добавьте:
ANR rate per screen / per team
Avg UI thread block time
Correlation с событиями (например, “ANR → exit”)
SQL-пример для ClickHouse:
SELECT
screen_name,
countIf(event_name = 'anr_detected') / count() AS anr_rate,
quantileTDigest(0.9)(block_time_ms) AS p90_block_time
FROM app_performance
GROUP BY screen_name
ORDER BY anr_rate DESC
Выводы
ANR — это не просто “фриз”, это потерянный пользователь.
Главный поток должен быть свободен и легок, как good UX.
Мониторьте, анализируйте, автоматизируйте.
И помните: “ANR — это crash, только тихий.”