ANR w Android: co to jest, przyczyny i metody usuwania

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

ANR (Application Not Responding) — to systemowe powiadomienie Androida, które pojawia się, gdy aplikacja nie reaguje na wprowadzanie danych przez 5 sekund. W przeciwieństwie do glitchy (błędy logiczne bez blokowania UI) i lagów (spowolnienie bez całkowitego zatrzymania), ANR to krytyczna awaria rejestrowana przez system operacyjny: Android wyświetla okno dialogowe „Aplikacja nie odpowiada” z propozycją zamknięcia lub oczekiwania. Według Android Vitals Documentation, aplikacje ze wskaźnikiem ANR powyżej 0,5% mają obniżoną pozycję w Google Play i mogą być ukryte przed rekomendacjami. Diagnostyka obejmuje analizę /data/anr/traces.txt, użycie StrictMode i profilowanie głównego wątku.

Najważniejsze

  • ANR — systemowe powiadomienie Androida przy blokadzie głównego wątku na ponad 5 sekund, prowadzące do okna dialogowego „Aplikacja nie odpowiada”
  • Główne przyczyny — blokada głównego wątku (BroadcastReceiver, Service), deadlock między wątkami, długa operacja w ContentProvider
  • Diagnostyka — analiza /data/anr/traces.txt, Android Studio Profiler, Firebase Performance Monitoring
  • Usuwanie — przenoszenie zadań do WorkManager, używanie Kotlin Coroutines z Dispatchers.IO, StrictMode do wczesnego wykrywania
  • Profilaktyka — ograniczenie czasu BroadcastReceiver do 10 sekund, Service do 20 sekund, ContentProvider do 15 sekund

Czym jest ANR w Android

ANR (Application Not Responding) — to mechanizm ochrony użytkownika w Androidzie, który uruchamia się, gdy aplikacja przestaje reagować na wprowadzanie danych. System śledzi czas przetwarzania zdarzeń: jeśli BroadcastReceiver nie kończy onReceive w ciągu 10 sekund, Service nie zwraca się z onCreate w ciągu 20 sekund, a ContentProvider nie odpowiada w ciągu 15 sekund — Android generuje ANR.

Jak ANR wygląda dla użytkownika

Kiedy występuje ANR, Android wyświetla systemowe okno dialogowe nad wszystkimi oknami: „Aplikacja nie odpowiada. Zamknąć ją czy poczekać?”. Użytkownik może zamknąć aplikację lub poczekać na jej odzyskanie. Jeśli ANR powtarzają się często, użytkownik usuwa aplikację. Google Play uwzględnia wskaźnik ANR — procent sesji z ANR — w algorytmach rankingu.

Różnica między ANR a zawieszaniem się na iOS

Na iOS nie ma odpowiednika ANR z systemowym oknem dialogowym. Zamiast tego Apple używa Watchdog, który kończy proces aplikacji kodem 0x8badf00d. Użytkownik nie widzi okna dialogowego — aplikacja po prostu zamyka się do ekranu głównego. To sprawia, że ANR na Androidzie jest bardziej zauważalny dla użytkownika, ale daje systemowi więcej informacji do diagnostyki.

Główne przyczyny ANR

ANR występuje, gdy system śledzi limit czasu dla jednego z czterech typów komponentów. Każdy komponent ma swój limit czasu.

Blokada w BroadcastReceiver

BroadcastReceiver wykonuje się w głównym wątku. Jeśli onReceive uruchamia synchroniczne żądanie sieciowe, długą operację zapisu do bazy danych lub oczekuje na blokadę — po 10 sekundach pojawia się ANR. Rozwiązanie: używaj goAsync() i WorkManager do przetwarzania w tle. Typowy scenariusz — otrzymanie powiadomienia Push z FCM i synchroniczne zapisywanie w Room.

Długa operacja w Service

Service.onCreate i Service.onStartCommand mają limit 20 sekund. Jeśli serwis uruchamia ciężką inicjalizację (ładowanie bibliotek, odczyt konfiguracji z sieci) w głównym wątku — ANR jest nieunikniony. Używaj IntentService (przestarzały) lub WorkManager do gwarantowanego wykonania w wątku tła.

ContentProvider z długą inicjalizacją

