Błędy ANR

Gdy wątek UI aplikacji na Androida jest zablokowany zbyt długo, pojawia się błąd „Aplikacja nie odpowiada” (ANR). Android Vitals śledzi i raportuje dane o błędach ANR w Konsoli Google Play, aby pomóc Ci monitorować stabilność i szybkość działania aplikacji na różnych urządzeniach.

Dane i progi Android Vitals

Android Vitals może pomóc Ci monitorować i zmniejszać częstotliwość błędów ANR w aplikacji. Android Vitals mierzy kilka rodzajów częstotliwości błędów ANR:

  • Częstotliwość błędów ANR: odsetek liczby aktywnych użytkowników dziennie, u których wystąpił dowolny typ błędu ANR.
  • Częstotliwość błędów ANR widocznych dla użytkowników: odsetek liczby aktywnych użytkowników dziennie, u których wystąpił co najmniej 1 błąd ANR widoczny dla użytkowników. Obecnie za błędy ANR widoczne dla użytkowników uznawane są tylko błędy ANR typu Input dispatching timed out.
  • Częstotliwość wielokrotnych błędów ANR: odsetek aktywnych użytkowników dziennie, u których wystąpiły co najmniej 2 błędy ANR.

Liczba aktywnych użytkowników dziennie to unikalny użytkownik, który korzysta z aplikacji w ciągu 1 dnia na 1 urządzeniu, potencjalnie w ramach wielu sesji. Jeśli użytkownik korzysta z aplikacji na więcej niż 1 urządzeniu w ciągu 1 dnia, każde z tych urządzeń wpłynie na liczbę aktywnych użytkowników w danym dniu.

Częstotliwość błędów ANR widocznych dla użytkowników jest jednym z podstawowych wskaźników, co oznacza, że wpływa na możliwość odkrycia Twojej aplikacji w Google Play. Jest to ważne, ponieważ zliczane błędy ANR występują zawsze, gdy użytkownik korzysta z aplikacji, co powoduje najwięcej zakłóceń.

W przypadku tych danych Google Play określa 2 progi niewłaściwego działania:

  • Próg niewłaściwego działania na poziomie ogólnym: błąd ANR widoczny dla użytkowników wystąpił u co najmniej 0, 47% liczby aktywnych użytkowników dziennie na wszystkich modelach urządzeń.
  • Próg niewłaściwego działania na poziomie urządzenia: błąd ANR widoczny dla użytkowników wystąpił u co najmniej 8% użytkowników dziennie na 1 modelu urządzenia.

Jeśli aplikacja przekracza ogólny próg niewłaściwego działania, prawdopodobnie będzie trudniejsza do odkrycia na wszystkich urządzeniach. Jeśli aplikacja przekracza próg niewłaściwego działania na niektórych urządzeniach, może być trudniej ją znaleźć na tych urządzeniach, a na jej stronie w Sklepie może wyświetlać się ostrzeżenie.

Android Vitals może wysyłać alerty w Konsoli Play, gdy w aplikacji występuje nadmierna liczba błędów ANR.

Więcej informacji o tym, jak Google Play zbiera dane Android Vitals, znajdziesz w dokumentacji Konsoli Play.

Wykrywanie problemu

Jeśli aplikacja działa na pierwszym planie, gdy wystąpi błąd ANR, system wyświetla użytkownikowi okno, jak na rysunku 1. Okno ANR daje użytkownikowi możliwość wymuszenia zamknięcia aplikacji.

Użytkownikowi wyświetliło się okno z błędem ANR.
Rysunek 1. Wyświetlenie użytkownikowi okna z błędem ANR

Błędy ANR są problemem, ponieważ główny wątek aplikacji, który odpowiada za aktualizowanie interfejsu, nie może przetwarzać zdarzeń wejściowych użytkownika ani rysować, co powoduje frustrację użytkownika. Więcej informacji o głównym wątku aplikacji znajdziesz w omówieniu procesów i wątków.

Błąd ANR jest wywoływany w aplikacji, gdy wystąpi jeden z tych warunków:

  • Przekroczenie limitu czasu wysyłania danych wejściowych: jeśli aplikacja nie zareagowała na zdarzenie wejściowe (np. naciśnięcie klawisza lub dotknięcie ekranu) w ciągu 5 sekund.
  • Wykonywanie usługi: jeśli usługa zadeklarowana przez aplikację nie może zakończyć wykonywania metod Service.onCreate i Service.onStartCommand lub Service.onBind w ciągu kilku sekund.
  • Nie wywołano Service.startForeground: jeśli aplikacja używa Context.startForegroundService do uruchomienia nowej usługi na pierwszym planie, ale usługa nie wywołuje startForeground w ciągu 5 sekund.
  • Rozgłaszanie intencji: jeśli BroadcastReceiver nie zakończy się w określonym czasie. Jeśli aplikacja jest aktywna na pierwszym planie, limit czasu wynosi 10 sekund.
  • Interakcje z JobScheduler: jeśli JobService nie powróci z JobService.onStartJob lub JobService.onStopJob w ciągu kilku sekund albo jeśli rozpocznie się zadanie zainicjowane przez użytkownika, a aplikacja nie wywoła JobService.setNotification w ciągu kilku sekund po wywołaniu JobService.onStartJob. W przypadku aplikacji kierowanych na Androida 13 lub starszego błędy ANR są ciche i nie są zgłaszane aplikacji. W przypadku aplikacji kierowanych na Androida 14 lub nowszego błędy ANR są jawne i są zgłaszane aplikacji.

