ANR产生的原因就不赘述了,这篇文章也不会过多的涉及源码分析
问题分解
要实现捕获ANR功能,简单来说,需要解决以下问题:
去哪里获取?
什么时候去获取?
一 FileObserver
使用FileObserver监听/data/anr目录,
new FileObserver("/data/anr",8){
@Override
public void onEvent(int event, @Nullable String path) {
if(path != null) {
String var3 = "/data/anr/" + path;
if(var3.contains("trace")) {
}
}
}
};
在FileObserver创建的时候可以传入一个mask参数,8正是代表着CLOSE_WRITE这个常量,当有写入并且close的时候将会回调.
实际测试几部手机,当发生ANR的时候,都没有回调到onEvent方法了.
不同型号的手机,有的手机会在/data/anr目录下生成以"trace"开头的txt,有的是把堆栈信息存到traces.txt里,使用pull 或者cat命令提示;remote open failed: Permission denied,显而易见高版本(网传5.0以上系统,这个交给读者自己试试了)的权限不允许我们访问。
我得出结论:
最大的困难是兼容性问题,这个方案受限于Android系统的SELinux机制,5.0以后基本已经使低权限应用无法监听到trace文件了,但是可以在开发内测阶段通过root手机修改app对应的te文件提权进行监控。
SELinux(或SEAndroid)将app划分为主要三种类型(根据user不同,也有其他的domain类型):
untrusted_app:第三方app,没有android平台签名,没有system权限
platform_app:有android平台签名,没有system权限
system_app:有android平台签名和system权限
从上面划分,权限等级,理论上:untrusted_app < platform_app < system_app
显而易见一般我们的app属于platform_app
二 WathDog模式
WathDog模式是参考Android WatchDog机制(com.android.server.WatchDog.java)起个单独线程向主线程发送一个变量+1操作,自我休眠自定义ANR的阈值,休眠过后判断变量是否+1完成,如果未完成则告警。
ANR-WatchDog就是一个线程,核心代码如下:
_uiHandler是通过主线程的Looper获得的Handler。
private final Handler _uiHandler = new Handler(Looper.getMainLooper());
_ticker是实现了Runnable接口的类,是要再主线程执行的方法
private final Runnable _ticker = new Runnable() {
@Override public void run() {
_tick = (_tick + 1) % Integer.MAX_VALUE;
}
};
_tick = (_tick + 1) % Integer.MAX_VALUE; 核心的逻辑就是一个很小的数对一个比他大很多的数取余,余数是他自己
优点:
兼容性好,各个机型版本通用
无需修改APP逻辑代码,非侵入式
逻辑简单,性能影响不大
参考链接:1.https://codezjx.com/2017/08/06/anr-trace-analytics/
2.https://blog.csdn.net/J_bing/article/details/47146953
3.https://blog.csdn.net/koma_mj/article/details/81448916
4.https://github.com/SalomonBrys/ANR-WatchDog
5.http://www.10tiao.com/html/212/201802/2247484608/1.html
6.https://blog.csdn.net/nature_fly088/article/details/80640576
7.https://issuetracker.google.com/issues/36951741
8.http://androidxref.com/
9.https://www.jianshu.com/p/17b0ac9b40fa