When my android application throw an exception, I want to show a custom dialog to tell user there is something wrong happened, so I use Thread.setDefaultUncaughtExceptionH
You cannot do any UI operation from here. Just start another activity/ splash screen. Pass an intent extra to denote crash and show dialog in that activity.
/*
* (non-Javadoc)
*
* @see
* java.lang.Thread.UncaughtExceptionHandler#uncaughtException(java.
* lang.Thread, java.lang.Throwable)
*/
@Override
public void uncaughtException(Thread t, final Throwable e) {
StackTraceElement[] arr = e.getStackTrace();
final StringBuffer report = new StringBuffer(e.toString());
final String lineSeperator = "-------------------------------\n\n";
report.append(DOUBLE_LINE_SEP);
report.append("--------- Stack trace ---------\n\n");
for (int i = 0; i < arr.length; i++) {
report.append( " ");
report.append(arr[i].toString());
report.append(SINGLE_LINE_SEP);
}
report.append(lineSeperator);
// If the exception was thrown in a background thread inside
// AsyncTask, then the actual exception can be found with getCause
report.append("--------- Cause ---------\n\n");
Throwable cause = e.getCause();
if (cause != null) {
report.append(cause.toString());
report.append(DOUBLE_LINE_SEP);
arr = cause.getStackTrace();
for (int i = 0; i < arr.length; i++) {
report.append(" ");
report.append(arr[i].toString());
report.append(SINGLE_LINE_SEP);
}
}
// Getting the Device brand,model and sdk verion details.
report.append(lineSeperator);
report.append("--------- Device ---------\n\n");
report.append("Brand: ");
report.append(Build.BRAND);
report.append(SINGLE_LINE_SEP);
report.append("Device: ");
report.append(Build.DEVICE);
report.append(SINGLE_LINE_SEP);
report.append("Model: ");
report.append(Build.MODEL);
report.append(SINGLE_LINE_SEP);
report.append("Id: ");
report.append(Build.ID);
report.append(SINGLE_LINE_SEP);
report.append("Product: ");
report.append(Build.PRODUCT);
report.append(SINGLE_LINE_SEP);
report.append(lineSeperator);
report.append("--------- Firmware ---------\n\n");
report.append("SDK: ");
report.append(Build.VERSION.SDK);
report.append(SINGLE_LINE_SEP);
report.append("Release: ");
report.append(Build.VERSION.RELEASE);
report.append(SINGLE_LINE_SEP);
report.append("Incremental: ");
report.append(Build.VERSION.INCREMENTAL);
report.append(SINGLE_LINE_SEP);
report.append(lineSeperator);
Log.e("Report ::", report.toString());
Intent crashedIntent = new Intent(BaseActivity.this, SplashActivity.class);
crashedIntent.putExtra(EXTRA_CRASHED_FLAG, "Unexpected Error occurred.");
crashedIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
crashedIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(crashedIntent);
System.exit(0);
// If you don't kill the VM here the app goes into limbo
}
Also see:
Android UncaughtExceptionHandler that instantiates an AlertDialog breaks
Toast not showing up in UnCaughtExceptionHandler
How to start activity from UncaughtExceptionHandler if this is main thread crashed?
How i do it:
I have a BaseActivity which extends Activity, and in onCreate of the activity I set the UncaughtExceptionHandler. All my activities extend the BaseActivity instead of Activity.
Keys
Application.onCreate
, instead, you should create a BaseActivity
and set it on the onCreate
method of it.System.exit(0)
SplashActivity
, since it will be destroyed, instead, we can pass some error message or persist it in file.