ANR w rozwoju aplikacji Android — co to jest, przyczyny i sposoby naprawy

Autor: IT Sectr Opublikowano: 2026-03-28 Czas czytania: 9 min

ANR (Application Not Responding) — to systemowe powiadomienie Androida, które pojawia się, gdy aplikacja przestaje reagować na wprowadzane przez użytkownika dane na dłużej niż 5 sekund. Według Android Developers, główną przyczyną są długotrwałe operacje na głównym wątku, blokujące przetwarzanie dotknięć i renderowanie interfejsu. Zrozumienie mechanizmów ANR jest niezbędne dla każdego programisty Androida, aby tworzyć responsywne aplikacje.

Najważniejsze

  • ANR — systemowe ostrzeżenie Androida przy zawieszeniu aplikacji dłuższym niż 5 sekund
  • Główny wątek (wątek UI) — jedyne miejsce, gdzie blokada prowadzi do ANR
  • InputDispatcher — komponent systemu rejestrujący opóźnienie wejścia i inicjujący ANR
  • traces.txt — kluczowy plik do diagnozowania przyczyny zawieszenia na urządzeniu
  • StrictMode — wbudowane narzędzie Androida do wykrywania długotrwałych operacji na wątku UI

Co to jest ANR

ANR (Application Not Responding) — to okno dialogowe systemu operacyjnego Android, które pojawia się, gdy aplikacja przestaje odpowiadać na wprowadzane przez użytkownika dane. System śledzi czas przetwarzania zdarzeń przez InputDispatcher: jeśli dotknięcie lub naciśnięcie przycisku nie zostanie obsłużone w ciągu 5 sekund, Android wyświetla dialog z propozycją zamknięcia lub poczekania na aplikację.

Mechanizm ANR chroni doświadczenie użytkownika przed zawieszonymi aplikacjami. Android nie pozwala jednej aplikacji blokować całego systemu — w przeciwieństwie do systemów Desktop, platforma mobilna wymusza ograniczenie czasu przetwarzania zdarzeń. BroadcastReceiver ma limit 10 sekund, a usługa foreground — 20 sekund.

ANR NIE jest wyjątkiem w kodzie — to mechanizm systemowy na poziomie procesów Linuxa. Android wysyła sygnał SIGQUIT do procesu, po czym system zapisuje stos wywołań wszystkich wątków do pliku traces.txt. Programista otrzymuje ANR nie jako catch-wyjątek, ale jako raport po restarcie aplikacji. Na Androidzie 11+ pojawiło się API ApplicationExitInfo, które pozwala programowo uzyskać przyczynę zakończenia procesu, w tym ANR — upraszcza to zbieranie statystyk bez ręcznego parsowania traces.txt.

Główne przyczyny ANR

Pięć kategorii operacji stabilnie prowadzi do ANR w aplikacjach Android. Każda z nich blokuje główny wątek, uniemożliwiając systemowi przetwarzanie zdarzeń wejściowych i przerysowywanie ekranu.

Żądania sieciowe na głównym wątku

Synchroniczne żądania HTTP wykonane na wątku UI — najczęstsza przyczyna ANR u początkujących programistów. Nawet szybkie żądanie do serwera może zająć 1–3 sekundy, a przy słabym połączeniu — 30 sekund i więcej. Android jawnie zabrania operacji sieciowych na głównym wątku od API 11, wyrzucając NetworkOnMainThreadException.

Używaj Coroutines lub RxJava do asynchronicznych wywołań. Korutyny z dyspozytorem Dispatchers.IO wykonują żądanie w tle, a wynik przekazują na główny przez Dispatchers.Main. To całkowicie eliminuje blokowanie wątku UI przez operacje sieciowe.

kotlin
fun fetchUserData() {
    CoroutineScope(Dispatchers.Main).launch {
        val result = withContext(Dispatchers.IO) {
            api.getUserData() // operacja w tle
        }
        updateUI(result) // wynik na głównym wątku
    }
}

Intensywne obliczenia na wątku UI

Przetwarzanie dużych tablic danych, parsowanie JSON lub XML, praca z bitmapami bezpośrednio na głównym wątku — druga pod względem częstotliwości przyczyna ANR. Nawet 300 milisekund ciągłej pracy wątku UI bez powrotu do pętli zdarzeń powoduje zauważalne opóźnienie renderowania, a wartość graniczna 5 sekund jest rejestrowana jako ANR.

WorkManager i usługi tła są przeznaczone do przenoszenia ciężkich obliczeń z głównego wątku. Używaj AsyncTask (przestarzałe), ListenableFuture lub Kotlin Flow do przesyłania danych porcjami, nie blokując UI.

Blokady synchronizacji i Deadlock

