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).

Я не говорю, что это ответ, но это может быть ответ, если этот метод исключает.