11

I have a simple setup:

  • CrashHandler - a class which implements Thread.UncaughtExceptionHandler;
  • CrashActivity - an activity which can send user reports;
  • MainActivity - the main app with which the user should interact.

When there is an uncaught exception within the MainActivity or any of it's threads, the CrashHandler intercepts it and creates a notification with an intent to start the 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); 

In the mean time Android shows an "Application crashed" message, the user clicks OK, the application is closed, then the user might click the notification. If the notification is clicked, the CrashActivity starts and shows.

This code has been working for a long time in many different situations (crash on main thread, crash in a handler, crash on a background thread...). However, I recently discovered that it DOES NOT WORK if the exception is thrown in the OnClickListener.onClick method in a listener attached to a button in the MainActivity. The situation is as follows:

  1. I execute code that deliberately throws a NullPointerException;
  2. CrashHandler intercepts it and creates a notification (which is shown);
  3. Android DOES NOT show any messages (for example, there is no "Application crashed", which should be visible);
  4. The MainActivity is frozen;
  5. IF the user clicks on the notification to launch the CrashActivity, a black screen is shown and everything freezes (the desired activity is not shown).

Logcat shows that there is a timeout on launch, even before OnCreate or any of my code:

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}
  • If before clicking the notification I kill the app from ADB, the notification works perfectly.
  • If before clicking the notification I make some clicks and gestures on the frozen app, after a few seconds I receive a message about an 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 
    
  • If I click "yes, kill it", and then click the notification, it works perfectly.

  • If I add System.exit(-1) in the CrashHandler just after creating the notification, the app immediately quits and the notification works perfectly (unfortunately, I can't go with this solution in production).

I have two questions:

  1. Why a NullPointer exception in OnClickListener.onClick doesn't cause the app to crash, instead freezing it together with the OS and preventing other activities from starting?
  2. What to do to avoid it in general, or at least, how to make the CrashActivity start in these conditions?
am05mhz
  • 2,727
  • 2
  • 23
  • 37
Kocus
  • 1,613
  • 17
  • 31

2 Answers2

0

Without seeing your code, you should debug you CrashHandler Class. The JVM will ignore all exceptions in this

void uncaughtException(Thread t, Throwable e)

"Any exception thrown by this method will be ignored by the Java Virtual Machine." (JavaDoc).

I say not that this is the answer but it possible could the answer, if this method thwows an exceptions.

RobSky
  • 325
  • 2
  • 6
0

Why can't you kill your own app process with https://developer.android.com/reference/android/os/Process.html#sendSignal(int, int)?

ashishb
  • 534
  • 7
  • 17