记录它后Rethrow UncaughtExceptionHandler异常

时间:2012-01-29 04:30:53

标签: android eclipse exception exception-handling

在我的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();
    }
}

}

4 个答案:

答案 0 :(得分:13)

道歉,不是Android专家 - 但看起来你不能抛出ex,因为你的方法签名“void uncaughtException(Thread,Throwable)”并没有声明它“抛出”任何东西。

假设你覆盖了一个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()方法)。