【问题标题】:Android catch unhandled exception and show the dialogAndroid 捕获未处理的异常并显示对话框
【发布时间】:2014-06-08 20:41:31
【问题描述】:

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

所以我写了一个代码。

活动:

@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 方法中的逻辑不起作用。什么问题以及如何解决?

【问题讨论】:

  • 定义什么是不正确的?发生了什么以及您的 onClick 行为中的预期行为是什么?
  • 你期待什么,你看到了什么?即为什么你说'它不起作用'?
  • @ben75 我希望对话框将关闭,应用程序将在按下“退出”按钮时完成。
  • @MartinKonecny 预期行为我在之前对 ben75 的回答中描述。对话框刚刚显示,但点击未处理。
  • @SergeyShustikov 我也有这个问题。你找到解决办法了吗?

标签: android exception


【解决方案1】:

就我而言,我在线程运行函数中移动了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();
}

一切都完美无缺。

希望对您有所帮助。

【讨论】:

  • 您确定您处理过一次崩溃操作吗?因为我捕获了 2-3 个异常。
  • 当第一个异常发生时,我看到 alertdialog 和关闭按钮监听器,杀死我的应用程序。 2-3 个例外是什么意思?
  • 我的意思是 ARM 向我们的异常处理程序发送 2-3 次 uncaughtException(Thread thread, Throwable ex)
【解决方案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

【讨论】:

  • 但是点击没有被处理。我在调试中检查过。
  • 如果我删除我的 ReportHelper 我会得到一个编译错误,因为Thread.setDefaultUncaughtExceptionHandler 传递了实现Thread.UncaughtExceptionHandler 的参数。我希望你错过了这个。
  • 我将日志放入uncaughtException(Thread thread, Throwable ex),我看到了神奇的行为。这个方法从不同的线程调用了 3 次。
【解决方案3】:

由于 UI-Thread 发生异常:该线程的状态可能出乎意料

所以在你的点击处理程序中简单地试试这个:

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

                }
            });

【讨论】:

    猜你喜欢
    • 2017-07-22
    • 1970-01-01
    • 2016-02-28
    • 1970-01-01
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 2017-11-25
    • 1970-01-01
    相关资源
    最近更新 更多