Diagnozowanie i naprawianie błędów ANR

Jeśli wątek UI aplikacji na Androida jest zablokowany zbyt długo, system wysyła błąd „Aplikacja nie odpowiada” (ANR). Na tej stronie opisujemy różne typy błędów ANR oraz sposoby ich diagnozowania i usuwania. Wszystkie podane domyślne zakresy czasu oczekiwania dotyczą urządzeń AOSP i Pixel. Mogą się one różnić w zależności od producenta OEM.

Pamiętaj, że przy określaniu przyczyny błędów ANR warto odróżnić problemy z systemem od problemów z aplikacją.

Jeśli system znajduje się w złym stanie, błędy ANR mogą powodować te problemy:

  • Przejściowe problemy na serwerze systemowym powodują zwykle powolne wywołania Binder.
  • Problemy z serwerem systemowym i dużym obciążeniem urządzenia powodują brak harmonogramu wątków aplikacji.

Dobrym sposobem na odróżnienie problemów z systemem od problemów z aplikacją, jeśli to możliwe, jest użycie śladów Perfetto:

  • Aby sprawdzić, czy główny wątek aplikacji jest zaplanowany, spójrz na ścieżkę stanu wątku w Perfetto i zobacz, czy jest on uruchomiony.
  • Przejrzyj wątki w system_server pod kątem problemów takich jak rywalizacja o blokadę.
  • W przypadku powolnych wywołań Binder, spójrz na wątek odpowiedzi, aby zobaczyć, dlaczego działa wolno.

Limit czasu wysyłania danych wejściowych

Błędy ANR w wysyłaniu danych wejściowych mają miejsce, gdy główny wątek aplikacji nie reaguje na zdarzenie wejściowe, takie jak przesunięcie lub naciśnięcie klawisza w odpowiednim czasie. Ponieważ aplikacja działa na pierwszym planie w przypadku przekroczenia limitu czasu wysyłania danych wejściowych, są one prawie zawsze widoczne dla użytkownika i bardzo ważne, aby je zniwelować.

Domyślny okres oczekiwania: 5 sekund.

Błędy ANR w wysyłaniu danych wejściowych są zwykle spowodowane problemami w wątku głównym. Jeśli wątek główny został zablokowany podczas oczekiwania na blokadę, może to dotyczyć także wątku właściciela.

Aby uniknąć błędów ANR w wysyłaniu danych wejściowych, postępuj zgodnie z tymi sprawdzonymi metodami:

  • Nie wykonuj blokowania ani długo trwających operacji w wątku głównym. Możesz użyć narzędzia StrictMode, aby wychwycić przypadkowe działania w wątku głównym.
  • Zminimalizuj rywalizację o blokadę między wątkami głównym a innymi wątkami.
  • Zminimalizować czas pracy niezwiązany z interfejsem użytkownika w wątku głównym, na przykład przy obsłudze transmisji lub uruchomieniu usług.

Najczęstsze przyczyny

Oto kilka częstych przyczyn i sugerowanych rozwiązań błędów ANR w wysyłaniu danych wejściowych.