Oprócz Android Vitals możesz używać innych narzędzi do wykrywania błędów ANR w terenie, ale narzędzia innych firm nie mogą zgłaszać błędów ANR na Androidzie 10 (poziom interfejsu API 29) i starszych wersjach.

Diagnozowanie błędów ANR

Podczas diagnozowania błędów ANR warto zwrócić uwagę na kilka typowych wzorców:

  • Aplikacja wykonuje powolne operacje wejścia-wyjścia w wątku głównym.
  • Aplikacja wykonuje długie obliczenia w głównym wątku.
  • Wątek główny wykonuje synchroniczne wywołanie Binder do innego procesu, a ten proces długo nie zwraca odpowiedzi.
  • Wątek główny jest zablokowany i czeka na zsynchronizowany blok długiej operacji, która odbywa się w innym wątku.
  • Wątek główny jest zablokowany przez inny wątek w Twoim procesie lub przez wywołanie binder. Wątek główny nie tylko czeka na zakończenie długiej operacji, ale jest w sytuacji zakleszczenia.

Poniższe techniki mogą pomóc Ci określić przyczynę błędów ANR.

HealthStats

HealthStats dostarcza dane o stanie aplikacji, rejestrując łączny czas użytkownika i systemu, czas pracy procesora, sieć, statystyki radiowe, czas włączenia i wyłączenia ekranu oraz alarmy wybudzenia. Może to pomóc w pomiarze ogólnego wykorzystania procesora i zużycia baterii.

Debugowanie

Debug pomaga sprawdzać aplikacje na Androida podczas ich tworzenia, m.in. śledzić i liczyć alokacje, aby wykrywać zacinanie się i opóźnienia w aplikacjach. Możesz też użyć Debug, aby uzyskać liczniki pamięci środowiska wykonawczego i pamięci natywnej oraz wskaźniki pamięci, które pomogą Ci określić wykorzystanie pamięci przez dany proces.

ApplicationExitInfo

Interfejs ApplicationExitInfo jest dostępny na Androidzie 11 (poziom API 30) i nowszych wersjach. Dostarcza on informacji o przyczynie zamknięcia aplikacji. Obejmuje to błędy ANR, małą ilość pamięci, awarie aplikacji, nadmierne wykorzystanie procesora, przerwy w działaniu aplikacji spowodowane przez użytkownika, przerwy w działaniu aplikacji spowodowane przez system i zmiany uprawnień w czasie działania aplikacji.

Tryb ścisły

Korzystanie z StrictMode pomaga znaleźć przypadkowe operacje wejścia/wyjścia w głównym wątku podczas tworzenia aplikacji. Możesz używać StrictMode na poziomie aplikacji lub aktywności.

Włącz okna błędów ANR w tle

Android wyświetla okna ANR w przypadku aplikacji, które zbyt długo przetwarzają komunikat, tylko wtedy, gdy w Opcjach programisty na urządzeniu włączona jest opcja Pokaż wszystkie błędy ANR. Z tego powodu okna błędów ANR w tle nie zawsze są wyświetlane użytkownikowi, nawet jeśli aplikacja ma problemy z wydajnością.

Profilowanie procesora i śledzenie systemu

Użyj CPU Profilera w Android Studio, aby rejestrować śledzenie systemu i aktywność procesora podczas działania gry. Sprawdzanie głównego wątku Activity wraz z wątkami renderowania, dźwięku i wątkami instancji roboczej silnika gry pomaga wykrywać długie klatki, synchroniczne wczytywanie zasobów i rywalizację o wątki, zanim spowodują one błąd ANR.

Pobieranie pliku logów czasu

Android przechowuje informacje o śladach, gdy wystąpi błąd ANR. W starszych wersjach Androida na urządzeniu znajduje się jeden plik /data/anr/traces.txt. W nowszych wersjach Androida jest kilka plików /data/anr/anr_*. Ślady błędów ANR możesz uzyskać z urządzenia lub emulatora, używając Android Debug Bridge (adb) jako użytkownik root:

adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>

