Gdy wątek UI aplikacji na Androida jest zablokowany przez zbyt długi czas, wywoływany jest błąd „Aplikacja nie odpowiada” (ANR). Jeśli aplikacja działa na pierwszym planie, system wyświetla użytkownikowi okno, jak pokazano na ilustracji 1. W oknie błędu ANR użytkownik może wymusić zamknięcie aplikacji.
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 artykule Omówienie 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 odpowiedział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 dokończyć wykonywania
Service.onCreateiService.onStartCommand/Service.onBindw ciągu kilku sekund. Service.startForegroundnie wywołano: jeśli aplikacja używaContext.startForegroundServicedo uruchomienia nowej usługi na pierwszym planie ale usługa nie wywołastartForegroundw ciągu 5 sekund.- Rozgłaszanie intencji: jeśli
BroadcastReceivernie zakończył wykonywania w określonym czasie. Jeśli aplikacja ma jakąkolwiek aktywność na pierwszym planie, ten limit czasu wynosi 5 sekund. JobSchedulerinterakcje: jeśliJobServicenie zwróci wartości zJobService.onStartJoblubJobService.onStopJobw ciągu kilku sekund albo jeśli zadanie zainicjowane przez użytkownika zostanie uruchomione, a aplikacja nie wywołaJobService.setNotificationw ciągu kilku sekund po wywołaniuJobService.onStartJob. W przypadku aplikacji kierowanych na Androida 13 i starsze wersje błędy ANR są ciche i nie są zgłaszane aplikacji. W przypadku aplikacji kierowanych na Androida 14 i nowsze wersje błędy ANR są jawne i zgłaszane aplikacji.
Jeśli w aplikacji występują błędy ANR, możesz skorzystać z informacji w tym dokumencie, aby zdiagnozować i rozwiązać problem.
Wykrywanie problemu
Jeśli aplikacja została już opublikowana, możesz użyć Android Vitals, aby wyświetlić informacje o błędach ANR w aplikacji. Do wykrywania błędów ANR w terenie możesz używać innych narzędzi, ale pamiętaj, że narzędzia innych firm nie mogą zgłaszać błędów ANR w Androidzie 10 i starszych wersjach, w przeciwieństwie do Android Vitals.
Android Vitals
Android Vitals może pomóc Ci monitorować i poprawiać częstotliwość błędów ANR w aplikacji. Android Vitals mierzy kilka 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 typu
Input dispatching timed out. - Częstotliwość wielokrotnych błędów ANR: odsetek liczby aktywnych użytkowników dziennie, u których wystąpiły co najmniej 2 błędy ANR.
Aktywny użytkownik 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 tego wskaźnika w Google Play obowiązują 2 progi niewłaściwego działania:
- Ogólny próg niewłaściwego działania: 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 Twoja aplikacja przekracza ogólny próg niewłaściwego działania, prawdopodobnie będzie trudniejsza do odkrycia na wszystkich urządzeniach. Jeśli Twoja aplikacja przekracza próg niewłaściwego działania na poziomie urządzenia na niektórych urządzeniach, prawdopodobnie będzie trudniejsza do odkrycia 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ąpi zbyt wiele błędów ANR.
Więcej informacji o tym, jak Google Play zbiera dane Android Vitals, znajdziesz w dokumentacji Play Console.
Diagnozowanie błędów ANR
Podczas diagnozowania błędów ANR warto zwrócić uwagę na te typowe wzorce:
- Aplikacja wykonuje powolne operacje wejścia-wyjścia w wątku głównym.
- Aplikacja wykonuje długie obliczenia w wątku głównym.
- Wątek główny wykonuje synchroniczne wywołanie bindera do innego procesu, a ten proces długo czeka na powrót.
- Wątek główny jest zablokowany i czeka na zsynchronizowany blok długiej operacji, która jest wykonywana w innym wątku.
- Wątek główny jest w stanie zakleszczenia z innym wątkiem, w Twoim procesie lub przez wywołanie bindera. Wątek główny nie tylko czeka na zakończenie długiej operacji, ale też jest w stanie zakleszczenia.
Poniższe techniki mogą pomóc Ci określić przyczynę błędów ANR.
HealthStats
HealthStats udostępnia dane o stanie aplikacji, rejestrując łączny czas użytkownika i systemu, czas procesora, statystyki sieci i radia, czas włączenia i wyłączenia ekranu oraz alarmy wybudzania. Może to pomóc w pomiarze ogólnego wykorzystania procesora i zużycia baterii.
Debugowanie
Debug pomaga w sprawdzaniu aplikacji na Androida podczas programowania, w tym w śledzeniu i zliczaniu alokacji, aby wykryć zacięcia i opóźnienia w aplikacjach.
Możesz też użyć Debug, aby uzyskać liczniki pamięci natywnej i pamięci w czasie wykonywania oraz dane o pamięci, które mogą pomóc w określeniu wykorzystania pamięci przez dany proces.
ApplicationExitInfo
ApplicationExitInfo jest dostępny w Androidzie 11 (poziom API 30) lub nowszym i zawiera informacje o przyczynie zamknięcia aplikacji. Obejmuje to błędy ANR, brak pamięci, awarie aplikacji, nadmierne wykorzystanie procesora, przerwy spowodowane przez użytkownika, przerwy systemowe i zmiany uprawnień w czasie wykonywania.
Tryb ścisły
Używanie StrictMode pomaga znaleźć przypadkowe operacje wejścia-wyjścia w wątku głównym
podczas programowania aplikacji. Możesz używać StrictMode na poziomie
aplikacji lub aktywności.
Włączanie okien błędu ANR w tle
Android wyświetla okna błędu ANR w przypadku aplikacji, które zbyt długo przetwarzają komunikat rozgłaszany, tylko wtedy, gdy w opcjach programisty na urządzeniu jest włączona opcja Pokaż wszystkie błędy ANR. Z tego powodu okna błędu ANR w tle nie zawsze są wyświetlane użytkownikowi, nawet jeśli w aplikacji występują problemy z wydajnością.
Wąskie gardła rekompozycji
Użyj profilera Android Studio i narzędzia Layout Inspector, aby wykryć wąskie gardła rekompozycji. Więcej informacji znajdziesz w artykule Jetpack Compose Performance.
Pobieranie pliku śledzenia
Gdy Android napotka błąd ANR, zapisuje informacje o śledzeniu. W starszych wersjach systemu operacyjnego na urządzeniu znajduje się jeden plik /data/anr/traces.txt. W nowszych wersjach systemu operacyjnego jest kilka plików /data/anr/anr_*. Dostęp do śladów błędów ANR
z urządzenia lub emulatora można uzyskać za pomocą narzędzia Android Debug Bridge (adb) jako
root:
adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>
Raport o błędzie możesz utworzyć 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
Tworzenie 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ć często spotykane problemy.
Powolny kod w wątku głównym
Określ miejsca w kodzie, w których wątek główny aplikacji jest zajęty przez ponad 5 sekund. Poszukaj podejrzanych przypadków użycia w aplikacji i spróbuj odtworzyć błąd ANR.
Częstym problemem jest długotrwałe zadanie bezpośrednio w komponencie:
@Composable
fun BadList(rawStrings: List<String>) {
// Math or sorting inside the composable runs on EVERY recomposition pass!
val heavilyProcessedList = rawStrings
.filter { it.isNotBlank() }
.map { it.uppercase().reversed() }
.map { it.computationallyHeavyFunction() }
.sortedBy { it.length }
LazyColumn { items(sortedList) { Text(it) } }
}
// Modern Compose-first fix
@Composable
fun GoodList(viewModel: MyViewModel = viewModel()) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
// UI simply renders state; no heavy processing allowed here
LazyColumn { items(uiState.sortedData) { Text(it) } }
}
Wejście-wyjście w wątku głównym
Wykonywanie operacji wejścia-wyjścia w wątku głównym jest częstą przyczyną powolnych operacji w wątku głównym, co może powodować błędy ANR. W Compose programiści często przypadkowo wywołują odczyty z dysku (np. SharedPreferences lub wywołania bazy danych) podczas próby uzyskania stanu początkowego.
Długotrwałe operacje wejścia-wyjścia wykonuj poza warstwą interfejsu. Użyj
withContext(Dispatchers.IO) w ViewModel lub, co jeszcze lepsze, użyj a
Repository na warstwie danych.
Zakleszczenia
Zakleszczenie występuje, gdy wątek przechodzi w stan oczekiwania, ponieważ wymagany zasób jest używany przez inny wątek, który również czeka na zasób używany przez pierwszy wątek. Jeśli wątek główny aplikacji znajduje się w takiej sytuacji, prawdopodobnie wystąpią błędy ANR.
Zakleszczenia są dobrze zbadanym zjawiskiem w informatyce. Istnieją algorytmy zapobiegające zakleszczeniom, których możesz użyć, aby ich uniknąć.
Więcej informacji znajdziesz w artykułach Deadlock i Deadlock prevention algorithms w Wikipedii.
Gdy używasz Kotlina i Compose, możesz zastąpić pierwotne blokady
nieblokującymi muteksami współprogramów (Mutex.withLock), aby zapobiec blokowaniu
wątków przez zawieszenie kontekstu wykonywania zamiast zamrażania wątku
UI. Przykład:
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
// Modern non-blocking concurrency state architecture
class SecureDataRepository {
private val mutex = Mutex()
suspend fun safeUIAccess() {
// If locked, the main thread suspends seamlessly, preventing an ANR
mutex.withLock {
performSafeOperation()
}
}
}
Powolne odbiorniki
Aplikacje mogą odpowiadać na komunikaty rozgłaszane, np. włączanie lub wyłączanie trybu samolotowego albo zmianę stanu połączenia, za pomocą odbiorników. Błąd ANR występuje, gdy aplikacja zbyt długo przetwarza komunikat rozgłaszany.
Błąd ANR występuje w tych przypadkach:
- Odbiornik nie zakończył wykonywania metody
onReceivew rozsądnym czasie. - Odbiornik wywołuje
goAsynci nie wywołujefinishw obiekciePendingResult.
Aplikacja powinna wykonywać tylko krótkie operacje w metodzie onReceive
odbiornika BroadcastReceiver. Jeśli jednak aplikacja wymaga bardziej złożonego przetwarzania w wyniku komunikatu rozgłaszanego, powinna przekazać zadanie do ViewModel (wykorzystując możliwości współprogramów, zakresów i dyspozytorów Kotlina) jeśli zadanie ma trwać co najwyżej kilka sekund, do dowolnego typu zmiennej stanu, lub do WorkManager w przypadku zadań, które mają trwać 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 C lub C++. Jeśli zastąpisz dotychczasową aktywność natywną
GameActivity, możesz zmniejszyć blokowanie wątku UI i zapobiec niektórym
błędom ANR.
Więcej informacji o błędach ANR znajdziesz w artykule Zapewnianie responsywności aplikacji. Więcej informacji o wątkach znajdziesz w artykule Lepsza wydajność dzięki wielowątkowości.
Dodatkowe materiały
Wyświetlanie treści
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy język JavaScript jest wyłączony.
- Zbyt częste wybudzenia