Przyczyna Skutki Sugerowane poprawki
Powolne wywołanie Binder Wątek główny wykonuje długie wywołanie wiązania synchronicznego. Usuń wywołanie z głównego wątku lub spróbuj je zoptymalizować, jeśli jesteś właścicielem interfejsu API.
Wiele kolejnych wywołań Binder Wątek główny wykonuje wiele następujących po sobie synchronicznych wywołań powiązania. Nie wykonuj połączeń pośrednich w zapętleniu.
Blokowanie I/O Wątek główny powoduje zablokowanie wywołania wejścia-wyjścia, takie jak dostęp do bazy danych lub sieci. Przenieś wszystkie blokujące operacje wejścia-wyjścia z wątku głównego.
Rywalizacja o blokadę Wątek główny jest zablokowany w oczekiwaniu na blokadę. Ogranicz rywalizację o blokadę między wątkiem głównym a innym wątkiem. Zoptymalizuj powolny kod w drugim wątku.
Drogie kadrowanie Zbyt obszerne renderowanie w jednej klatce, co prowadzi do poważnego zacinania się. Mniej pracy na pogłębianiu kadru. Nie używaj algorytmów n2. Używaj wydajnych komponentów do przewijania lub stronicowania, np. biblioteki stronicowania Jetpack.
Zablokowane przez inny komponent Inny komponent, na przykład odbiornik transmisji, działa i blokuje wątek główny. Jeśli to możliwe, usuń zadania niewymagające interfejsu z głównego wątku. Uruchom odbiorniki w innym wątku.
Zawieszenie GPU Zawieszenie GPU to problem systemowy lub sprzętowy, który powoduje blokowanie renderowania i tym samym związany z wysyłaniem danych wejściowych błąd ANR. Zazwyczaj nie ma żadnych poprawek po stronie aplikacji. Jeśli to możliwe, skontaktuj się z zespołem ds. sprzętu, aby rozwiązać problem.

Jak debugować

Zacznij debugować od sprawdzenia podpisu klastra błędów ANR w Konsoli Google Play lub Firebase Crashlytics. Klaster zwykle zawiera górne ramki, co do których istnieje podejrzenie, że powodują błąd ANR.

Poniższy schemat blokowy pokazuje, jak określić przyczynę błędu ANR w wyniku przekroczenia limitu czasu na dane wejściowe.

Rysunek 1. Debugowanie błędu ANR w wysyłaniu danych wejściowych.

Play Vitals może wykrywać i usuwać niektóre z tych częstych przyczyn błędów ANR. Jeśli na przykład wskaźniki wykryją, że błąd ANR wystąpił w wyniku rywalizacji o blokadę, możesz podsumować problem i zalecane rozwiązanie w sekcji Statystyki błędów ANR.

Rysunek 2. Wykrywanie błędów ANR w Play Vitals.

Brak zaznaczonego okna

Zdarzenia takie jak dotyk są wysyłane bezpośrednio do odpowiedniego okna na podstawie testowania trafień, ale zdarzenia takie jak klucze wymagają elementu docelowego. Jest on nazywany oknem skupionym. Na każdy wyświetlacz jest aktywne tylko jedno aktywne okno. Zazwyczaj jest to okno, z którym użytkownik w danej chwili wchodzi w interakcję. Jeśli nie można znaleźć zaznaczonego okna, dane wejściowe wywołują błąd ANR no-focus-window. ANR „Nie wybrano okna” to typ błędu ANR w wysyłaniu danych wejściowych.

Domyślny okres oczekiwania: 5 sekund.

Najczęstsze przyczyny

Błędy ANR „Nie wybrano okien” są zwykle spowodowane przez jeden z tych problemów:

  • Aplikacja wykonuje za dużo pracy i zbyt wolno, aby narysować pierwszą klatkę.
  • Nie można zaznaczyć okna głównego. Jeśli okno jest oznaczone etykietą FLAG_NOT_FOCUSABLE, użytkownik nie może wysyłać do niego zdarzeń związanych z kluczem ani przyciskiem.

Kotlin

override fun onCreate(savedInstanceState: Bundle) {
  super.onCreate(savedInstanceState)
  setContentView(R.layout.activity_main)
  window.addFlags(WindowManager.LayoutParams.FLAG_FLAG_NOT_FOCUSABLE)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
}

Upłynął limit czasu odbiornika transmisji

Błąd ANR odbiornika transmisji ma miejsce, gdy odbiornik nie obsługuje na czas transmisji. W przypadku odbiorników synchronicznych lub odbiorników, które nie wywołują metody goAync(), przekroczenie limitu czasu oznacza, że działanie onReceive() nie zostało ukończone w czasie. W przypadku odbiorników asynchronicznych wywołujących funkcję goAsync() limit czasu oznacza, że funkcja PendingResult.finish() nie została wywołana na czas.

