问题描述
在我的Android应用程序抛出一个异常,我想显示自定义对话框,告诉用户有什么不对的事,所以我用 Thread.setDefaultUncaughtExceptionHandler
来设置一个全局异常处理程序:
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.setDefaultUncaughtExceptionHandler
to set a global exception handler:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, final Throwable ex) {
AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext());
builder.setTitle("There is something wrong")
.setMessage("Application will exit:" + ex.toString())
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// throw it again
throw (RuntimeException) ex;
}
})
.show();
}
});
}
}
但我发现它有抛出的异常,在 AlertDialog
不会出现,相反,应用程序块,一段时间后,它会显示一个系统对话框:
But I found it there is any exception thrown, the AlertDialog
won't show, instead, the application blocks and after a while, it will show a system dialog:
X app is not responding. Would you like to close it?
Wait | OK
我应该怎么做呢?
What should I do now?
更新
日志:
11-16 12:54:16.017: WARN/WindowManager(90): Attempted to add window with non-application token WindowToken{b38bb6a8 token=null}. Aborting.
这似乎错误是来自新AlertDialog.Builder(getApplicationContext());
但是,这是一个异常处理程序应用程序
的子类,我怎么可以设置一个活动实例呢?
But this is an exception handler in Application
subclass, how can I set an activity instance to it?
推荐答案
您不能在这里做任何UI操作。刚开始另一项活动/闪屏。传递一个额外的意图表示崩溃,并在活动显示对话框。
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
}
另请参见:
Android UncaughtExceptionHandler的实例化一个AlertDialog打破
Toast没有出现在UncaughtExceptionHandler的了
How从UncaughtExceptionHandler的启动活动,如果这是主线程崩溃?
我如何做到这一点:
我有一个BaseActivity延伸活动,并在活动的onCreate我设置的UncaughtExceptionHandler。我所有的活动扩大活动的BaseActivity代替。
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.
键
- 您不能设置在异常处理程序
Application.onCreate
,相反,你应该创建一个BaseActivity
和在它的的onCreate
方法对其进行设置。 - 启动SplashActivity后,我们应该叫
System.exit(0)
- 我们不能持有错误的实例分享给
SplashActivity
,因为它会被破坏,相反,我们可以通过一些错误信息,或将其保留在文件中。
- You can't set the exception handler in
Application.onCreate
, instead, you should create aBaseActivity
and set it on theonCreate
method of it. - After starting the SplashActivity, we should call
System.exit(0)
- We can't hold the error instance to share it to
SplashActivity
, since it will be destroyed, instead, we can pass some error message or persist it in file.
这篇关于显示在'Thread.setDefaultUncaughtExceptionHandler`对话框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!