ContentProvider.onCreate wykonuje się przed wywołaniem Application.onCreate i ma limit 15 sekund. Jeśli provider wykonuje migrację bazy danych, ładowanie słowników lub inicjalizację SDK z sieci — powoduje to ANR przy uruchamianiu aplikacji. Rozwiązanie: lazy-inicjalizacja, przeniesienie ciężkich operacji do WorkManager.

  • BroadcastReceiver — 10 sekund na onReceive; używaj goAsync() do przetwarzania w tle
  • Service — 20 sekund na onCreate/onStartCommand; używaj WorkManager lub CoroutineWorker
  • ContentProvider — 15 sekund na onCreate; przenieś inicjalizację do Application.onCreate z opóźnionym uruchomieniem
  • Wątek UI — 5 sekund bez przetwarzania zdarzeń; każda blokada dłuższa niż 5 sekund powoduje ANR

Jak diagnozować ANR

Android udostępnia kilka narzędzi do analizy ANR: od logów systemowych po specjalistyczne biblioteki.

Analiza traces.txt

Przy każdym ANR Android zapisuje plik /data/anr/traces.txt z zrzutem stosów wszystkich wątków aplikacji. Znajdź wątek „main” — ostatnia metoda w stosie wskazuje przyczynę. Typowe wzorce: Thread.sleep(), InputStream.read(), BinderProxy.transact(). Do wyodrębnienia pliku z urządzenia użyj adb z uprawnieniami superużytkownika.

Firebase Crashlytics z raportami ANR

Firebase Crashlytics automatycznie zbiera ANR i wyświetla je na pulpicie wraz ze śledzeniem. Dla Android 11+ raporty ANR przychodzą z pełnym stosem głównego wątku. Integracja wymaga dodania zależności i inicjalizacji FirebaseApp w Application.onCreate.

Android Studio Profiler ze śledzeniem wątków

CPU Profiler w Android Studio pozwala zapisać śledzenie działania aplikacji i zobaczyć, które metody zajmują czas procesora. Włącz „Record with method traces” i odtwórz scenariusz wywołujący ANR. Na osi czasu będzie widoczne, które metody wykonywały się w głównym wątku w momencie zawieszenia.

Przykład integracji Firebase Crashlytics do zbierania ANR na Androidzie:

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

Metody usuwania ANR

Usuwanie ANR to przede wszystkim przeniesienie wszystkich długich operacji z głównego wątku do tła. Rozważmy konkretne techniki dla każdego typu komponentu.

Używanie WorkManager do zadań w tle

WorkManager — rekomendowane przez Google rozwiązanie do pracy w tle. Gwarantuje wykonanie zadania w wątku tła z uwzględnieniem stanu urządzenia. W przeciwieństwie do Service, WorkManager nie blokuje głównego wątku i jest odporny na ponowne uruchomienie aplikacji. Dla BroadcastReceiver użyj goAsync() i przekaż wynik PendingResult do WorkManager.

Kotlin Coroutines z odpowiednimi dyspozytorami

Uruchamiaj wszystkie żądania sieciowe, pracę z bazą danych i operacje plikowe z Dispatchers.IO. Główny wątek powinien tylko aktualizować UI. Używaj viewModelScope do automatycznego anulowania coroutines przy zniszczeniu Activity. Unikaj runBlocking() w jakimkolwiek kontekście — to synchroniczna blokada bieżącego wątku.

Lazy-inicjalizacja ContentProvider

Jeśli ContentProvider wykonuje długą inicjalizację, użyj mechanizmu opóźnionego ładowania: stwórz provider, który zwraca dane natychmiast, a ciężką inicjalizację uruchom przez WorkManager z opóźnieniem. Zapobiega to ANR przy uruchamianiu aplikacji, gdy system jest najbardziej wrażliwy na opóźnienia.

Przykład prawidłowego użycia BroadcastReceiver z goAsync w 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()
    }
}

Profilaktyka ANR w rozwoju

Najlepszym sposobem walki z ANR jest zapobieganie ich pojawianiu się na etapie rozwoju poprzez narzędzia i rozwiązania architektoniczne.

StrictMode do wykrywania blokad głównego wątku

StrictMode z włączonymi politykami detectNetwork() i detectDiskReads()/detectDiskWrites() wykrywa potencjalne ANR na etapie rozwoju. W kompilacji Debug ustaw penaltyDeath — każde naruszenie doprowadzi do natychmiastowego upadku, a programista zobaczy problem przed zatwierdzeniem.