Błędy ANR odbiornika transmisji często występują w tych wątkach:

  • Wątek główny, jeśli problem dotyczy powolnego uruchamiania aplikacji.
  • Wątek z odbiornikiem transmisji, jeśli problem dotyczy powolnego kodu onReceive().
  • Przesyłaj wątki instancji roboczych, jeśli problem dotyczy powolnego kodu przesyłania goAsync().

Aby uniknąć błędów ANR odbiornika transmisji, postępuj zgodnie z tymi sprawdzonymi metodami:

  • Zadbaj o szybkie uruchamianie aplikacji, bo jest on liczony jako limit czasu błędu ANR, gdy rozpoczęto obsługę transmisji.
  • Jeśli używana jest funkcja goAsync(), sprawdź, czy PendingResult.finish() jest szybko wywoływane. Ten limit czasu ANR jest taki sam jak w przypadku synchronicznych odbiorników.
  • Jeśli używasz goAsync(), sprawdź, czy wątki robocze nie są udostępniane innym długo trwającym lub blokującym operacjam.
  • Zastanów się, czy nie użyć registerReceiver(), aby uruchomić odbiorniki w wątku innym niż główny, co pozwoli uniknąć blokowania kodu interfejsu użytkownika w wątku głównym.

Okresy oczekiwania

Okresy oczekiwania na odebranie transmisji zależą od tego, czy ustawiona jest flaga intencji na pierwszym planie oraz od wersji platformy.

Typ intencji Android 13 i starsze Android 14 lub nowszy

Intencja dotycząca priorytetu pierwszego planu

(FLAG_RECEIVER_FOREGROUND zestaw)

10 sekund,

10–20 sekund, w zależności od tego, czy proces jest obciążany procesorami

Intencja dotycząca priorytetu tła

(FLAG_RECEIVER_FOREGROUND nie ustawiono)

60 sekund

60–120 sekund w zależności od tego, czy proces jest obciążany procesorami

Aby sprawdzić, czy jest ustawiona flaga FLAG_RECEIVER_FOREGROUND, wyszukaj ciąg „flg=” w temacie błędu ANR i sprawdź, czy występuje element 0x10000000. Jeśli ten bit jest ustawiony, intencja ma ustawiony parametr FLAG_RECEIVER_FOREGROUND, więc czas oczekiwania jest krótszy.

Przykładowy błąd ANR z krótkim czasem oczekiwania na transmisję (10–20 sekund):

Broadcast of Intent { act=android.inent.action.SCREEN_ON flg=0x50200010 }

Przykładowy błąd ANR z długim czasem oczekiwania na transmisję (60–120 sekund):

Broadcast of Intent { act=android.intent.action.TIME_SET flg=0x25200010 }

Jak mierzony jest czas transmisji

Pomiar czasu trwania transmisji rozpoczyna się po wysłaniu transmisji z aplikacji system_server do aplikacji i kończy, gdy aplikacja skończy jej przetwarzanie. Jeśli proces aplikacji nie był wcześniej uruchomiony, musi też uruchomić się „na zimno” w ramach określonego czasu oczekiwania na błąd ANR. Z tego powodu powolne uruchamianie aplikacji może powodować błędy ANR odbiornika transmisji transmisji.

Poniższy rysunek przedstawia oś czasu błędów ANR odbiornika transmisji, która jest zgodna z niektórymi procesami aplikacji.

Rysunek 3. Oś czasu błędów ANR odbiornika transmisji.

Pomiar limitu czasu błędu ANR kończy się, gdy odbiornik zakończy przetwarzanie transmisji. To, kiedy dokładnie tak się stanie, zależy od tego, czy jest to odbiornik synchroniczny czy asynchroniczny.

  • W przypadku odbiorników synchronicznych pomiar zatrzymuje się po zwróceniu parametru onReceive().
  • W przypadku odbiorników asynchronicznych pomiar zatrzymuje się po wywołaniu funkcji PendingResult.finish().
