Android ANR 知多少

极力推荐文章:欢迎收藏
Android 干货分享

阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android

ANR(Application Not Responding ) 应用无响应的简称,是为了在 APP卡死时,用户 可以强制退出APP的选择,从而避免卡机无响应问题,这是Android 系统的一种自我保护机制。

通过本篇阅读,您将学习到以下内容

  1. 什么是ANR
  2. ANR的类型
  3. ANR 产生的原因
  4. 如何分析解决 ANR问题
  5. ANR 问题分析解决建议
  6. MTK 平台 ANR问题分析

1. 什么是ANR

Android 中,应用程序响应由Activity ManagerWindow Manager 系统服务进行监视。ANR(Application Not Responding ),则是Android的一种自我保护措施,当主线程出现卡顿时候,Android 系统会给用户一个弹出提示,让用户手动选择继续等待还是强制关闭此APP

当Android检测到以下情况之一时,Android将显示特定应用程序的ANR对话框,比如以下三种情况下ANR 将经常发生:

  1. UI Thread 超过 5 s 没有响应
  2. Broadcast 广播超过10 s没响应
  3. Service 服务超过 20s 没响应
    因此,为避免ANR 发生,请不要在主线程中进行耗时操作,耗时操作请尽量在子线程中运行。
  4. 发生ANR 截图 如下:

ANR Dialog 举例

2. ANR的类型

ANR Android 手机中很常见,按其相应类型可以分为以下 常见 三种类型。

ANR类型:

  1. 按键响应分发超时(Key Dispatch Timeout)
    默认 5 s,超过则会出现ANR。
  2. 广播超时(Broadcast Timeout)
    默认 10 s,超过则会出现ANR。
  3. 服务超时(Service Timeout)
    默认 20 s,超过则会出现ANR。

3. ANR 产生的原因

Android系统中,APP 通常运行在一个UI Thread 或者叫MainThread里。并且Android中只有一个MainThreadMain Message QueueMainThread主要用于UI的绘制、事件响应,监听与接收事件处理等功能。Main Message Queue 主要存放用户要处理消息的队列,主线程MainThread从消息队列Main Message Queue中取消息Message后,尽快分发下去,一旦某条消息分发超时,则ANR可能发生。

因此,当ANR 发生时,我们要分析ANR 产生的原因,也就是查找消息处理不及时的原因。例如可以从以下几个疑问点进行分析:

    1. 为什么 APP 不能获取CPU 时间片?
    1. APP 是否是等待一些没能及时处理的事件完成?
  • 3 . 消息处理流程是不是太复杂?

4. 如何分析解决 ANR问题

在分析ANR时有一些常见的模式可供选择:

  1. APP正在主线程上进行缓慢的I/O操作。
  2. APP正在主线程中进行很复杂的计算操作
  3. 主线程正在对另一个进程执行同步Binder程序调用,但另一个进程需要很长时间才能返回结果。
  4. 主线程在等待另一个正在长时间执行块操作的子线程时被阻塞。
  5. 主线程因为另一个线程死锁,无论是Bind调用还是主线程调用,都不能让主线程等待很久,更不能在主线程中进行复杂的计算。

知道产生ANR的原因,那么如何避免ANR 问题呢?

a.Strict mode

使用StrictMode可以帮助您在开发应用程序时在主线程上发现意外的I / O操作。 您可以在applicationactivity使用StrictMode

b.关闭 ANR Dialog 提示

查看方法ANR控制的方法:
设置---- 开发者选项---显示所有ANR

注意 :
如没有开发者选项,请进入设置---关于手机--- 多次连击 版本号 即可打开隐藏的开发者选项的item

后台 app ANR 开关

c.Traceview

Traceview获取正在运行的应用程序的跟踪信息,分析此traces.txt文件 可以推测出主线程在忙于某些事情。

traces 文件通常保存在/data/anr/traces.txt下,你可以直接用adb cat 查看,或者 adb pull 出来都可以。

  • 直接查看trace 信息

个人不太建议

adb root
adb shell
cat /data/anr/traces.txt

  • pull trace 文件到桌面

建议使用此方法

adb root
adb remount
adb pull /data/anr/traces.txt C:\Users\Administrator\Desktop\新建文件夹

pull traces 文件到桌面

5. ANR 问题分析解决建议

分析查看ANR原因,接着解决ANR问题。

  1. 耗时操作
    请放在工作现场中进行,可以使用Handler、AsyncTask 等。

  2. IO 操作
    (比如:网络操作、存储操作等)也是引起ANR的常见因素。强烈建议在工作线程中进行。

  3. 程序锁竞争

某些情况,ANR产生的原因不是直接因为在主线程中产生的。 比如: 工作线程对某个资源等上锁,恰好此时,主线程需要此资源,如等待超时,则此时ANR可能发生。

  1. 死锁

当主线程因为请求一个其他线程正在持有的资源而进入等待状态时,ANR可能会发生。

  1. 广播接收慢

应用程序可以通过广播接收器响应广播消息,例如启用或禁用飞行模式或更改连接状态。 当应用程序花费太长时间来处理广播消息时,理论上超过10s 未处理完成,ANR可能会发生。

广播 ANR发生在下列情况下:

  1. onReceive() 方法长时间未执行完毕。

尽量避免在onReceive() 中进行耗时操作。

  1. 广播接收者调用goAsync()方法并且未能在PendingResult对象上调用finish()

如要处理的广播内容较多,请使用IntentService 进行处理。

比如下面例子:

  • 不建议在onReceive 方法中进行耗时操作,超过10s 未处理,会引起ANR

不建议在onReceive 方法中进行耗时操作,超过10s 未处理,会引起ANR

  • 建议使用IntentService ,避免ANR发生

IntentService 避免处理广播消息过多引起ANR

您的广播接收机可以使用goAsync()来通知系统需要更多的时间来处理消息。 但是,您应该在PendingResult对象上调用finish()。 以下示例显示如何调用finish()以让系统回收广播接收器并避免ANR:

goAsync()---finish 获取更多广播响应时间

6. MTK 平台 ANR问题分析

前提,抓取一份ANR MTK log

1.event_log 中 搜索关键字 am_anr或者anr,分析并查看ANR原因

event_log 分析 ANR原因

2. main_log中 搜索关键字Application Not Responding或者anr ,分析并查看ANR原因。

main_log 中分析ANR 原因

3. MTK ANR 策略建议

MTK 官方总结图

MTK ANR 分析步骤

MTK ANR  Debug SOP

MTK ANR  Debug SOP

常见ANR 举例分析如下:

Main Thread is idle

Stuck in IO

Main Thread Waiting a lock

Wait Binder Transaction

Main Thread Query DB

至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

微信关注公众号:  程序员Android,领福利

posted @ 2019-08-09 14:40  程序员Android  阅读(1153)  评论(0编辑  收藏  举报