Android 全局异常处理

  • 简介

        app崩溃,这个是大家都会遇到的问题,如果是我们自测,这个easy,我们很容易根据日志找到原因。但是有的时候并不会那么理想。 比如本人要和一个国内电视机厂商合作,因为应用都是内置到系统,并且一个人负责几个app。因为不在同一个城市,每次整机升级的时候都很痛苦。因为对方的测试也的确要测试很多东西。他们基本没时间帮你抓日志。直接把系统日志抛出来,基本都是那种20m以上的日志。这个时候就脑袋疼了。还有一点就是每次崩溃,都有一个提示框出来,也不美观。 让人觉得比较low。所以我们就需要自己处理app整体流程的崩溃。好了,吐槽完毕,上代码。

  • 代码分析

   1  首先是一个实现了UncaughtExceptionHandler接口的类,这个类来捕获app内部异常。

public class CrashCatchHandler implements Thread.UncaughtExceptionHandler {

    private static CrashCatchHandler INSTANCE;
    private Context mContext;
    private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/log/";

    private CrashCatchHandler() {

    }

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

    public void init(Context c) {
        //这里的c应该是全局的。
        if (c == null) {
            System.out.println("the context cann't be empty ");
            return;
        }
        mContext = c;
    }


    @Override
    public void uncaughtException(Thread t, Throwable e) {

        //如果是测试,那么只要写入本地日志即可,然后让测试拿到日志就可以。
        writeToFile(e);
        //在测试的时候无需上报
        uploadToServer();

        //杀死这个进程避免类似ios直接退出。
        Process.killProcess(Process.myPid());
    }

    /**
     * 把错误日志写到文件中。
     */
    private void writeToFile(Throwable ex) {
        //在这里需要确认具体的存储路径
        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            return;
        }

        File dir = new File(PATH);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        File file = new File(PATH + time + ".txt");
        try {
            PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
            //导出发生异常的时间
            pw.println(time);
            pw.println();
            //导出异常的调用栈信息
            ex.printStackTrace(pw);

            pw.close();
        } catch (Exception e) {
        }
    }

    /**
     * 将错误日志上传到服务器
     */
    private void uploadToServer() {

    }
}

   其中最重要的是实现uncaughtException()这个函数,我们通过源码中可以看到,这个thread发生异常的时候会触发。

 /**
     * Interface for handlers invoked when a <tt>Thread</tt> abruptly
     * terminates due to an uncaught exception.
     * <p>When a thread is about to terminate due to an uncaught exception
     * the Java Virtual Machine will query the thread for its
     * <tt>UncaughtExceptionHandler</tt> using
     * {@link #getUncaughtExceptionHandler} and will invoke the handler's
     * <tt>uncaughtException</tt> method, passing the thread and the
     * exception as arguments.
     * If a thread has not had its <tt>UncaughtExceptionHandler</tt>
     * explicitly set, then its <tt>ThreadGroup</tt> object acts as its
     * <tt>UncaughtExceptionHandler</tt>. If the <tt>ThreadGroup</tt> object
     * has no
     * special requirements for dealing with the exception, it can forward
     * the invocation to the {@linkplain #getDefaultUncaughtExceptionHandler
     * default uncaught exception handler}.
     *
     * @see #setDefaultUncaughtExceptionHandler
     * @see #setUncaughtExceptionHandler
     * @see ThreadGroup#uncaughtException
     * @since 1.5
     */
    @FunctionalInterface
    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);
    }

2 实现了这个接口之后,需要注册一下。需要在application的子类中实现。

public class MyApp extends MultiDexApplication {

    @Override
    public void onCreate(){
        super.onCreate();
        CrashCatchHandler crashHandler = CrashCatchHandler.getInstance();
        crashHandler.init(this);
        Thread.setDefaultUncaughtExceptionHandler(crashHandler);
    }
}

 这样注册之后,就可以是实现捕获程序里面的错误日志了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值