Firebase Performance Monitoring dla metryk produkcyjnych

Firebase Performance śledzi czas wykonania kluczowych operacji i pokazuje, które scenariusze przekraczają próg ANR. Skonfiguruj niestandardowe śledzenie dla każdego ekranu i żądania sieciowego. Jeśli czas wykonania przekracza 3 sekundy — to potencjalny ANR wymagający optymalizacji.

Testowanie z opóźnieniami sieci i dysku

Symuluj wolne warunki: ogranicz prędkość sieci przez Network Link Conditioner na iOS lub Android Emulator. Spowolnij odczyt z dysku przez emulację wolnej pamięci. ANR często pojawiają się właśnie w takich warunkach, na szybkich urządzeniach programisty nie są widoczne.

  • BroadcastReceiver — zawsze używaj goAsync() do przetwarzania dłuższego niż 1 sekunda
  • Service — zastąp WorkManager lub CoroutineWorker z dyspozytorem tła
  • ContentProvider — unikaj sieci i bazy danych w onCreate, użyj lazy-init z WorkManager
  • Wątek UI — StrictMode z penaltyDeath w Debug, Firebase Performance dla monitorowania produkcyjnego

Często zadawane pytania

Dlaczego ANR pojawia się na Androidzie, ale nie na iOS?

Android jawnie śledzi czas przetwarzania zdarzeń na głównym wątku i wyświetla okno dialogowe ANR. iOS używa Watchdog, który wymusza zamknięcie aplikacji po zawieszeniu na ponad 10–20 sekund. ANR to cecha architektury Androida, gdzie kilka komponentów (BroadcastReceiver, Service) ma sztywne limity czasu.

Jak znaleźć traces.txt na urządzeniu bez root?

Na Android 11+ można uzyskać zrzut ANR przez adb shell dumpsys dropbox --print data_app_anr. Na Android 10 i niżej bez root dostępu do /data/anr/traces.txt nie ma. Użyj Firebase Crashlytics — zbiera raporty ANR automatycznie dla Android 11+.

Jaki wskaźnik ANR uważa się za akceptowalny?

Google Play zaleca wskaźnik ANR poniżej 0,5% — czyli nie więcej niż 5 ANR na 1000 sesji. Aplikacja ze wskaźnikiem powyżej 1% otrzymuje ostrzeżenie w Google Play Console i może być ukryta przed rekomendacjami. Idealnie wskaźnik ANR powinien być poniżej 0,1%.

Czy coroutine może spowodować ANR?

Coroutine sama w sobie nie blokuje wątku. Ale jeśli wewnątrz coroutine wykonywany jest runBlocking na głównym wątku lub coroutine jest uruchomiona z Dispatchers.Main i wykonuje długą operację CPU — to spowoduje ANR. Używaj Dispatchers.IO dla wejścia-wyjścia i Dispatchers.Default dla obliczeń.

Jak testować ANR w emulatorze?

Użyj Android Emulator z profilem „Slow Network” lub napisz test, który wywołuje Thread.sleep(6000) na głównym wątku. Uruchom aplikację przez Debug i po 5 sekundach zobaczysz okno dialogowe ANR. Sprawdź, czy w logcat pojawił się wpis o ANR ze śledzeniem.

Podsumowanie

  • ANR — systemowe powiadomienie Androida przy blokadzie głównego wątku na ponad 5 sekund lub przekroczeniu limitów czasu komponentów
  • Limity czasu: BroadcastReceiver — 10 s, Service — 20 s, ContentProvider — 15 s, UI — 5 s
  • Diagnostyka — /data/anr/traces.txt, Firebase Crashlytics, CPU Profiler w Android Studio
  • Usuwanie — WorkManager, goAsync(), Kotlin Coroutines z Dispatchers.IO, lazy-inicjalizacja ContentProvider
  • Profilaktyka — StrictMode z penaltyDeath, Firebase Performance Monitoring, testowanie z opóźnieniami sieci
  • Google Play zaleca wskaźnik ANR < 0,5%; przy wskaźniku > 1% aplikacja podlega ograniczeniom widoczności
  • Zalecenie: skonfiguruj Firebase Crashlytics i Performance do zbierania ANR w produkcji i ustaw alerty przy przekroczeniu progu 0,3%

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ż