Deadlock występuje, gdy dwa wątki trzymają blokady i czekają na siebie nawzajem. Jeśli jeden z wątków jest głównym, system rejestruje ANR dokładnie po 5 sekundach. Thread.join(), CountDownLatch.await() i blokady synchronized wywoływane z wątku UI niosą ryzyko blokady.

Unikaj wszelkich blokujących operacji na głównym wątku. Zamiast synchronized używaj ConcurrentHashMap, zamiast Thread.join() — korutyn z async/await. Ta zasada obowiązuje dla każdego języka w Androidzie: Java, Kotlin lub C++ przez JNI.

Długa praca BroadcastReceiver

BroadcastReceiver domyślnie wykonuje się na głównym wątku. Jeśli onReceive() jest zajęty dłużej niż 10 sekund, Android wyświetla ANR. Ładowanie danych z bazy danych lub sieci wewnątrz onReceive to gwarantowana droga do zawieszenia.

Używaj goAsync() wewnątrz BroadcastReceiver do przełączenia na wątek tła albo registerReceiver z getBackgroundBroadcastReceiver(). Pozwala to na przetwarzanie zdarzeń bez blokowania UI.

ContentProvider i SQLite na głównym wątku

Ciężkie zapytania do ContentProvider lub bezpośrednia praca z SQLite na wątku UI — mniej oczywista, ale częsta przyczyna ANR. Podczas migracji bazy danych lub wsadowego wstawiania tysięcy rekordów czas wykonania może przekroczyć 5-sekundowy limit.

Przenoś wszystkie operacje na bazie danych do wątków tła przez Room z suspend-funkcjami. Room automatycznie sprawdza, czy zapytanie nie jest wykonywane na głównym wątku i wyrzuca wyjątek w przypadku naruszenia.

Jak diagnozować ANR

Diagnozowanie ANR różni się od debugowania zwykłych wyjątków — nie można złapać ANR w try-catch. Głównym źródłem informacji jest plik traces.txt, który Android tworzy w momencie zawieszenia.

traces.txt zawiera stos wywołań wszystkich wątków aplikacji w momencie ANR. Aby odczytać plik z rzeczywistego urządzenia, wykonaj polecenie adb bugreport, które zbiera pełny raport systemu, w tym wszystkie ANR z ostatniego czasu. Dla emulatora plik jest dostępny w /data/anr/traces.txt. Stos wywołań pokazuje, która metoda wykonywała się na głównym wątku w momencie blokady.

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

Google Play Console udostępnia sekcję ANR & Crash z zagregowanymi raportami i częstotliwościami błędów. Dla każdego ANR pokazany jest stos wywołań i statystyki według urządzeń: model, wersja Androida, region. Pozwala to zidentyfikować ANR, które zależą od konkretnych urządzeń lub wersji systemu.

Android Studio od 2021 roku zawiera ANR Watchdog w profilatorze. Automatycznie zapisuje zrzut wątków, jeśli główny wątek nie odpowiada dłużej niż progowy czas. Narzędzie pokazuje oś czasu zdarzeń: jakie operacje były uruchamiane, jakie metody były wykonywane i na którym etapie nastąpiła blokada.

Jak zapobiegać ANR

Profilaktyka ANR opiera się na jednej fundamentalnej zasadzie: główny wątek powinien tylko obsługiwać zdarzenia UI. Każda operacja trwająca dłużej niż 16 milisekund (czas jednej klatki) powinna być wykonywana w wątku tła.

StrictMode — automatyczne sprawdzanie

StrictMode — wbudowane narzędzie Androida do wykrywania potencjalnych ANR na etapie rozwoju. Włącz je w Application.onCreate() z flagami dla operacji dyskowych i sieciowych. W przypadku naruszenia StrictMode wyrzuca wyjątek lub zapisuje w logcat.

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

Wzorce asynchroniczne: Coroutines i RxJava

Kotlin Coroutines — standardowy sposób asynchronicznej pracy w nowoczesnych aplikacjach Android. Główna zasada: operacje wejścia-wyjścia wykonują się na Dispatchers.IO, wynik przekazywany jest na Dispatchers.Main do aktualizacji UI. Dla scenariuszy Flow używaj Dispatchers.Default do zadań intensywnie obciążających CPU.

RxJava pozostaje popularny w projektach legacy. subscribeOn(Schedulers.io()) i observeOn(AndroidSchedulers.mainThread()) — minimalny zestaw do zapobiegania ANR. Główna zasada jest taka sama: żaden Observable ani Flowable nie powinien emitować danych z głównego wątku.

Monitoring w produkcji