Raport o błędzie możesz wygenerować na urządzeniu fizycznym, korzystając z opcji programisty Zgłoś błąd na urządzeniu lub polecenia adb bugreport na komputerze używanym do programowania. Więcej informacji znajdziesz w artykule Przechwytywanie i odczytywanie raportów o błędach.

Rozwiązywanie problemów

Po zidentyfikowaniu problemu możesz skorzystać ze wskazówek w tej sekcji, aby rozwiązać najczęstsze problemy.

Powolny kod w głównym wątku

Zidentyfikuj miejsca w kodzie, w których główny wątek aplikacji jest zajęty przez ponad 5 sekund. Poszukaj podejrzanych przypadków użycia w grze i spróbuj odtworzyć błąd ANR.

W grach blokady wątku głównego często występują, gdy synchroniczna dekompresja zasobów, kompilacja cieniowania lub intensywna inicjalizacja stanu gry są uruchamiane w głównym wątku Activity Androida (np. wewnątrz wywołań zwrotnych onCreate, onResume lub JNI wywoływanych z wątku UI). Przenieś wykonywanie pętli gry, przetwarzanie zasobów i inicjowanie scen do dedykowanych wątków silnika, renderowania lub wątków instancji roboczej w tle, aby wątek główny mógł przetwarzać dane wejściowe i zdarzenia cyklu życia.

Wejście-wyjście w wątku głównym

Wykonywanie operacji wejścia-wyjścia w wątku głównym jest częstą przyczyną powolnego działania wątku głównego, co może powodować błędy ANR.

Przenieś wszystkie odczyty pakietów zasobów, serializację zapisanych gier, SharedPreferences dostęp i żądania sieciowe z głównego wątku Activity do wątków instancji roboczej w tle, aby opóźnienia pamięci masowej lub sieci nie blokowały wysyłania danych wejściowych.

Zakleszczenia

Zakleszczenie występuje, gdy wątek przechodzi w stan oczekiwania, ponieważ wymagany zasób jest zajęty przez inny wątek, który również oczekuje na zasób zajęty przez pierwszy wątek. Jeśli główny wątek aplikacji znajduje się w takiej sytuacji, prawdopodobnie wystąpią błędy ANR.

W grach blokady i rywalizacja o blokadę często występują między głównym wątkiem Activity Androida (obsługującym cykl życia, powierzchnię lub wywołania zwrotne danych wejściowych) a natywnymi wątkami renderowania, logiki lub dźwięku w języku C lub C++. Unikaj synchronicznego oczekiwania w głównym wątku na blokady silnika natywnego i używaj spójnej kolejności blokad lub kolejek wiadomości bez blokad podczas komunikacji między wątkami JNI i silnika.

Zakleszczenia to dobrze znane zjawisko w informatyce. Istnieją algorytmy zapobiegania zakleszczeniom, których można używać, aby ich unikać.

Więcej informacji znajdziesz w artykułach Zakleszczenie i Algorytmy zapobiegania zakleszczeniom w Wikipedii.

Powolne odbiorniki

Aplikacje mogą reagować na komunikaty, takie jak włączenie lub wyłączenie trybu samolotowego albo zmiana stanu połączenia, za pomocą odbiorników komunikatów. Błąd ANR występuje, gdy aplikacja zbyt długo przetwarza komunikat.

Błąd ANR występuje w tych przypadkach:

  • Odbiornik komunikatów nie zakończył wykonywania metody onReceive w odpowiednim czasie.
  • Odbiornik wywołuje metodę goAsync, ale nie wywołuje metody finish w obiekcie PendingResult.

Aplikacja powinna wykonywać tylko krótkie operacje w metodzie onReceive klasy BroadcastReceiver. Jeśli jednak aplikacja wymaga bardziej złożonego przetwarzania w wyniku komunikatu, należy odroczyć zadanie do wątku instancji roboczej w tle, jeśli ma ono potrwać maksymalnie kilka sekund, lub do WorkManager, jeśli ma potrwać dłużej niż kilka sekund.

GameActivity

Biblioteka GameActivity zmniejszyła liczbę błędów ANR w studiach przypadków gier i aplikacji napisanych w języku C lub C++. Jeśli zastąpisz dotychczasowe działanie natywne biblioteką GameActivity, możesz ograniczyć blokowanie wątku UI i zapobiec niektórym błędom ANR.

Jeśli tworzysz grę w Unity, zapoznaj się z artykułami Debugowanie błędów ANR w grach Unity, Typowe błędy ANR w grach Unity i Symbolizacja awarii i błędów ANR na Androidzie w grach Unity.

Więcej informacji o błędach ANR znajdziesz w artykule Zapewnianie szybkiego działania aplikacji. Więcej informacji o wątkach znajdziesz w artykule Lepsza wydajność dzięki wątkom.