0%

ANR问题分析

ANR

ANR(Application Not responding),是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR。在 Android 里,应用程序的响应性是由 Activity Manager 和 WindowManager 系统服务监视的。当它监测到以下情况中的一个时,Android 就会针对特定的应用程序显示 ANR。

场景

Service Timeout、BroadcastQueue Timeout

ContentProvider Timeout 、InputDispatching Timeout

Timeout时长

对于前台服务,则超时为SERVICE_TIMEOUT = 20s; 对于后台服务,则超时为SERVICE_BACKGROUND_TIMEOUT = 200s

对于前台广播,则超时为BROADCAST_FG_TIMEOUT = 10s; 对于后台广播,则超时为BROADCAST_BG_TIMEOUT = 60s;

ContentProvider超时为CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10s;

InputDispatching Timeout: 输入事件分发超时5s,包括按键和触摸事件。

注: Input的超时机制与其他的不同,对于input来说即便某次事件执行时间超过timeout时长,只要用 户后续在没有再生成输入事件,则不会触发ANR。

如何避免ANR

  1. 主线程尽量只做UI相关的操作,避免耗时操作,比如过度复杂的UI绘制,网络操作,文件IO操作;

  2. 避免主线程跟工作线程发生锁的竞争,减少系统耗时binder的调用,谨慎使用sharePreference,注意主线程

    执行provider query操作。

如何解决ANR

线下可以通过ADB命令导出ANR文件进行分析。

导出ANR文件

ANR发生之后我们可以使用以下命令导出ANR文件

1
2
3
4
5
6
adb pull data/anr/traces.txt 存储路径

//或者生成
adb bugreport
//导出
adb pull 文件路径 存储路径

ANR文件分析

查看trace信息,分析是否有耗时的message,binder调用,锁的竞争,CPU资源的抢占。

如何监控ANR方案

线上监控方案我们可以实现FileObserver去监听ANR目录的变化和使用ANR-WatchDod去监听并打印ANR堆栈信息。
FileObserver
注意事项:

  • FileOberver需要三种权限
1
2
3
4
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!--在sdcard中创建/删除文件的权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
  • FileOberver的startWatching、stopWatching都加锁,因此要避免在对象锁中实现,以免造成死锁。

使用方法:

1
2
3
4
5
6
7
8
9
@SuppressLint("NewApi")
fun startANRListener(){
val fileObserver = object :FileObserver(File("/data/anr/"), CLOSE_WRITE){
override fun onEvent(event: Int, path: String?) {
Log.d("ANRWatching", "/data/anr/$path")
}
}
fileObserver.startWatching()
}

ANR-WatchDog
ANR-WatchDog,是一个非侵入式的ANR监控组件。
使用步骤:

1
implementation 'com.github.anrwatchdog:anrwatchdog:1.4.0'

 在application中使用

1
2
3
4
5
6
class MyApplication: Application() {
override fun onCreate() {
super.onCreate()
ANRWatchDog().start();
}
}

原理
Watchdog原理类似,ANRWatchDog 继承子Thread,所以它最重要的就是run方法。核心内容可以分为以下几点:

  • 在run方法中实现无限循环
  • _tick自动加上5000毫秒并往Handler发消息
  • 睡眠5000毫秒
  • 如果5000毫秒之内主线程还没有处理Runnable,将_tick置0,则进入ANR异常。

Watchdog机制总结

每一个线程都可以对应一个Looper,一个Looper对应一个MessageQueue,所以可以通过向MessageQueue中post检测任务来预测该检测任务是否被及时的执行,以此达到检测线程任务卡顿的效果,但是前提是该线程要先创建一个Looper。

ANR异常我们可分为线上监测和线下监测两个方向

  • 线上监测主要是利用FileObserver进行ANR目录文件变化监听,以ANR-WatchDog进行补充。
  • FileObserver在使用过程中应注意高版本程序不可用以及预防死锁出现。
  • 线下监测主要是在报错之后利用ADB命令将错误的日志导出并找到错误的类进行分析