Android 收集崩溃信息并上传

 

Android 收集崩溃信息并上传

标签: android崩溃
  169人阅读  评论(0)  收藏  举报
  分类:
项目相关(10) 

对于任何应用程序而言,线上崩溃都是不可避免的。毕竟完全依靠测试同学的测试,是无法测试出所有问题的。 
所以收集线上应用崩溃的信息,并上传到服务器就显得格外重要了。

收集崩溃信息并上传的步骤: 
1 收集崩溃信息并保存 
2 应用崩溃后如何处理 
3 下次启动发送崩溃信息

这里导致崩溃的异常为Java Exception,即UnChecked Exception。还有一个Native异常这里先不做讨论。 
能够引起App Crash的为UnChecked Exception(即我们通常说的RunTime 异常), 
理论上来说我们可以利用try cache将异常捕获。 
但是我们不能将所有的代码全部try cache,而且除非我们特意抛出RunTime异常,否则当异常发生时,我们是不知道下一步逻辑该如何处理的。

如何收集?

当UnChecked异常发生时,系统会通知接口UncaughtExceptionHandler,回调uncaughtException()方法。 
我们可以利用其回调的参数,收集异常的堆栈信息。

代码 1public static class UnhandledExceptionHandler implements Thread.UncaughtExceptionHandler {

        private Thread.UncaughtExceptionHandler uncaughtExceptionHandler;

        public UnhandledExceptionHandler(Thread.UncaughtExceptionHandler uncaughtExceptionHandler) {
            this.uncaughtExceptionHandler = uncaughtExceptionHandler;
        }

        @Override
        public void uncaughtException(Thread thread, Throwable ex) {
            //收集异常信息
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
代码 2:
/**
     * 收集异常信息
     * @param throwable
     */
    private static void getStackTraceInfo(Throwable throwable) {
        Writer wr = new StringWriter();
        PrintWriter pwr = new PrintWriter(wr);
        throwable.printStackTrace(pwr);
        //将崩溃堆栈信息保存到SharedPreferences中
        SPHelper.getInstance().setString(SPConstant.LAST_ERROR_REPORT, wr.toString());
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

当异常发生时,会调用终止当前线程,并通知UncaughtExceptionHandler接口,如果没有显示设置handler,系统会通知默认的Handler. 
我们要捕获当前线程的崩溃信息,需要设置为当前线程设置handler。

即调用接口: 
static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

我们可以看一下这个接口的说明: 
Set the default handler invoked when a thread abruptly terminates due to an uncaught exception, 
and no other handler has been defined for that thread.

即这个接口是针线程的。 
一般我们会监控UI线程。所以我们可以在Application onCreate()方法中将其设置进去。

代码 3Thread.setDefaultUncaughtExceptionHandler(new UnhandledExceptionHandler(Thread.getDefaultUncaughtExceptionHandler()));
  • 1
  • 2
  • 1
  • 2

那么我们为什么要传入defaultUncaughtExceptionHandler 的实例呢?

因为我们显示的设置了Handler,异常不会走Android的默认异常设置,这里传入defaultUncaughtExceptionHandler 是希望当我们收集完异常信息后, 
依然希望调用Android默认的异常处理,即杀死进程,防止出现进程不可交互的状态。 
这里便是我们之前说的第二布,崩溃之后的处理。崩溃之后收集好堆栈信息,依然走Android默认处理逻辑。

完整如下: 
代码 4:

public class CrashReporter {

    public static class UnhandledExceptionHandler implements Thread.UncaughtExceptionHandler {

        private Thread.UncaughtExceptionHandler uncaughtExceptionHandler;

        public UnhandledExceptionHandler(Thread.UncaughtExceptionHandler uncaughtExceptionHandler) {
            this.uncaughtExceptionHandler = uncaughtExceptionHandler;
        }

        @Override
        public void uncaughtException(Thread thread, Throwable ex) {
            try {
                //收集崩溃信息
                getStackTraceInfo(ex);
            }finally {
                //走Android默认的崩溃处理逻辑
                uncaughtExceptionHandler.uncaughtException(thread, ex);
            }
        }
    }

    /**
     * 收集异常信息
     * @param throwable
     */
    private static void getStackTraceInfo(Throwable throwable) {
        Writer wr = new StringWriter();
        PrintWriter pwr = new PrintWriter(wr);
        throwable.printStackTrace(pwr);
        //将崩溃堆栈信息保存到SharedPreferences中
        SPHelper.getInstance().setString(SPConstant.LAST_ERROR_REPORT, wr.toString());
    }

    public void report() {
        //上传崩溃信息
    }
  • 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
  • 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

最后在应用下次启动时,可以调用report()方法,上传崩溃信息。当然可能还需要同时上传一些手机型号,系统版本等相关信息。

你可能感兴趣的:(android)