ANR
概述
ANR(Application Not responding),是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR。一般地,这时往往会弹出一个提示框,告知用户当前xxx未响应,用户可选择继续等待或者Force Close。当出现ANR时,都是调用到AMS.appNotResponding()。
那么哪些场景会造成ANR呢?
一般来说,当在主线程(UI线程)进行耗时的操作时就很容易出现ANR
Service Timeout:比如前台服务在20s内未执行完成;
BroadcastQueue Timeout:比如前台广播在10s内未执行完成
ContentProvider Timeout:内容提供者,在publish过程超时10s;
InputDispatching Timeout: 输入事件分发超时5s,包括按键和触摸事件。
Timeout时长
服务相关的TimeOut在ActiveServices.java中定义,其他大部分的TimeOut都在AMS中定义。
对于前台服务,则超时为SERVICE_TIMEOUT = 20s;
对于后台服务,则超时为SERVICE_BACKGROUND_TIMEOUT = 200s;
对于前台广播,则超时为BROADCAST_FG_TIMEOUT = 10s;
对于后台广播,则超时为BROADCAST_BG_TIMEOUT = 60s;
ContentProvider超时为CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10s;
InputDispatching的输入事件超时为KEY_DISPATCHING_TIMEOUT = 5s。
触发ANR时系统会输出关键信息:
将am_anr信息,输出到EventLog.(ANR开始起点看EventLog)
获取重要进程trace信息,保存到/data/anr/traces.txt;(只保存最近一次ANR的信息)
Java进程的traces;
Native进程的traces;
ANR reason以及CPU使用情况信息,输出到main log;
再将CPU使用情况和进程trace文件信息,再保存到/data/system/dropbox;
解读Java进程的traces文件:http://gityuan.com/2016/11/26/art-trace/
如何避免ANR
避免在主线程上进行复杂耗时的操作,比如说发送接收网络数据/进行大量计算/操作数据库/读写文件等。这个可以通过使用AsyncTask或者使用多线程来实现。
broadCastReceiver 要进行复杂操作的的时候,可以在onReceive()方法中启动一个Service来处理
在设计及代码编写阶段避免出现出现同步/死锁或者错误处理不恰当等情况。