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のみを表示してから、myContext.finish();を呼び出したいと思いました。CrashActivityに行く代わりに。しかし、そのトーストは見えません。

私はどこが間違っていますか?

4

3 に答える 3

9

まったく同じ問題をグーグルで検索しているときに、この質問が見つかりました。Toast.show()私が知る限り、アプリケーションコンテキストがある限り、UIスレッドから呼び出される必要はありません。

AFAIK:ここで発生する問題は次のとおりです。Toastを表示しようとしていて、その直後にアプリケーションがVMによってシャットダウンされます。つまり、Toastもシャットダウンされます。

この問題の解決策は次のとおりです。

  • 別のスレッドからトーストを実行します
  • UncaughtExceptionHandlerでアプリケーションのシャットダウンを遅らせます。

私がしていることは次のとおりです。

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.
        }
    }
});

これは、ACRAのトースト通知がどのように機能するかと似ています(実際、これは私がヒントを得た場所です)。

于 2012-11-07T18:40:23.480 に答える
4

System.exit(0)Android内から呼び出すと、UncaughtExceptionHandlerアプリケーションがエラーから回復し、最後のアクティビティを再起動するのに役立ちます。私見ですが、ユーザーエクスペリエンスが大幅に向上します。ただし、このアプローチは、複数のAndroidプラットフォームで試してテストする必要があります。GBとJBでこれを試しました。それはうまくいきました。さらに、他の人(私はAndroidを初めて使用します)から、Androidでの呼び出しSystem.exit()は推奨されていないと聞きましたが、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

トーストはUIスレッドから呼び出す必要がありますが、おそらくスレッドからトーストを呼び出しています...

これで問題が解決しない場合は、logcatの出力を提供してください。これにより、発生しているエラーの種類を確認できます。

于 2012-07-23T09:26:28.217 に答える