Android CrashHandler全局异常

CrashHandler 介绍

Android 应用不可避免的会发生crash 即崩溃,无论程序写的多好,都会不可避免的发生崩溃,可能是由底层引起的,也有可能是写的代码引起的。当crash发生时,系统会kill掉正在执行的程序,现象是程序闪退或提升用户已停止运行。出现这种情况,开发者却无法得到程序为何crash。Android 提供了处理这类问题的方法。
java的Thread中有一个UncaughtExceptionHandler接口,该接口的作用主要是为 了 当 Thread 因未捕获的异常而突然终止时,调用处理程序。


    public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
        // Android-removed: SecurityManager stubbed out on Android.
        /*
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(
                new RuntimePermission("setDefaultUncaughtExceptionHandler")
                    );
        }
        */

         defaultUncaughtExceptionHandler = eh;
     }

    public interface UncaughtExceptionHandler {
        /**
         * Method invoked when the given thread terminates due to the
         * given uncaught exception.
         * <p>Any exception thrown by this method will be ignored by the
         * Java Virtual Machine.
         * @param t the thread
         * @param e the exception
         */
        void uncaughtException(Thread t, Throwable e);
    }

使用


public class CrashHandler implements Thread.UncaughtExceptionHandler {

    public static final String TAG = "CrashHandler";

    private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/Crash/log";
    private static final String FILE_NAME = "crash";
    private static final String FILE_NAME_SUFFIX = ".trace";

    private static CrashHandler mInstance;
    private Context mContext;
    private Thread.UncaughtExceptionHandler mDefaultCrashHandler;

    public CrashHandler() {

    }

    public static synchronized CrashHandler getInstance() {
        if (mInstance == null) {
            synchronized (CrashHandler.class) {
                if (mInstance == null) {
                    mInstance = new CrashHandler();
                }
            }
        }
        return mInstance;
    }

    public void init(Context context) {
        mDefaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
        mContext = context.getApplicationContext();
    }


    /**
     * 当程序中有未被捕获的异常,系统将会自动调用uncaughtException方法
     *
     * @param thread 为出现未捕获异常的线程
     * @param ex     为未捕获的异常
     */
    @Override
    public void uncaughtException(@NonNull Thread thread, @NonNull Throwable ex) {
        try {
            //导出异常信息到SDCard中
            dumpExceptionToSDCard(ex);
            uploadExceptionToServer();
        } catch (IOException e) {
            e.printStackTrace();
        }

        ex.printStackTrace();
        //如果系统提供了默认异常处理器,则交给系统去结束程序,否则就由自己结束自己
        if (mDefaultCrashHandler != null) {
            mDefaultCrashHandler.uncaughtException(thread, ex);
        } else {
            Process.killProcess(Process.myPid());
        }
    }


    private void dumpExceptionToSDCard(Throwable ex) throws IOException {
        //判断SD是否存在
        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            //判断是否是Debug
            Log.w(TAG, "sdcard unmounted dump exception");
            return;
        }
        File dir = new File(PATH);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        long currentTimeMillis = System.currentTimeMillis();
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(currentTimeMillis);

        File file = new File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX);
        Log.i(TAG, "fileName:" + file.getName() + " , path:" + file.getPath());


        try {
            PrintWriter printWriter = new PrintWriter(new BufferedWriter(new FileWriter(file)));
            printWriter.println(time);
            dumpPhoneInfo(printWriter);
            printWriter.println();
            ex.printStackTrace(printWriter);
            printWriter.close();
        } catch (Exception e) {
            Log.e(TAG, "dump crash info failed");
            e.printStackTrace();
        }
    }

    private void dumpPhoneInfo(PrintWriter printWriter) throws PackageManager.NameNotFoundException {

        PackageManager pm = mContext.getPackageManager();
        PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
        printWriter.print("App Version: ");
        printWriter.print(pi.versionName);
        printWriter.print("_");
        printWriter.println(pi.versionCode);

        //Android 版本号
        printWriter.print("OS Version: ");
        printWriter.print(Build.VERSION.RELEASE);
        printWriter.print("_");
        printWriter.println(Build.VERSION.SDK_INT);

        //手机制造商
        printWriter.print("Vendor: ");
        printWriter.println(Build.MANUFACTURER);

        //手机型号
        printWriter.print("Model: ");
        printWriter.println(Build.MODEL);

        //CPU架构
        printWriter.print("CPU ABI: ");
        printWriter.println(Build.CPU_ABI);
    }

    private void uploadExceptionToServer() {
        // TODO upload Exception Message To Your Server
    }
}

在Applicaption 类中初始化

public class TestApplication extends Application {
 @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
        CrashHandler instance = CrashHandler.getInstance();
        instance.init(this);
    }
}

自己手动抛出一个异常

        addDisposable(RxView.clicks(mainBinding.settingIv)
                .throttleFirst(PDAConstant.CLICK, TimeUnit.SECONDS).subscribe(o -> {
                    throw new RuntimeException(" 自定义 exception");
                }));

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值