Android ANR 原因分析与检测
来源:互联网 发布:sql case when 嵌套 编辑:程序博客网 时间:2024/06/05 08:16
Android ANR 原因分析与检测
ANR,即应用程序不响应(Application Not Responding)。在主线程中进行某些耗时操作,超过一定时间,系统就会弹出ANR对话框。此时可以选择等待,让程序跑完,也可以选择关闭应用程序。
一、 ANR 原因分析
只有当应用程序的UI线程响应超时才会引起ANR,超时产生的原因一般有两种:
当前事件没有机会得到处理,例如UI线程正在响应另一个事件,当前事件由于某种原因被阻塞了
当前事件正在处理,但是由于耗时太长未能及时完成
本质上,产生ANR的原因有三种:KeyDispatchTimeout、BroadcastTimeout、ServiceTimeout
1.1 KeyDispatchTimeout
View的按键事件或者触摸事件这特定事件(5秒)内无法得到响应
1.2 BroadcastTimeout
BroadcastReceiver 的 onReceive()方法在特定时间(10秒)内无法完成处理(onReceive是运行在主线程的)
1.3 ServiceTimeout
Service 的各个生命周期函数在特定时间(20秒)内无法完成处理
二、ANR 避免
一个原则:主线程尽量只做UI相关的事,耗时操作(如文件读取,数据库读写等),计算量大的任务,在线程中执行,完成之后通过Handler来更新UI。
2.1 主线程
运行在主线程的有:
1. Activity的各个生命周期 onCreate(),onResume(),onDestory,点击/触摸事件等
2. Service的各个生命周期
3. BroadcastReceiver的onReceive()方法。
4. AsyncTask: onPreExecute(), onProgressUpdate(), onPostExecute(), onCancel
5. Mainthread handler: handleMessage(), post*(runnable r)
6. View的post()方法
在以上的这些方法内,尽量不要执行耗时的操作,如读写数据库,文件等。可以放在线程中运行,完成后再通知更新主线程。
2.2 异步处理技术
Android SDK提供了很多异步处理技术
1. Thread + Handler
2. HandlerThread
3. AsyncTask
4. IntentService
5. AsyncQueryHandler(用于ContentProvider上执行异步的CRUD)
6. Loader(Android 3.0引入的一个异步数据加载框架)
除了Android SDK提供的异步技术外,比较火的RxAnroid使用起来更加方便简洁,流程更加清晰,代码更加易于理解,功能更加强大(反正说是牛逼轰轰,确实也是很好用)。
三、ANR 定位分析
发生ANR后,可以结合Logcat日志和位于收集内部存储的/data/anr/trace.txt文件进行分析和定位。Cash和ANR的异常信息统计,一般可以接入第三的统计SDK,如友盟或者Bugly,不需要自己实现后台,便可以实时获得APP的异常统计信息,可以专注于问题的分析和定位。但是,为了更好地理解解决的思路,还是有必要了解信息是的来源和如何收集。
3.1 Logcat 日志信息
发生ANR后,可以查看Logcat日志,日志中有ANR的类型,时间等信息,参考浅谈ANR及log分析ANR
3.2 traces.txt 日志信息
有时候根据Logcat日志无法定位到问题的具体位置,这时候就需要traces.txt中的日志信息。
traces.txt位于设备的 /data/anr/traces.txt文件中(因为权限限制,在应用中无法读取,如果可以读取就可以上报给后台,实现自己的ANR日志收集SDK),链接上PC后可以通过adb命令导出:
adb pull /data/anr/traces.txt C:\Users\YourName\Desktop\traces.txt
如何分析traces.txt日志?参考:
- Android App优化之ANR详解
- android anr traces日志分析方法
3.3 第三方统计SDK
Logcat 日志和trace.txt日志都需要有设备才能获取到,而实际中几乎不可能拿到用户的设备来查看日志,所以,有必要有一个后台来收集错误信息。第一种方法是自己实现Crash和ANR信息收集;第二种方法是利用现有的第三方平台,如Bugly,友盟。使用第三方平台的好处是节约成本,专注于ANR的定位和问题的解决即可。
四、ANR 检测
可以借助一些工具,在调试阶段进行违规代码的检测
4.1 StrictMode
严格模式 StrictMode 是 Android SDK 提供的一个用来检测代码中是否存在违规操作的工具类,StrictMode主要检测两大类问题。
- 线程策略ThreadPolicy
- detectCustomSlowCalls 检测自定义耗时操作
- detectDiskReads 检测是否存在磁盘读取操作
- detectDiskWrites 检测是否存在磁盘写入操作
- detectNetwork 检测是否存在网络操作
- 虚拟机策略VmPolicy
- detectActivityLeaks 检测是否存在Activity泄漏
- detectLeakedClosableObjects 检测是否存在未关闭的Closable对象泄漏
- detectLeakedSqlLiteObject 检测是否存在Sqlite对象泄漏
- setClassInstanceLimit 检测类实例个数是否超出限制
严格模式的使用并不复杂,在自定义的Application类或者MainActivity的onCreate()方法中加入以下代码即可:
@Override public void onCreate() { super.onCreate(); if (BuildConfig.DEBUG) { // 只在debug使用,release不使用严格模式 StrictMode.enableDefaults(); } }
enableDefaults()的实现如下:
/** * Enable the recommended StrictMode defaults, with violations just being logged. * * <p>This catches disk and network access on the main thread, as * well as leaked SQLite cursors and unclosed resources. This is * simply a wrapper around {@link #setVmPolicy} and {@link * #setThreadPolicy}. */ public static void enableDefaults() { StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectAll() .penaltyLog() .build()); StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() .detectAll() .penaltyLog() .build()); }
启用了严格模式,在Logcat中过滤:tag = StrictMode即可看到输出的日志信息。然后根据输出的日志信息,检测是否存在问题,然后及时改正。
4.2 BlockCanary
BlockCanary 是一个非侵入式的性能监控函数库,它的用法和LeakCanary类似,只不过后者监控应用的内存泄漏,而BlockCanary主要用来监控应用的主线程卡顿,它的基本原理是利用主线程的消息队列处理机制,通过对比消息分发开始和结束的时间点来判断是否超过设定的时间,如果是则判断线程卡顿,它的集成很简单,在build.gradle中添加依赖: compile ‘com.github.moduth:blockcanary-android:1.2.1’,然后在Application中进行配置和初始化即可。
@Override public void onCreate() { super.onCreate(); BlockCanary.install(this, new AppBlockCanaryContext()).start(); }
更多参考:blockcanary,BlockCanary解析
五、扩展
一、实现ANR信息收集SDK
前面介绍中的 Logcat 日志和 traces.txt 文件日志可以作为分析ANR的主要信息,而Logcat日志需要连接到PC利用IDE来查看,traces.txt文件/data/anr/traces.txt是没有读取权限的。所以,如何收集这些信息,上报到后台?(PS: bugly等第三方平台是如何实现的呢?)
六、参考
- Android App优化之ANR详解
- Android高级进阶
- 浅谈ANR及log分析ANR
- blockcanary
- BlockCanary解析
- Android ANR 原因分析与检测
- Android ANR问题原因分析
- Android中ANR产生的原因以及定位分析和检测
- BlockCanary检测ANR原因
- Android ANR产生的原因和分析
- Android ANR分析与总结
- Android ANR产生的原因与解决方法
- Android ANR出现原因
- Android-ANR-Android ANR分析
- android crash 四 ANR原因分析及解决方法
- Android ANR产生的原因以及其定位分析
- Android ANR产生的原因及定位分析
- android ANR分析与如何处理
- Android ANR的产生与分析
- ANR原因分析及解决方法
- ANR原因分析及解决方法
- Android 通知栏ANR原因
- Android ANR发生原因总结
- 136. Single Number
- 面试中遇到过的问题
- WordPress主题 The Ken 多用途创意设计多功能主题汉化版[更新至v3.7]
- [cnblogs镜像]Unity 导入的模型检测不到碰撞
- Android Mediacodec H.265文件播放
- Android ANR 原因分析与检测
- 一些思考02
- mybatis(7)多对多映射
- SpringMvc高级配置详解
- Zipper
- 初识jdk动态代理
- docker从容器里面拷文件到宿主机或从宿主机拷文件到docker容器里面
- 泛型方法
- eclipse如何安装java decompiler反编译插件