8

我正在使用此代码来处理任何可能导致我的应用程序崩溃的未捕获异常。

public class ExceptionHandler implements java.lang.Thread.UncaughtExceptionHandler {
    private final Context myContext;

    public ExceptionHandler(Context context) {

        myContext = context;
    }

    public void uncaughtException(Thread thread, Throwable exception) {

        Toast.makeText(myContext,
                "The application has crashed, and a report is sent to the admin",
                Toast.LENGTH_SHORT).show();
        StringWriter stackTrace = new StringWriter();
        exception.printStackTrace(new PrintWriter(stackTrace));
        System.err.println(stackTrace);// You can use LogCat too
        Intent intent = new Intent(myContext, CrashActivity.class);
        myContext.startActivity(intent);
        Process.killProcess(Process.myPid());
        System.exit(10);
    }
}

当我使用已知但未捕获的异常(只是为了测试)运行它时,会调用活动“CrashActivity”,但必须在它之前出现的 Toast 没有出现。

实际上我只想显示 Toast 然后调用 myContext.finish(); 而不是去 CrashActivity。但那吐司在不可见。

我哪里错了?

4

3 回答 3

9

Found this question while googling for exact the same problem. As far as I can tell it is not necessary to have the Toast.show() called from the UI thread as long as there is an Application context.

AFAIK: The problem that here occurs is the following: You're trying to show a Toast and immediately afterwards your application is shut down by the VM, which means your Toast is shutdown as well.

A solution for the problem is the following:

  • Run the Toast from a sepearate Thread
  • Delay shutdown of your application in the Uncaught Exception Handler.

What I do is the following:

In Application::onCreate():

Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread thread, Throwable ex)
    {
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(getApplicationContext(), "Application crashed", Toast.LENGTH_LONG).show();
                Looper.loop();
            }
        }.start();

        try
        {
            Thread.sleep(4000); // Let the Toast display before app will get shutdown
        }
        catch (InterruptedException e)
        {
            // Ignored.
        }
    }
});

It is similiar to how the Toast notification in ACRA works (in fact this is where I got the hint from).

于 2012-11-07T18:40:23.480 回答
4

System.exit(0)从 Android 内部调用UncaughtExceptionHandler有助于应用程序从错误中恢复并重新启动上一个 Activity。恕我直言,用户体验得到显着改善。但是,这种方法需要在多个安卓平台上进行尝试和测试。已在 GB 和 JB 上尝试过。它工作得很好。此外,我从其他人(我是 Android 新手)那里听说,System.exit()在 Android 中不推荐调用,但 .. 可以将其用作 android 应用程序崩溃的一个很好的恢复选项。

    public void uncaughtException(Thread thread, Throwable ex) {
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();  
                Toast.makeText(YourActivity.this, "Application has Crashed. Recovering now.", Toast.LENGTH_LONG).show();
                /* Log relevant message/analytics from here. */
                System.exit(1);
                Looper.loop();
            }
        }.start();
    }
于 2013-03-07T13:36:09.370 回答
3

您可能正在从线程调用 Toast,而应该从 UI 线程调用 Toast...

如果这没有帮助,请向我们提供 logcat 输出,以便我们查看您遇到的错误类型。

于 2012-07-23T09:26:28.217 回答