当前位置:   article > 正文

Android UncaughtExceptionHandler 解决未捕获异常,防止软件报”停止运行“_android uncaughtexception 获取不到异常

android uncaughtexception 获取不到异常

UncaughtExceptionHandler接口

这个接口就是处理程序中没有处理的异常,而且是在系统抛出异常导致程序异常终止之前!无论是空值针,参数异常等各种异常出现后,若代码中未进行处理,均会调用该接口。

具体处理步骤,如下:

1. 创建一个UncaughtExceptionHandler的具体实现类

/**
 * 未捕获异常捕捉类
 */
public class CrashHandlers implements Thread.UncaughtExceptionHandler {

    public static final String TAG = "CrashHandlers";

    // 系统默认的UncaughtException处理类
    private Thread.UncaughtExceptionHandler mDefaultHandler;

    // CrashHandler实例
    private static CrashHandlers instance;
    // 程序的Context对象
    private Context mContext;


    /**
     * 保证只有一个CrashHandler实例
     */
    private CrashHandlers() {
    }

    /**
     * 获取CrashHandler实例 ,单例模式
     */
    public synchronized static CrashHandlers getInstance() {
        if (instance == null) {
            instance = new CrashHandlers();
        }
        return instance;
    }

    /**
     * 初始化
     *
     * @param context
     */
    public void init(Context context) {
        mContext = context;
        // 获取系统默认的UncaughtException处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        // 设置该CrashHandler为程序的默认处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     * 当UncaughtException发生时会转入该函数来处理
     */
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if (!handleException(thread, ex) && mDefaultHandler != null) {
            // 如果用户没有处理则让系统默认的异常处理器来处理
            mDefaultHandler.uncaughtException(thread, ex);
        } else {
            try {
                //3秒后执行重启
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                Log.e(TAG, e.toString());
            }
            //发送广播重新启动APP
            mContext.sendBroadcast(new Intent("com.xin.crash"));
            //退出程序,否则无法重新启动
            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(1);
        }
    }

    /**
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
     *
     * @param ex
     * @return true-->处理了该异常信息
     *          false-->未处理异常.
     */
    private boolean handleException(Thread thread, Throwable ex) {
        if (ex == null) {
            //未处理异常,返回false
            return false;
        }
        // 使用Toast来显示异常信息
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                //捕获到异常,弹出提示
                Toast.makeText(APP.getInstance(), "即将重启", Toast.LENGTH_SHORT).show();
                Looper.loop();
            }
        }.start();
        return true;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94

2. 自定义Application类

public class APP extends Application {

    @override
    public void onCreate() {
        super.onCreate();
        CrashHandler handler = CrashHandler.getInstance();
        handler.init(getApplicationContext()); //在Appliction里面设置我们的异常处理器为UncaughtExceptionHandler处理器
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

3. Application类注册到AndroidManifest文件中

    <application
        android:name=".APP"
        ...
        >
    </application>
  • 1
  • 2
  • 3
  • 4
  • 5

4. 在代码中抛出异常,查看结果

附一:

在步骤一中,捕获异常后发送了广播,需通过另一个程序接收该广播,并进行启动的操作

public class Rece extends BroadcastReceiver {
    public static String TAG = "MyCrash";
    public static String PKGNAME= "com.test.crash";
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i(TAG,"收到广播");

        //执行启动
        Intent LaunchIntent = context.getPackageManager().getLaunchIntentForPackage(PKGNAME);
        LaunchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(LaunchIntent);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

附二:

若需当异常出现时,通过Dialog提示用户,部分代码如下:

   /**
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
     *
     * @param ex
     * @return true-->处理了该异常信息
     * false-->未处理异常.
     */
    private boolean handleException(Thread thread, Throwable ex) {
        if (ex == null) {
            //未处理异常,返回false
            return false;
        }
        // 使用Dialog来显示异常信息
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                //捕获到异常,弹出提示
                new AlertDialog.Builder(mContext).setTitle("提示").setCancelable(false)
                        .setMessage("程序崩溃了...").setNeutralButton("我知道了", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        //发送广播重新启动APP
                        mContext.sendBroadcast(new Intent("com.xin.crash"));
                        android.os.Process.killProcess(android.os.Process.myPid());
                        System.exit(1);
                    }
                }).create().show();
                Looper.loop();
            }
        }.start();
        return true;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 说明:Dialog必须依附于Activity之上,Application作为参数时无法弹出Dialog。因此,若需如此,UncaughtExceptionHandler这个类必须在Activity中的onCreate()中实现。Sample如下:
public class BaseActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        CrashHandler crashHandler = CrashHandler.getInstance();
        crashHandler.init(this);  //传入参数必须为Activity,否则AlertDialog将不显示。

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/245373
推荐阅读
相关标签
  

闽ICP备14008679号