在我的Application类中,我试图在它发生之前捕获一个强制关闭,所以我可以记录它然后重新抛出它以便android可以处理它。我这样做是因为有些用户没有报告强制关闭。
我在eclipse中开发,eclipse不允许我重新抛出异常。它显示错误说“未处理的异常类型Throwable:Surround with try / catch”。我该如何重新抛出异常?
public class MainApplication extends Application
{
@Override
public void onCreate()
{
super.onCreate();
try
{
//Log exception before app force closes
Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
AnalyticsUtils.getInstance(MainApplication.this).trackEvent(
"Errors", // Category
"MainActivity", // Action
"Force Close: "+ex.toString(), // Label
0); // Value
AnalyticsUtils.getInstance(MainApplication.this).dispatch();
Toast.makeText(MainApplication.this, "Snap! Something broke. Please report the Force Close so I can fix it.", Toast.LENGTH_LONG);
//rethrow the Exception so user can report it
//throw ex; //<-- **eclipse is showing an error to surround with try/catch**
}
});
} catch (Exception e)
{
e.printStackTrace();
}
}
}
答案 0 :(得分:13)
假设你覆盖了一个API接口,并且(a)无法修改这个签名,并且(b)不想因为你将它抛出上下文,你可以改为使用装饰模式吗?子类默认的UncaughtExceptionHandler实现来记录你的消息,然后让它像往常一样继续处理?
编辑:未经测试,但这看起来有点像:
final UncaughtExceptionHandler subclass = Thread.currentThread().getUncaughtExceptionHandler();
Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
// your code
AnalyticsUtils.getInstance(MainApplication.this).trackEvent(
"Errors", // Category
"MainActivity", // Action
"Force Close: "+ex.toString(), // Label
0); // Value
AnalyticsUtils.getInstance(MainApplication.this).dispatch();
Toast.makeText(MainApplication.this, "Snap! Something broke. Please report the Force Close so I can fix it.", Toast.LENGTH_LONG).show();
// carry on with prior flow
subclass.uncaughtException(thread, ex);
}
});
答案 1 :(得分:0)
我不确定这是否是您想要的,但是您可以添加finally
子句,该子句将在成功try
或处理catch
之后运行:
try {
//your code
} catch (Exception e) {
//print stack trace
} finally {
//Log
}
答案 2 :(得分:0)
我认为以下代码应该可行。使用新线程执行处理程序代码允许应用程序显示警报/吐司并执行其他操作。
此外,您可以在退出System.exit(0)
之前尝试调用run()
。这会重新启动上一个活动。
我在 Ginger Bread 以及 Jelly Bean 上检查过这个。
final UncaughtExceptionHandler subclass = Thread.currentThread().getUncaughtExceptionHandler();
Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
new Thread() {
@Override
public void run() {
Looper.prepare();
// your code
AnalyticsUtils.getInstance(MainApplication.this).trackEvent(
"Errors", // Category
"MainActivity", // Action
"Force Close: "+ex.toString(), // Label
0); // Value
AnalyticsUtils.getInstance(MainApplication.this).dispatch();
Toast.makeText(MainApplication.this, "Snap! Something broke. Please report the Force Close so I can fix it.", Toast.LENGTH_LONG);
Looper.loop();
}
}.start();
}
});
答案 3 :(得分:0)
对于仅现在发现此问题的任何人,我不确定以上任何答案在发布时是否正确,但现在不是。如今,您想要创建一个实现Thread.UncaughtExceptionHandler
的新类,并在构造函数中,将Thread.getCurrentUncaughtExceptionHandler()
保存到字段中,然后在以下位置调用 its uncaughtException(Thread, Throwable)
您的 uncaughtException(Thread, Throwable)
方法的结尾。然后,您可以通过实例化您的类的任何代码(通常为Thread.setUncaughtExceptionHandler()
)调用MainApplication.onCreate
。
因此完整的代码如下:
//MainApplication.java
public class MainApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
CustomUncaughtExceptionHandler cueh = new CustomUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(cueh);
}
}
//CustomUncaughtExceptionHandler.java
class CustomUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
private Thread.UncaughtExceptionHandler oldHandler;
CustomUncaughtExceptionHandler() {
oldHandler = Thread.getDefaultUncaughtExceptionHandler();
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
AnalyticsUtils.getInstance(MainApplication.this).trackEvent(
"Errors", // Category
"MainActivity", // Action
"Force Close: "+ex.toString(), // Label
0); // Value
AnalyticsUtils.getInstance(MainApplication.this).dispatch();
if (oldHandler != null) {
oldHandler.uncaughtException(thread, ex);
else {
System.exit(1);
}
}
}
如果出于某种原因您决定不想再运行代码,也可以将原始的默认未捕获异常处理程序存储在其他地方,以便以后恢复(或添加getOldHandler()
方法)。