线程的 DefaultUncaughtExceptionHandler 未捕获 AlertDialog onClick() 方法中抛出的异常
Thread's DefaultUncaughtExceptionHandler not catching exception thrown in AlertDialog onClick() method
我在 Activity
的 onCreate()
中为当前线程设置了默认值 UncaughtExceptionHandler
,并从 AlertDialog
的 onClick()
侦听器但未捕获异常。我还尝试从 onCreateOptionsMenu()
和 onOptionsItemSelected()
抛出异常,但没有被捕获。然而,当从 onCreate()
或 onResume()
抛出时,它会被捕获。
这是我的 activity:
public class MainActivity extends AppCompatActivity implements DialogInterface.OnClickListener {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread.setDefaultUncaughtExceptionHandler(new DefExcHandler());
Log.d(TAG, "onCreate: "+Thread.currentThread().getName()+" "+Thread.currentThread().getId());
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setNeutralButton("CRASH", this);
AlertDialog dialog = builder.create();
dialog.show();
dialog.setCancelable(false);
dialog.setCanceledOnTouchOutside(false);
}
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
Log.d(TAG, "onClick: "+Thread.currentThread().getName()+" "+Thread.currentThread().getId());
throw new RuntimeException();
}
}
这是我的异常处理程序:
public class DefExcHandler implements Thread.UncaughtExceptionHandler {
private static final String TAG = "DefExcHandler";
public DefExcHandler() {
Log.d(TAG, "DefaultExceptionHandler: ");
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
Log.d(TAG, "Uncaught exception caught: "+ex.getMessage()+" "+ex.getCause().toString());
}
}
根据我在 activity 中创建的日志消息,线程在 onCreate()
和 onClick()
中是相同的:
09-27 15:00:57.260 10667-10667/a.b.c D/MainActivity: onCreate: main 1
09-27 15:01:52.680 10667-10667/a.b.c D/MainActivity: onClick: main 1
为什么从 onClick()
、onCreateOptionsMenu()
或 onOptionsItemSelected()
抛出的异常没有被捕获?
我试图重现应用程序的行为。 DefExcHandler
实例似乎被遗漏了,因为它没有记录任何内容,但我尝试了另外两个有效的方法:断点和文件创建。
请尝试在uncaughtException()
内设置断点。我相信它会停止在您的代码中执行。我在下面写了一个例子,它使用一个文件作为标志来指示未捕获的异常处理程序确实被调用了。
总之,似乎 DefExcHandler.uncaughtException()
正在被调用,但 Android 无法进行日志记录,原因不明,可能是内部竞争条件。
// Example that assures that an UncaughtExceptionHandler
// is being invoked by flagging execution with file creation.
public class MainActivity extends ... implements ... {
private File mCrashFile;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCrashFile = new File(getFilesDir(), "crash");
// Crash file existence means the application has crashed before.
Log.d(TAG, "crash file exists: " + mCrashFile.exists());
// Clear crash flag.
if (mCrashFile.exists()) {
Log.d(TAG, "crash file delete: " + mCrashFile.delete());
}
Thread.setDefaultUncaughtExceptionHandler(new DefExcHandler());
...
}
private class DefExcHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
// Set crash flag.
try {
mCrashFile.createNewFile();
} catch (IOException e) {
// dunno if it really prints anything
e.printStackTrace();
}
}
}
}
我在 Activity
的 onCreate()
中为当前线程设置了默认值 UncaughtExceptionHandler
,并从 AlertDialog
的 onClick()
侦听器但未捕获异常。我还尝试从 onCreateOptionsMenu()
和 onOptionsItemSelected()
抛出异常,但没有被捕获。然而,当从 onCreate()
或 onResume()
抛出时,它会被捕获。
这是我的 activity:
public class MainActivity extends AppCompatActivity implements DialogInterface.OnClickListener {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread.setDefaultUncaughtExceptionHandler(new DefExcHandler());
Log.d(TAG, "onCreate: "+Thread.currentThread().getName()+" "+Thread.currentThread().getId());
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setNeutralButton("CRASH", this);
AlertDialog dialog = builder.create();
dialog.show();
dialog.setCancelable(false);
dialog.setCanceledOnTouchOutside(false);
}
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
Log.d(TAG, "onClick: "+Thread.currentThread().getName()+" "+Thread.currentThread().getId());
throw new RuntimeException();
}
}
这是我的异常处理程序:
public class DefExcHandler implements Thread.UncaughtExceptionHandler {
private static final String TAG = "DefExcHandler";
public DefExcHandler() {
Log.d(TAG, "DefaultExceptionHandler: ");
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
Log.d(TAG, "Uncaught exception caught: "+ex.getMessage()+" "+ex.getCause().toString());
}
}
根据我在 activity 中创建的日志消息,线程在 onCreate()
和 onClick()
中是相同的:
09-27 15:00:57.260 10667-10667/a.b.c D/MainActivity: onCreate: main 1
09-27 15:01:52.680 10667-10667/a.b.c D/MainActivity: onClick: main 1
为什么从 onClick()
、onCreateOptionsMenu()
或 onOptionsItemSelected()
抛出的异常没有被捕获?
我试图重现应用程序的行为。 DefExcHandler
实例似乎被遗漏了,因为它没有记录任何内容,但我尝试了另外两个有效的方法:断点和文件创建。
请尝试在uncaughtException()
内设置断点。我相信它会停止在您的代码中执行。我在下面写了一个例子,它使用一个文件作为标志来指示未捕获的异常处理程序确实被调用了。
总之,似乎 DefExcHandler.uncaughtException()
正在被调用,但 Android 无法进行日志记录,原因不明,可能是内部竞争条件。
// Example that assures that an UncaughtExceptionHandler
// is being invoked by flagging execution with file creation.
public class MainActivity extends ... implements ... {
private File mCrashFile;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCrashFile = new File(getFilesDir(), "crash");
// Crash file existence means the application has crashed before.
Log.d(TAG, "crash file exists: " + mCrashFile.exists());
// Clear crash flag.
if (mCrashFile.exists()) {
Log.d(TAG, "crash file delete: " + mCrashFile.delete());
}
Thread.setDefaultUncaughtExceptionHandler(new DefExcHandler());
...
}
private class DefExcHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
// Set crash flag.
try {
mCrashFile.createNewFile();
} catch (IOException e) {
// dunno if it really prints anything
e.printStackTrace();
}
}
}
}