Rysunek 4. Punkty końcowe pomiaru limitu czasu błędów ANR dla synchronicznych i asynchronicznych odbiorników.

Najczęstsze przyczyny

Oto kilka częstych przyczyn błędów ANR odbiornika transmisji i sugerowane sposoby ich rozwiązania.

Przyczyna Dotyczy Co się stało Proponowane rozwiązanie
Powolne uruchamianie aplikacji Wszyscy odbiorcy Uruchomienie aplikacji „na zimno” trwało zbyt długo. Zoptymalizuj powolne uruchamianie aplikacji.
Nie zaplanowano: onReceive() Wszyscy odbiorcy Wątek odbiorcy był zajęty wykonywaniem innych zadań i nie mógł uruchomić metody onReceive(). Nie wykonuj długo trwających zadań w wątku odbiorcy (ani przenieś odbiornik do dedykowanego wątku).
Wolny nośnik onReceive() Wszystkie odbiorniki, ale głównie synchroniczne Metoda onReceive() została uruchomiona, ale była zablokowana lub powolna, więc nie zakończyła się na czas. Zoptymalizuj kod powolnego odbiornika.
Nie zaplanowano zadań odbiornika asynchronicznego goAsync() odbiornika Metoda onReceive() próbowała wykonać pracę na zablokowanej puli wątków instancji roboczych, dlatego praca się nie rozpoczęła. Zoptymalizuj powolne lub blokujące połączenia albo używaj różnych wątków dla pracowników komunikatów w porównaniu z innymi długotrwałymi zadaniami.
Powolne lub zablokowane instancje robocze goAsync() odbiornika Podczas przetwarzania transmisji w puli wątków instancji roboczych wystąpiła blokada lub powolna operacja. Z tego powodu numer PendingResult.finish nie został wywołany na czas. Zoptymalizuj powolny kod odbiorcy async.
Zapomniałem(-am) zadzwonić do: PendingResult.finish goAsync() odbiornika W ścieżce kodu brakuje wywołania pod numer finish(). Upewnij się, że usługa finish() jest zawsze wywoływana.

Jak debugować

Na podstawie podpisu klastra i raportu ANR możesz znaleźć wątek, w którym działa odbiornik, a następnie konkretny kod, którego brakuje lub działa wolno.

Na poniższym schemacie blokowym przedstawiono sposób określenia przyczyny błędu odbiornika ANR.

Rysunek 5. Jak debugować błąd ANR odbiornika transmisji.

Znajdowanie kodu odbiorcy

Konsola Google Play pokazuje klasę odbiorcy i intencję transmisji w sygnale ANR. Sprawdź, czy:

  • cmp=<receiver class>
  • act=<broadcast_intent>

Oto przykład podpisu ANR odbiornika:

com.example.app.MyClass.myMethod
Broadcast of Intent { act=android.accounts.LOGIN_ACCOUNTS_CHANGED
cmp=com.example.app/com.example.app.MyAccountReceiver }

Znajdź wątek z metodą onReceived()

Jeśli używasz funkcji Context.registerReceiver, aby określić niestandardowy moduł obsługi, jest to wątek, w którym uruchomiono ten moduł. W przeciwnym razie jest to wątek główny.

Przykład: asynchroniczne zadania odbiorcy nie zostały zaplanowane

W tej sekcji jest podany przykład debugowania błędu ANR odbiornika.

Załóżmy, że podpis ANR wygląda tak:

com.example.app.MyClass.myMethod
Broadcast of Intent {
act=android.accounts.LOG_ACCOUNTS_CHANGED cmp=com.example.app/com.example.app.MyReceiver }

Z podpisu wygląda na to, że intencja transmisji to android.accounts.LOG_ACCOUNTS_CHANGED, a klasa odbiorcy to com.example.app.MyReceiver.

