Android зависает, когда в OnClickListener.onClick есть исключение NullPointerException (другие задачи не могут запускаться)
У меня простая настройка:
-
CrashHandler
- класс, который реализует Thread.UncaughtExceptionHandler
;
-
CrashActivity
- действие, которое может отправлять отчеты пользователя;
-
MainActivity
- основное приложение, с которым пользователь должен взаимодействовать.
Если в MainActivity
или любом из его потоков есть неперехваченное исключение, CrashHandler
перехватывает его и создает уведомление с намерением запустить 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);
В то же время, когда Android показывает сообщение "сбой приложения", пользователь нажимает "ОК", приложение закрывается, а затем пользователь может нажать notification
. Если нажать notification
, начнется и показывается CrashActivity
.
Этот код долгое время работал во многих ситуациях (авария в главном потоке, авария в handler
, авария на фоне thread
...). Однако недавно я обнаружил, что он НЕ РАБОТАЕТ, если исключение выбрано в методе OnClickListener.onClick
в прослушивателе, прикрепленном к button
в MainActivity
. Ситуация такова:
- Я выполняю код, который намеренно бросает
NullPointerException
;
-
CrashHandler
перехватывает его и создает notification
(который показан);
- Android НЕ показывает никаких сообщений (например, нет "Application crashed", который должен быть видимым);
-
MainActivity
заморожен;
- Если пользователь нажимает на уведомление для запуска
CrashActivity
, отображается черный экран и все зависает (желаемая активность не отображается).
Logcat
показывает, что при запуске есть таймаут, даже до OnCreate
или любого из моего кода:
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}
- Если перед нажатием
notification
я убью приложение из ADB
, notification
отлично работает.
-
Если перед нажатием notification
я сделаю несколько кликов и жестов в замороженном приложении, через несколько секунд я получаю сообщение о ANR
:
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
-
Если я нажму "да, убей его", а затем нажмите notification
, он отлично работает.
- Если я добавлю
System.exit
(- 1) в CrashHandler
сразу после создания уведомления, приложение немедленно прекратит работу, и уведомление будет работать отлично (к сожалению, я не могу пойти с этим решением в процессе производства).
У меня есть два вопроса:
- Почему
NullPointer exception
в OnClickListener.onClick
не приводит к сбою приложения, вместо этого замораживает его вместе с ОС и предотвращает запуск других действий?
- Что делать, чтобы избежать вообще или, по крайней мере, как начать
CrashActivity
в этих условиях?
Ответы
Ответ 1
Не просматривая свой код, вы должны отладить свой класс CrashHandler. JVM будет игнорировать все исключения в этом
void uncaughtException(Thread t, Throwable e)
"Любое исключение, созданное этим методом, будет игнорироваться виртуальной машиной Java". (JavaDoc).
Я не говорю, что это ответ, но это может быть ответ, если этот метод исключает.
Ответ 2
Почему вы не можете убить свой собственный процесс приложения
https://developer.android.com/reference/android/os/Process.html#sendSignal(int, int)?