Android捕获未处理的异常并显示对话框

时间:2014-06-08 20:41:31

标签: android exception

我想在没有任何第三方库的应用程序中处理未处理的异常。

所以我写了一段代码。

活动:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Thread.setDefaultUncaughtExceptionHandler(new ReportHelper(this));
    throw new NullPointerException();
}

我的崩溃处理程序:

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
import android.widget.Toast;

/**
 * Created by S-Shustikov on 08.06.14.
 */
public class ReportHelper implements Thread.UncaughtExceptionHandler {
    private final AlertDialog dialog;
    private       Context     context;

    public ReportHelper(Context context) {
        this.context = context;
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setMessage("Application was stopped...")
                .setPositiveButton("Report to developer about this problem.", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {

                    }
                })
                .setNegativeButton("Exit", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        // Not worked!
                        dialog.dismiss();
                        System.exit(0);
                        android.os.Process.killProcess(android.os.Process.myPid());

                    }
                });

        dialog = builder.create();
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        showToastInThread("OOPS!");
    }

    public void showToastInThread(final String str){
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(context, "OOPS! Application crashed", Toast.LENGTH_SHORT).show();
                if(!dialog.isShowing())
                    dialog.show();
                Looper.loop();

            }
        }.start();
    }
}

当我看到我抛出NullPointerException 时启动应用程序。显示了我处理逻辑中的Toast,并显示了对话框。但!对话框点击无法正确处理。我的意思是onClick方法中的逻辑没有奏效。问题是什么以及如何解决这个问题?

3 个答案:

答案 0 :(得分:5)

就我而言,我在线程运行函数中移动AlertDialog.Builder,如下所示:

public void showToastInThread(final String str){
    new Thread() {
        @Override
        public void run() {
            Looper.prepare();

            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setMessage("Application was stopped...")
            .setPositiveButton("Report to developer about this problem.", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {

                }
            })
            .setNegativeButton("Exit", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    // Not worked!
                    dialog.dismiss();
                    System.exit(0);
                    android.os.Process.killProcess(android.os.Process.myPid());

                }
            });

            dialog = builder.create();


            Toast.makeText(context, "OOPS! Application crashed", Toast.LENGTH_SHORT).show();
            if(!dialog.isShowing())
                dialog.show();
            Looper.loop();

        }
    }.start();
}

所有事情都很完美。

希望这能帮助你。

答案 1 :(得分:2)

根据this post,当调用setDefaultUncaughtExceptionHandler时,应用程序的状态是未知的。这意味着您的onClick侦听器可能不再处于活动状态。

为什么不使用这种方法:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    try {
        setContentView(R.layout.main);
        Thread.setDefaultUncaughtExceptionHandler(new ReportHelper(this));
        throw new NullPointerException();
    } catch (NullPointerException e) {
        new ReportHelper(this);
    }
}

并删除实现Thread.UncaughtExceptionHandler界面的ReportHelper。

您未明确捕获异常的方法可以被视为anti-pattern

答案 2 :(得分:0)

由于UI-Thread发生异常:此线程的状态可能意外

所以在点击处理程序中尝试这个:

.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    android.os.Process.killProcess(android.os.Process.myPid());

                }
            });