Na podstawie kodu odbiorcy możesz ustalić, że główna rola przetwarzania komunikatu odpowiada pula wątków „BG Thread [0,1,2,3]”. Po spojrzeniu na zrzuty stosu można zauważyć, że wszystkie 4 wątki w tle mają ten sam wzorzec: uruchamiają połączenie blokujące, getDataSync. Ponieważ wszystkie wątki GG były zajęte, nie udało się przetworzyć transmisji na czas, co doprowadziło do błędu ANR.

BG Thread #0 (tid=26) Waiting

at jdk.internal.misc.Unsafe.park(Native method:0)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:211)
at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture:563)
at com.google.common.util.concurrent.ForwardingFuture.get(ForwardingFuture:68)
at com.example.app.getDataSync(<MyClass>:152)

...

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
at com.google.android.libraries.concurrent.AndroidExecutorsModule.lambda$withStrictMode$5(AndroidExecutorsModule:451)
at com.google.android.libraries.concurrent.AndroidExecutorsModule$$ExternalSyntheticLambda8.run(AndroidExecutorsModule:1)
at java.lang.Thread.run(Thread.java:1012)
at com.google.android.libraries.concurrent.ManagedPriorityThread.run(ManagedPriorityThread:34)

There are several approaches to fix the issue:

  • Find out why getDataSync is slow and optimize.
  • Don't run getDataSync on all four BG threads.
  • More generally, ensure that the BG thread pool isn't saturated with long-running operations.
  • Use a dedicated thread pool for goAsync worker tasks.
  • Use an unbounded thread pool instead of the bounded BG thread pool

Example: slow app startup

A slow app startup can cause several types of ANRs, especially broadcast receiver and execute service ANRs. The cause of an ANR is likely slow app startup if you see ActivityThread.handleBindApplication in the main thread stacks.

Execute service timeout

An execute service ANR happens when the app's main thread doesn't start a service in time. Specifically, a service doesn't finish executing onCreate() and onStartCommand() or onBind() within the timeout period.

Default timeout period: 20 seconds for foreground service; 200 seconds for background service. The ANR timeout period includes the app cold start, if necessary, and calls to onCreate(), onBind(), or onStartCommand().

To avoid execute service ANRs, follow these general best practices:

  • Make sure that app startup is fast, since it's counted in the ANR timeout if the app is started to run the service component.
  • Make sure that the service's onCreate(), onStartCommand(), and onBind() methods are fast.
  • Avoid running any slow or blocking operations on the main thread from other components; these operations can prevent a service from starting quickly.

Common causes

The following table lists common causes of execute service ANRs and suggested fixes.

Cause What Suggested fix
Slow app startup The app takes too long to perform a cold start. Optimize slow app start.
Slow onCreate(), onStartCommand(), or onBind() The service component's onCreate(), onStartCommand(), or onBind() method takes too long to execute on the main thread. Optimize slow code. Move slow operations off the critical path where possible.
Not scheduled (main thread blocked before onStart()) The app's main thread is blocked by another component before the service can be started. Move other component's work off the main thread. Optimize other component's blocking code.

How to debug

From the cluster signature and ANR report in Google Play Console or Firebase Crashlytics, you can often determine the cause of the ANR based on what the main thread is doing.

The following flow chart describes how to debug an execute service ANR.

Figure 6. How to debug an execute service ANR.

