Android ANR:Application Not Responding 详解
日志关键字:
Timeout of broadcast BroadcastRecord
ServiceTimeout —— Service 在特定的时间内未处理完成导致 ANR 发生。(限制:前台服务 20s;后台服务 200s);
日志关键字:
Timeout executing service
ContentProviderTimeout —— 内容提供者,在 10s 内未处理完成导致 ANR 发生;
日志关键字:`Timeout publishing conte
nt providers`
三、ANR 的产生原因
主线程被 IO 操作(从 4.0 之后网络 IO 不允许在主线程中)阻塞
主线程中错误的操作,比如 Thread.wait 或者 Thread.sleep 等 Android 系统会监控程序的响应状况,导致的主线程等待超时,一旦出现下面两种情况,则弹出 ANR 对话框。
主线程中存在耗时的计算:
例如大量的数据库读写,耗时的网络情况,高强度的硬件计算等。
BroadcastReceiver 未在 10 秒内完成相关的处理
Service 在特定的时间内无法处理完成 20 秒
四、怎么避免 ANR:
使用 AsyncTask 处理耗时 IO 操作。
使用 Thread 或者 HandlerThread 时,调用**Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)**设置优先级,否则仍然会降低程序响应,因为默认 Thread 的优先级和主线程相同。
使用 Handler 处理工作线程结果,而不是使用**Thread.wait()或者 Thread.sleep()**来阻塞主线程。
Activity 的 onCreate 和 onResume 回调中尽量避免耗时的代码。
BroadcastReceiver 中 onReceive 代码也要尽量减少耗时,建议使用 IntentService 处理。
将所有耗时操作,比如访问网络,Socket 通信,查询大量 sql 语句,复杂逻辑计算等都放在子线程中去,然后通过 handler.sendMessage、runonUIThread、AsyncTask、RxJava 等方式更新 UI。
五、发生了 ANR 的情况,如何解决:
如果在已经尽量避免的情况下,还是发生了 ANR 的情况,我们可以根据以下的步骤进行问题定位与分析:
1.问题分析
导出 ANR 日志信息,根据日志信息,判断确认发生 ANR 的包名类名,进程号,发生时间,导致 ANR 原因类型等。
关注系统资源信息,包括 ANR 发生前后的 CPU,内存,IO 等系统资源的使用情况。
查看主线程状态,关注主线程是否存在耗时、死锁、等锁等问题,判断该 ANR 是 App 导致还是系统导致的。
结合应用日志,代码或源码等,分析 ANR 问题发生前,应用是否有异常,其中具体问题具体分析。
2.导出 ANR 日志
NR 问题发生时,系统会收集 ANR 相关的日志信息,CPU 使用情况,trace 日志也就是各线程执行情况等信息,生成一个 traces.txt 的文件并且放在**/data/anr/**路径下。
注意:每一次新的 ANR 问题的发生,会把之前的 ANR 信息覆盖掉。
我们可以通过 adb 命令将 traces 文件导出到本地。
adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>
读取关键日志信息
在 log 中找到 ANR 发生信息:
评论