关于Android如何对应用进行Java Crash监控

问题

android开发或者运行过程中难免会出现Crash,如何持久化崩溃日志便于重新定位

知识点补充

Java中的Thread定义了一个接口UncaughtExceptionHandler用于处理未捕获的异常导致线程的终止(值得注意:已经被捕获的异常是捕获不到的)。

  • 当应用crash的时候,就会执行UncaughtExceptionHandler.uncaughtException方法 ,该方法可以获取到异常的信息。
  • 通过Thread.setDefaultUncaughtExceptionHandler 方法可以设置线程的默认异常处理器。
  • 通过Thread.getDefaultUncaughtExceptionHandler();方法可以拿到系统默认的异常处理对象(Android默认的是RuntimeInit.java内部类KillApplicationHandler的实例对象)。
   private static class KillApplicationHandler implements Thread.UncaughtExceptionHandler {
        private final LoggingHandler mLoggingHandler;

        public KillApplicationHandler(LoggingHandler loggingHandler) {
            this.mLoggingHandler = Objects.requireNonNull(loggingHandler);
        }

        @Override
        public void uncaughtException(Thread t, Throwable e) {
            try {
                ensureLogging(t, e);
                if (mCrashing) return;
                mCrashing = true;
                if (ActivityThread.currentActivityThread() != null) {
                    ActivityThread.currentActivityThread().stopProfiling();
                }
                ActivityManager.getService().handleApplicationCrash(
                        mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));
            } catch (Throwable t2) {
                if (t2 instanceof DeadObjectException) {
                } else {
                    try {
                        Clog_e(TAG, "Error reporting crash", t2);
                    } catch (Throwable t3) {
                    }
                }
            } finally {
                Process.killProcess(Process.myPid());
                System.exit(10);
            }
        }

解决方案

Application中调用init()方法即可
具体实现步骤

  • 获得系统默认的异常处理对象
  • 替换当前系统默认的异常处理对象为自行实现的异常处理对象
  • 在执行完后,再调用原系统默认的异常处理对象执行原有操作
public final class CrashHandler implements Thread.UncaughtExceptionHandler {

    private static final CrashHandler mCrashHandler = new CrashHandler();
    private static Thread.UncaughtExceptionHandler mDefaultExceptionHandler;
    private static Context mContext;
    private static final String FILE_NAME_SUFFIX = ".txt";

    private CrashHandler() {
    }

    public static void init(@NonNull Context context) {
        //获得默认的系统异常的异常处理对象
        mDefaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(mCrashHandler);
        mContext = context.getApplicationContext();
    }


    /**
     * 当程序中有未被捕获的异常,
     * 系统将会调用这个方法
     *
     * @param t 出现未捕获异常的线程
     * @param e 得到异常信息
     */
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        try {//自行处理:保存本地
            File file = dealException(t, e);
        } catch (Exception e1) {
            e1.printStackTrace();
        } finally { //交给系统默认程序处理
            if (null != mDefaultExceptionHandler) {
                mDefaultExceptionHandler.uncaughtException(t, e);
            }
        }
    }

    /**
     * 导出异常信息到本地
     *
     * @param e
     */
    private File dealException(Thread t, Throwable e) throws Exception {
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        File f = new File(mContext.getCacheDir().getAbsoluteFile(), "crash_info");
        if (!f.exists()) {
            f.mkdirs();
        }
        File crashFile = new File(f, time + FILE_NAME_SUFFIX);
        PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(crashFile)));
        pw.println(time);
        pw.println("Thread: " + t.getName());
        pw.println(getPhoneInfo());
        e.printStackTrace(pw); //写入crash堆栈
        pw.flush();
        pw.close();
        return crashFile;
    }

    /**
     * 用户信息
     *
     * @return
     */
    private String getPhoneInfo() {
        return "";//todo 自定义需要拼接的用户信息
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值