If you've determined that the execute service ANR is actionable, follow these steps to help resolve the issue:

  1. Find the service component class in the ANR signature. In Google Play Console, the service component class is shown in the ANR signature. In the following example ANR details, it's com.example.app/MyService.

    com.google.common.util.concurrent.Uninterruptibles.awaitUninterruptibly
    Executing service com.example.app/com.example.app.MyService
    
  2. Determine whether the slow or block operation is part of app startup, the service component, or elsewhere by checking for the following important function call(s) in the main threads.

    Function call(s) in main thread stacks What it means
    android.app.ActivityThread.handleBindApplication App was starting up, so the ANR was caused by slow app start.

    <ServiceClass>.onCreate()

    [...]

    android.app.ActivityThread.handleCreateService

    Service was being created, so the ANR was likely caused by slow onCreate() code.

    <ServiceClass>.onBind()

    [...]

    android.app.ActivityThread.handleBindService

    Service was being bound, so the ANR was likely caused by slow onBind() code.

    <ServiceClass>.onStartCommand()

    [...]

    android.app.ActivityThread.handleServiceArgs

    Service was being started, so the ANR was likely caused by slow onStartCommand() code.

    For example, if the onStartCommand() method in the MyService class is slow, the main threads will look like this:

    at com.example.app.MyService.onStartCommand(FooService.java:25)
    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4820)
    at android.app.ActivityThread.-$$Nest$mhandleServiceArgs(unavailable:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2289)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:205)
    at android.os.Looper.loop(Looper.java:294)
    at android.app.ActivityThread.main(ActivityThread.java:8176)
    at java.lang.reflect.Method.invoke(Native method:0)
    

    Jeśli nie widzisz żadnych ważnych wywołań funkcji, istnieje kilka innych możliwości:

    • Usługa działa lub się wyłącza, co oznacza, że stosy działają za późno. W takim przypadku możesz zignorować błąd ANR jako fałszywie pozytywny.
    • Uruchomiony jest inny komponent aplikacji, na przykład odbiornik. W takim przypadku wątek główny jest prawdopodobnie zablokowany w tym komponencie, co uniemożliwia uruchomienie usługi.
  3. Jeśli widzisz wywołanie kluczowej funkcji i możesz ustalić, gdzie zwykle występuje błąd ANR, sprawdź pozostałe stosy wątków głównych, aby znaleźć powolną operację i zoptymalizować ją lub przenieść poza ścieżkę krytyczną.

  4. Więcej informacji o usługach znajdziesz na tych stronach:

    Dostawca treści nie odpowiada

    Błąd ANR dostawcy treści ma miejsce, gdy na odpowiedź dostawcy treści potrzebuje więcej czasu, niż wynosi limit czasu, i zostaje zatrzymany.

    Domyślny okres oczekiwania: określony przez dostawcę treści za pomocą ContentProviderClient.setDetectNotResponding. Okres limitu czasu błędu ANR obejmuje łączny czas uruchomienia zapytania zdalnego dostawcy treści, co obejmuje uruchomienie aplikacji zdalnej „na zimno”, jeśli jeszcze nie była uruchomiona.

    Aby uniknąć błędów ANR dostawców treści, postępuj zgodnie z tymi sprawdzonymi metodami:

    • Zadbaj o szybkie uruchamianie aplikacji, bo czas oczekiwania błędu ANR jest liczony, gdy aplikacja zaczyna uruchamiać dostawcę treści.
    • Dopilnuj, aby zapytania dostawców treści były szybkie.
    • Nie wykonuj wielu równoczesnych wywołań funkcji Binder, które mogą blokować wszystkie powiązane wątki aplikacji.

    Najczęstsze przyczyny

    W tabeli poniżej znajdziesz typowe przyczyny błędów ANR dostawców treści i sugerowane rozwiązania ich problemów.

    Przyczyna Skutki Sygnał Proponowane rozwiązanie
    Powolne zapytanie dostawcy treści Dostawca treści trwa zbyt długo lub jest zablokowany. Ramka android.content.ContentProvider$Transport.query jest w wątku segregatora. Zapytanie dostawcy treści w witrynie Optimize. Dowiedz się, co blokuje wątek Binder.
    Powolne uruchamianie aplikacji Uruchamianie aplikacji dostawcy treści trwa zbyt długo. Ramka ActivityThread.handleBindApplication jest w wątku głównym. Optymalizuj uruchamianie aplikacji.
    Wyczerpanie wątków bindowania – wszystkie wątki bindowania są zajęte Wszystkie wątki powiązania są zajęte obsługą innych żądań synchronicznych, więc nie można uruchomić wywołania Binder dostawcy treści. Aplikacja się nie uruchamia, wszystkie wątki powiązania są zajęte, a dostawca treści nie jest uruchomiony. Zmniejsz obciążenie wątków bindowania. Oznacza to, że mniej synchronicznych wychodzących wywołań powiązania jest mniej pracochłonne przy obsłudze połączeń przychodzących.

    Jak debugować

    Aby debugować błędy ANR dostawcy treści za pomocą podpisu klastra i raportu o błędach ANR w Konsoli Google Play lub Firebase Crashlytics, sprawdź, co robią wątki główne i powiązane.

    Na tym schemacie blokowym opisano, jak debugować błąd ANR dostawcy treści:

    Rysunek 7. Jak debugować błąd ANR dostawcy treści.

    Poniższy fragment kodu pokazuje, jak wygląda wątek powiązania, gdy jest zablokowany z powodu powolnego zapytania dostawcy treści. W takim przypadku zapytanie dostawcy treści czeka na blokadę podczas otwierania bazy danych.

    binder:11300_2 (tid=13) Blocked
    
    Waiting for osm (0x01ab5df9) held by at com.google.common.base.Suppliers$NonSerializableMemoizingSupplier.get(Suppliers:182)
    at com.example.app.MyClass.blockingGetOpenDatabase(FooClass:171)
    [...]
    at com.example.app.MyContentProvider.query(MyContentProvider.java:915)
    at android.content.ContentProvider$Transport.query(ContentProvider.java:292)
    at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:107)
    at android.os.Binder.execTransactInternal(Binder.java:1339)
    at android.os.Binder.execTransact(Binder.java:1275)
    

    Ten fragment kodu pokazuje, jak wygląda główny wątek, gdy jest on zablokowany z powodu powolnego uruchamiania aplikacji. W tym przypadku uruchamianie aplikacji przebiega powolnie z powodu rywalizacji o blokadę podczas inicjowania sztyletu.

    main (tid=1) Blocked
    
    [...]
    at dagger.internal.DoubleCheck.get(DoubleCheck:51)
    - locked 0x0e33cd2c (a qsn)at dagger.internal.SetFactory.get(SetFactory:126)
    at com.myapp.Bar_Factory.get(Bar_Factory:38)
    [...]
    at com.example.app.MyApplication.onCreate(DocsApplication:203)
    at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1316)
    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6991)
    at android.app.ActivityThread.-$$Nest$mhandleBindApplication(unavailable:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2235)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:205)
    at android.os.Looper.loop(Looper.java:294)
    at android.app.ActivityThread.main(ActivityThread.java:8170)
    at java.lang.reflect.Method.invoke(Native method:0)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
    

    Powolna odpowiedź zadania

    Błąd ANR w powolnym zadaniu występuje, gdy aplikacja zbyt długo nie odpowiada na żądanie JobService.onStartJob() lub JobService.onStopJob() albo zbyt długo trwa przekazanie powiadomienia przy użyciu polecenia JobService.setNotification(). Sugeruje to, że główny wątek aplikacji jest zablokowany w czymś innym.

    Jeśli problem jest związany z JobService.onStartJob() lub JobService.onStopJob(), sprawdź, co dzieje się w wątku głównym. Jeśli problem dotyczy usługi JobService.setNotification(), zadzwoń jak najszybciej. Nie rób zbyt wielu rzeczy przed wysłaniem powiadomienia.

    Tajemnicze błędy ANR

    Czasami nie wiadomo, dlaczego błąd ANR występuje, lub nie ma wystarczającej ilości informacji do jego debugowania w podpisie klastra i raporcie o błędach ANR. W takiej sytuacji możesz wykonać jeszcze kilka czynności, aby sprawdzić, czy błąd ANR jest prawidłowy.

    Kolejka wiadomości jest nieaktywna lub natywnym razem

    Jeśli widzisz w stosach ramkę android.os.MessageQueue.nativePollOnce, często oznacza to, że wątek, który prawdopodobnie nie odpowiada, był tak naprawdę nieaktywny i czekał na wiadomości w postaci loopera. Szczegóły błędu ANR w Konsoli Google Play wyglądają tak:

    Native method - android.os.MessageQueue.nativePollOnce
    Executing service com.example.app/com.example.app.MyService
    

    Jeśli na przykład wątek główny jest nieaktywny, stosy wyglądają tak:

    "main" tid=1 NativeMain threadIdle
    
    #00  pc 0x00000000000d8b38  /apex/com.android.runtime/lib64/bionic/libc.so (__epoll_pwait+8)
    #01  pc 0x0000000000019d88  /system/lib64/libutils.so (android::Looper::pollInner(int)+184)
    #02  pc 0x0000000000019c68  /system/lib64/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+112)
    #03  pc 0x000000000011409c  /system/lib64/libandroid_runtime.so (android::android_os_MessageQueue_nativePollOnce(_JNIEnv*, _jobject*, long, int)+44)
    at android.os.MessageQueue.nativePollOnce (Native method)
    at android.os.MessageQueue.next (MessageQueue.java:339)  at android.os.Looper.loop (Looper.java:208)
    at android.app.ActivityThread.main (ActivityThread.java:8192)
    at java.lang.reflect.Method.invoke (Native method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:626)
    at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1015)
    

    Istnieje kilka powodów, dla których wątek może być nieaktywny:

    • Opóźniony zrzut stosu. Wątek przywrócił się w krótkim okresie między wywołaniem błędu ANR a zrzutami stosów. Na Pixelach z Androidem 13 opóźnienie wynosi około 100 ms, ale może przekraczać 1 s. Na telefonach z Androidem 14 opóźnienie wynosi zwykle mniej niż 10 ms.
    • Błędna atrybucja wątku. Wątek użyty do utworzenia podpisu ANR nie był rzeczywistym wątkiem, który spowodował błąd ANR. W takim przypadku spróbuj ustalić, czy błąd ANR należy do jednego z tych rodzajów:
    • Problem obejmujący cały system. Nie zaplanowano go z powodu dużego obciążenia systemu lub problemu z serwerem systemu.

    Brak ramek stosu

    Niektóre raporty o błędach ANR nie zawierają stosów z błędem ANR, co oznacza, że podczas generowania raportu o błędach nie udało się wykonać zrzutu stosu. Istnieje kilka możliwych powodów braku ramek stosu:

    • Pobieranie stosu trwa zbyt długo i przekracza limit czasu.
    • Proces zakończył działanie lub zakończył działanie przed zrobieniem stosu.
    [...]
    
    --- CriticalEventLog ---
    capacity: 20
    timestamp_ms: 1666030897753
    window_ms: 300000
    
    libdebuggerd_client: failed to read status response from tombstoned: timeout reached?
    
    ----- Waiting Channels: pid 7068 at 2022-10-18 02:21:37.<US_SOCIAL_SECURITY_NUMBER>+0800 -----
    
    [...]
    

    Podpis klastra ani raport o błędach ANR nie zawierają błędów ANR bez ramek stosu. Aby przeprowadzić debugowanie, spójrz na inne klastry danej aplikacji. Jeśli problem jest wystarczająco duży, aplikacja zwykle ma własny klaster z ramkami stosu. Możesz też skorzystać ze śladów Perfetto.

    Znane problemy

    Utrzymywanie w procesie aplikacji licznika czasu na potrzeby zakończenia obsługi transmisji przed wystąpieniem błędu ANR może nie działać prawidłowo z powodu asynchronicznego sposobu monitorowania tych błędów przez system.