mam prostą konfigurację:Android zamarza, gdy istnieje NullPointerException w OnClickListener.onClick (inne zadania nie można uruchomić)
CrashHandler
- klasy, która implementujeThread.UncaughtExceptionHandler
;CrashActivity
- działanie, które może wysyłać raporty użytkowników;MainActivity
- główna aplikacja, z którą użytkownik powinien wchodzić w interakcje.
Gdy jest przechwycony wyjątek w MainActivity
lub którykolwiek To gwintów CrashHandler
Przechwytuje i tworzy powiadomienia z zamiarem rozpoczęcia CrashActivity
:
Intent it = new Intent("CrashReporter" + SystemClock.currentThreadTimeMillis());
it.setClass(context, CrashActivity.class);
it.setFlags(it.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
W Średni czas Android pokazach wiadomość "Zgłoszenie aplikacji", użytkownik kliknie przycisk OK, aplikacja zostanie zamknięta, a następnie użytkownik może kliknąć ikonę notification
. Po kliknięciu przycisku notification
rozpoczyna się i pokazuje CrashActivity
.
Kod ten działał przez długi czas w wielu różnych sytuacjach (awarie głównego wątku, awaria w handler
, awaria na tle thread
...). Jednak niedawno odkryłem, że NIE DZIAŁA, jeśli wyjątek został zgłoszony w metodzie OnClickListener.onClick
w detektorze dołączonym do button
w . Sytuacja wygląda następująco:
- Wykonuję kod, który celowo rzuca
NullPointerException
; CrashHandler
przechwytuje i tworzynotification
(co pokazano);- Android NIE wyświetla żadnych komunikatów (na przykład nie ma "aplikacji zawieszonej", co powinno być widoczne);
- Urządzenie
MainActivity
jest zamrożone; - JEŻELI użytkownik kliknie powiadomienie, aby uruchomić
CrashActivity
, pojawi się czarny ekran i wszystko zawiesza się (pożądana aktywność nie jest pokazana).
Logcat
pokazuje, że nie jest to czas oczekiwania na uruchomienie nawet przed OnCreate
lub którykolwiek z mojego kodu:
I/ActivityManager(11826): START u0 {act=CrashHandler1196 flg=0x14000000 cmp=mycompany.myapp/.CrashActivity bnds=[0,102][720,230] (has extras)} from pid -1
W/KeyguardViewMediator(11826): verifyUnlock called when not externally disabled
W/ActivityManager(11826): Activity pause timeout for ActivityRecord{41f4d988 u0 mycompany.myapp/.MainActivity}
W/ActivityManager(11826): Launch timeout has expired, giving up wake lock!
W/ActivityManager(11826): Activity idle timeout for ActivityRecord{4225eeb8 u0 mycompany.myapp/.CrashActivity}
- Jeśli przed kliknięciem
notification
zabiję aplikację zADB
, żenotification
działa doskonale . Jeśli przed kliknięciem
notification
robię kilka kliknięć i gesty na zamarzniętym aplikacji, po kilku sekundach pojawia się komunikat oANR
:E/ActivityManager(11826): ANR in mycompany.myapp (mycompany.myapp/.MainActivity) E/ActivityManager(11826): Reason: keyDispatchingTimedOut E/ActivityManager(11826): Load: 0.63/0.57/0.49
Jeśli kliknę „tak, zabij go” a następnie kliknij
notification
, działa idealnie.- Jeśli dodam
System.exit
(-1) wCrashHandler
zaraz po utworzeniu powiadomienia, aplikacja natychmiast wychodzi i powiadomienie działa idealnie (niestety, nie mogę przejść z tym rozwiązaniem w produkcji).
Mam dwa pytania:
- Dlaczego
NullPointer exception
wOnClickListener.onClick
nie powoduje awarię aplikacji, zamiast zamrażania go wraz z systemem operacyjnym i zapobiegania innych czynności przed uruchomieniem? - Co należy zrobić, aby go uniknąć w ogóle, a przynajmniej jak wprowadzić
CrashActivity
w tych warunkach?
Myślę, że należy opublikować część kodu z ** onClick **, abyśmy mogli zrozumieć. –