概述
AMS 和 WMS 会检测App的响应时间,如果App在特定时间无法响应屏幕触摸或键盘输入时间,或者特定事件(生命周期等)没有处理完毕,就会出现 ANR(Application Not Responding)。
ANR 一般有以下几种类型:
- KeyDispatchTimeout: input 事件在 5s 内没有处理完成, logcat 关键字:
Input dispatching timed out
。 - BroadcastTimeout: 前台广播 onReceiver 在 10S 内没有处理完成,后台广播 onReceiver 在 60s 内没有处理完成, logcat 关键字:
Timeout of broadcast BroadcastRecord
。 - ServiceTimeout: 前台服务 onCreate, onStart, onBind 等生命周期在20s内没有处理完成,后台服务 onCreate, onStart, onBind 等生命周期在 200s 内没有处理完成, logcat 关键字:
Timeout executing service
。 - ContentProviderTimeout: ContentProvider 在 10s 内没有处理完成, logcat 关键字:
timeout publishing content providers
。
案例分析
发生 ANR 后在日志中搜索关键字 ANR
可以看到如下日志:
1 | 2021-03-12 19:52:42.224 2092-2171/? E/ActivityManager: ANR in com.hearing.demo (com.hearing.demo/.MainActivity) |
从上面可以看到发生 ANR 的时间,进程及 ANR 类型,由此可以根据进程过滤一下日志,然后由于该类型是 KeyDispatchTimeout, 所以可以重点看一下 5s 前有没有关键信息。
最关键的解决办法是从 /data/anr/
下 pull 出 anr 相关的日志文件,里面有 ANR 发生的堆栈信息。
在确定了大概位置后还可以通过 CPU Profile 工具查看具体方法的执行时长。
线上ANR处理
线上可以使用 ANRWatchDog 开源库:
1 | public class ANRWatchDog extends Thread { |