ANR的概念
ANR (Application Not Responding) 应用程序无响应。如果你的应用程序在UI线程被阻塞太长时间就会出现ANR 通常出现ANR,系统会弹出一个提示对话框,让用户知道,该程序正在被阻塞,是否等待还是关闭。
ANR的类型
-
KeyDispathTimeout(常见)
- input事件在5s内没有处理完成发生了ANR
- logcat日志关键字:Input event dispatching timed out
注意: input的超时机制和其他不同,对于input来说即使某次事件执行时间超过timeout时长,只要用户后续没有再生成输入事件,就不会触发ANR
-
BroadcastTimeOut
- 前台Broadcast: onReceive在10s内没有处理完成发生ANR。
- 后台Broadcast: onReceiver在60s内没有处理完成发生ANR。
- logcat日志关键字: Timeout of broadcast BroadcastRecord
- 根据发送广播sendBroadcast(Intent intent)中的intent的flags是否包含FLAG_RECEIVER_FOREGROUND来决定把该广播是放入前台广播队列或者后台广播队列,默认都是后台广播
-
ServiceTimeOut
- 前台Service: onCreate onStart onBind 等生命周期内20s内没有处理完成发生ANR
- 后台Service: onCreate onStart onBind 等生命周期内200s内没有处理完成发生ANR
- logcat日志关键字: Timeout executing service
-
ContentProviderTimeOut
- ConentProvider 在10S内没有处理完成发生ANR
- logcat日志关键字: timeout publishing content providers
前台与后台ANR
决定是前台或者后台ANR取决于该应用发生ANR时对用户是否可感知
可以看到 如果是后台ANR那么就直接关闭 如果是前台ANR就弹出对话框 当前用户在界面上
ANR是怎么产生的
Service 是在startService中
静态广播 超时检测过程需要检测SP
动态广播 静态广播没有正在执行持久化操作的SP任务,则不需要经过 queued-work-looper线程
ContentProvider超时机制
ContentProvider的超时是在ContentProvider进程首次启动的时候才会检测,当ContentProvider进程已启动的场景,再次请求ContentProvider并不会触发ContentProvider超时。
input超时机制
常见ANR操作
- 主线程进行IO操作比如 操作数据库 网络请求 文件操作。 sp文件操作 IO读写操作都不在主线程 序列化
- 多线程导致的死锁,主线程被block.
- 主线程通信被对端的Binder对端 block住了
- System Server中WatchDog出现ANR
- service binder的连接达到上线无法和System Server通信
- 系统资源已耗尽(cpu 管道 io)
ANR如何定位分析
线下:anr发生后会有日志
logcat:会有日志 会产生 /data/anr/trace_*.txt 文件
在Android手机上 没有root 无法访问那么 /data/anr/trace.txt
那么我们可以使用adb bugreport anrlog.zip 就可以了
读懂trace.txt文件
- 通过logcat日志,traces文件确认anr发生的时间点
- trace文件和CPU使用率/data/anr/trace_*.txt
- 通过firstPid来查看主线程的状态
- 其他线程的状态
如何监控线上的ANR
-
FileObserver:监控某个目录/文件 状态发生改变 创建 删除文件 添加内容 监听data/anr/目录是否发生变化 然后上传data/anr/trace*.txt 但是在 fileoberver 被selinux挡住 5.0之后肯定会 系统开发可以修改 .te配置文件修改
-
watchDog来监控方案
继承Thread向主线程发送一个handler判断是否 -
线上集成bugly
bugly会集成 手机品牌 型号 配置 大概位置 然后通过money 复现