Firebase Crashlytics od wersji SDK 18.4.0 obsługuje monitorowanie ANR „od razu po wyjęciu z pudełka“. Dla Android 11+ Crashlytics używa systemowego API ApplicationExitInfo, które dostarcza dokładną przyczynę zakończenia: ANR, Crash lub zabicie przez system. Włącz niestandardowe klucze z parametrami ekranu i stanu dla kontekstowej analizy.

Narzędzia do wykrywania ANR

Pięć narzędzi pokrywa wszystkie etapy pracy z ANR: od debugowania na stacji roboczej po monitoring w produkcji. Każde narzędzie rozwiązuje swoje zadanie i dostarcza dane dla różnych scenariuszy.

NarzędziePrzeznaczenieFormat danych
StrictModeWykrywanie na etapie rozwojuLogcat / Exception
ANR Watchdog (Android Studio)Śledzenie w czasie rzeczywistymThread dump + timeline
Google Play ConsoleZagregowana statystykaANR rate + stack traces
Firebase CrashlyticsMonitoring produkcyjnyApplicationExitInfo
adb bugreportPełny raport systemowytraces.txt + logcat + dmesg

Każde narzędzie ma swoją niszę: StrictMode łapie oczywiste naruszenia na wczesnych etapach, Crashlytics pokazuje rzeczywistą częstotliwość ANR u użytkowników, a adb bugreport daje maksymalnie pełny obraz dla skomplikowanych przypadków. Łącz je dla pełnego pokrycia.

Firebase Performance Monitoring

Firebase Performance śledzi czas odpowiedzi wątku UI i automatycznie tworzy ślady dla podejrzanie długich operacji. Jeśli główny wątek blokuje się na więcej niż 500 ms, Performance rejestruje niestandardowy ślad z nazwą metody-sprawcy. Pozwala to wykrywać scenariusze ANR bez udziału użytkownika i zanim staną się krytyczne.

Integracja z Firebase Crashlytics daje pełny obraz: Performance pokazuje spowolnienia przed ANR, a Crashlytics — sam fakt zawieszenia. Skonfiguruj alerty w Firebase Console na zdarzenie ANR rate powyżej 0.1%, a będziesz otrzymywać powiadomienia o nowych problemach zanim pojawią się masowe skargi użytkowników.

Często zadawane pytania

Czym ANR różni się od Crash?

ANR — to zawieszenie, przy którym aplikacja nie odpowiada, ale pozostaje w pamięci. Crash — całkowite awaryjne zakończenie z wyjściem z procesu. ANR można „przeżyć“, jeśli system lub użytkownik poczekają na odpowiedź, a Crash zawsze kończy aplikację.

Czy można złapać ANR przez try-catch?

Nie. ANR — to nie wyjątek Java/Kotlin, a sygnał systemu na poziomie procesów (SIGQUIT). Programista nie może go obsłużyć w kodzie aplikacji. Jedynym sposobem reagowania na ANR jest analizowanie raportów po restarcie.

Dlaczego ANR pojawia się na jednych urządzeniach, a na innych nie?

Wydajność urządzenia, wersja Androida, obciążenie CPU i liczba procesów tła wpływają na prawdopodobieństwo ANR. Na słabych urządzeniach ta sama operacja może wykonywać się 2–3 razy dłużej, przekraczając 5-sekundowy limit.

Jaki jest limit czasu BroadcastReceiver do ANR?

10 sekund dla zwykłego BroadcastReceiver w onReceive(). Dla usług foreground limit wynosi 20 sekund, a dla ContentProvider — nie ma wyraźnego limitu, ale blokada głównego wątku dłuższa niż 5 sekund i tak wywołuje ANR.

Co zrobić, jeśli ANR zdarza się rzadko i nie można go odtworzyć?

Włącz StrictMode we wszystkich debug-buildach, dodaj monitoring przez Firebase Crashlytics i używaj adb bugreport, gdy ANR wystąpi. Nieregularne ANR często są związane z warunkami wyścigu (race condition) lub specyficznymi stanami sieci.

Podsumowanie

  • ANR — systemowy mechanizm Androida, uruchamiany przy blokadzie głównego wątku dłuższej niż 5 sekund
  • Główny wątek powinien zajmować się tylko UI — wszystkie pozostałe operacje przenoszone są do wątków tła
  • Diagnostyka ANR prowadzona jest przez traces.txt, Google Play Console i Firebase Crashlytics
  • StrictMode wykrywa potencjalne ANR na etapie rozwoju bez uruchamiania na rzeczywistym urządzeniu
  • Coroutines z Dispatchers.IO — standardowy sposób asynchronicznej pracy w nowoczesnych projektach Android
  • BroadcastReceiver wymaga goAsync() lub rejestratora tła do pracy dłuższej niż 10 sekund
  • ANR w produkcji monitoruje się przez Crashlytics i wbudowane API ApplicationExitInfo na Android 11 i wyżej

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również