开发app过程中我,我们经常会遇到程序崩溃的问题,默认的处理方式是弹出一个crash的对话,点击后程序就会被关闭,与此同时,log日志也会有响应的错误栈打印。
那有没有办法在程序崩溃时,自行处理crash,比如将错误日志输出后,上传到服务器,然后重启app。这种场景就需要我们去自定义崩溃处理流程。
本文分为三部分,第一部分对android源码的crash流程进行分析,第二部分介绍如何自定义一个崩溃处理器,第三部分介绍如何去处理jni层的崩溃。
一、 Java层Crash源码流程分析。我们先来看下源码的RuntimeInit.class类,该类有一个静态的main方法,该方法会在android启动的过程中,被调用。
我们来看下CommonInit(),这里对线程设置了一个默认的异常处理器,从名字中也可以看出,设置的是java层未捕获的异常处理。
KillApplicationHandler:负责处理关闭app的处理器。
LoggingHandler:负责处理相关日志。
先来看下KillApplicationHandler:
-
首先调用了Log处理器,出现异常相关log
-
尝试停掉当前线程。
-
弹出错误弹窗,待用户点击确定。
最后会尝试杀死线程并退出。
整个报错流程就结束了,我们回头再来看下日志相关handler的处理。
主要就是处理日志的输出。
整个崩溃处理流程的源码相对来说还是比较简单,不难发现,如果要自定义处理器,那么有两个关键点。
-
需要重新设置处理器,也就是这个地方。
-
处理器需要实现相关接口,并重写uncaughtException方法,在方法中实现对异常的处理。
有了以上的分析,接下来我们来自定义一个crashHandler处理器。
二、 Java层自定义crashHandler,自行处理崩溃。首先我们要定义一个类,先实现相关接口,对外暴露一个init方法,该方法中,首先存储了默认的处理器(目的是,如果后面需要用到默认处理器,还能进行调用),接下来设置了我们当前自定义的处理器。
接下来就是重写handleException方法,定义对错误的处理。这里我们是通过一个流,将错误相关信息,写到了本地。最后在finally中,我们还可以直接调用系统默认的方法,关闭当前app。
假设如果不走系统的调用,则当前app会一直黑屏,无法退出。所以建议如果没有特殊的业务需求,在finally中,还是要调用下默认的处理机制。
至此,java层的异常处理机制就结束了。
三、 Jni层Crash处理。-
Jni crash处理思路。
对于jni层的crash,处理起来会比java层麻烦很多,因为在jni层,报错通常是以信号量signal。当Linux应用程序在执行时发生严重错误,一般会导致程序崩溃。其中,Linux专门提供了一类crash信 号,在程序接收到此类信号时,缺省操作是将崩溃的现场信息记录到核心文件,然后终止进程。
当jni层发生异常时,会产生一个墓碑文件记录崩溃的现场信息的文件,而这个文件在Android系统中就是 tombstones 墓碑文件。(墓碑文件位于路径/data/tombstones/下
)
这里需要借助Google的breakpad,一个跨平台的崩溃转储和分析框架和工具集合,其开源地址是:https://github.co m/google/breakpad。
breakpad在Linux中的实现就是借助了Linux信号捕获机制实现的。因为其实现 为C++,因此在Android中使用,必须借助NDK工具。
接下来我们来看具体实现。
-
jni层crash处理实现。
-
以ndk开发的方式引入breakpad,加入编译中进行编译。
-
编写jni层接口,并在接口中调用breakpad相关初始化,这里注意,要传入一个crash发生时的处理回调。
此时,若发生crash,DumpCallback将收到回调。我们可以直接在jni层中去做crash的相关处理,也可以将crash继续往上回调,交由java层去处理。



