文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任。
很久之前写的了,留着有点浪费,共享之。
编写者:李文栋 

如果你是一个Android应用程序开发人员,你的人生中不可避免的三件事情是:死亡、缴税和ANR。这么说是夸张了,但是由于Android本身的设计,以及应用程序和系统在开发过程中的缺陷,经常会在测试过程中遇到各种各样的ANR问题。在功能性的测试中还少一些,主要是在压力测试中(例如Monkey测试)会遇到非常多的ANR问题。本章的目的就是汇总笔者在工作中遇到的各种ANR问题,将其归纳总结出一套分析和处理ANR问题的方法,希望能够通过这套方法为大家提供思路,有效的减少大家处理ANR问题的时间。同时也会给出一些避免ANR的最佳实践,更多的从预防做起,更少的做事后补救。

考虑到看本文的读者大多是有实际经验的开发人员,我会尽量少的提到一些基础的概念,我也希望给大家更多的“干货”。

本章的主要内容如下:

  1. ANR简介(什么是ANR、为什么会有ANR、ANR的异常长什么样)

  2. 如何分析ANR(引起ANR的原因分类、分析ANR的利器)

  3. 实例讲解

  4. 避免ANR的最佳实践(从错误中吸取教训)

1.1 ANR简介

ANR,是“Application Not Responding”的缩写,即“应用程序无响应”。在Android中,ActivityManagerService(简称AMS)和WindowManagerService(简称WMS)会监测应用程序的响应时间,如果应用程序主线程(即UI线程)在超时时间内对输入事件没有处理完毕,或者对特定操作没有执行完毕,就会出现ANR。对于输入事件没有处理完毕产生的ANR,Android会显示一个对话框,提示用户当前应用程序没有响应,用户可以选择继续等待或者关闭这个应用程序(也就是杀掉这个应用程序的进程)。

1.1.1 为什么会有ANR

如上所述,ANR的产生需要同时满足三个条件:

  • 主线程:只有应用程序进程的主线程响应超时才会产生ANR;

  • 超时时间:产生ANR的上下文不同,超时时间也会不同,但只要在这个时间上限内没有响应就会ANR;

  • 输入事件/特定操作:输入事件是指按键、触屏等设备输入事件,特定操作是指BroadcastReceiver和Service的生命周期中的各个函数,产生ANR的上下文不同,导致ANR的原因也会不同;

针对这三个条件,有以下三种情况会触发ANR,详细说明如下。

  1.主线程对输入事件在5秒内没有处理完毕

Android的事件系统从2.3开始做了完全不同的实现,原先2.2中是在Java层实现的,但在2.3中整体转移到了C++层,本书基于2.3以后的版本进行说明。我们先简单了解一下产生这种ANR的整个流程<!-- 在这章之前要先讲Android的事件机制?还是放在后一章讲?偏向于放在后面。 -->。

当应用程序的Window处于Active状态并且能够接收输入事件(例如按键事件、触摸事件等)时,系统底层上报的事件就会被InputDispatcher分发给这个应用程序,应用程序的主线程通过InputChannel读取输入事件并交给界面视图处理,界面视图是一个树状结构,DecorView是视图树的根,事件从树根开始一层一层向端点(例如一个Button)传递。我们通常会注册一个监听器来接收并处理事件,或者创建自定义的视图控件来处理事件。

InputDispatcher运行在系统进程(进程名为system_server)的一个单独的线程中,应用程序的主线程在处理事件的过程中,InputDispatcher会不断的检测处理过程是否超时,一旦超时,会通过一系列的回调通知WMS的notifyANR函数,最终会调用到AMS中mHandler对象里的SHOW_NOT_RESPONDING_MSG这个case,此时界面上就显示系统提示对话框了,同时使用logcat命令查看log(日志信息)也可以看到关于ANR的信息。InputDispatcher就是那个爱打“小报告”的家伙。

一下子出现了好几个重要的名词,要深入了解这种情况的ANR,需要熟悉Android的事件机制,本书会在别的章节中详细分析,这里只需要记住他们的功能:

  • Window:具体指的是PhoneWindow对象,表示一个能够显示的窗口,它能够接收系统分发的各种输入事件;

  • InputDispatcher:将系统上报的输入事件分发给当前活动的窗口;

  • InputChannel:InputDispatcher和应用程序分别运行在两个不同的进程中,InputDispatcher就是通过InputChannel将事件对象传递给应用进程的。

注意:产生这种ANR的前提是要有输入事件,如果用户没有触发任何输入事件,即便是主线程阻塞了,也不会产生ANR,因为InputDispatcher没有分发事件给应用程序,当然也不会检测处理超时和报告ANR了。

   2.主线程在执行BroadcastReceiveronReceive函数时10秒内没有执行完毕

BroadcastReceiver(简称BR)的onReceive函数运行在主线程中,当这个函数超过10秒钟没有返回就会触发ANR。不过对这种情况的ANR系统不会显示对话框提示,仅是输出log而已。

    3.主线程在执行Service的各个生命周期函数时20秒内没有执行完毕

Service的各个生命周期函数也运行在主线程中,当这些函数超过20秒钟没有返回就会触发ANR。同样对这种情况的ANR系统也不会显示对话框提示,仅是输出log。

三种ANR中只有第1种会显示系统提示对话框,因为用户正在做界面交互操作,如果长时间没有任何响应,会让用户怀疑设备死机了,大多数人此时会开始乱按,甚至拔出电池重启,给用户的体验肯定是非常糟糕的。

三种ANR发生时都会在log中输出错误信息,你会发现各个应用进程和系统进程的函数堆栈信息都输出到了一个/data/anr/traces.txt的文件中,这个文件是分析ANR原因的关键文件,同时在日志中还会看到当时的CPU使用率,这也是重要信息,在后面的章节会详细介绍如何利用它们分析ANR问题。

这三种ANR不是孤立的,有可能会相互影响。例如一个应用程序进程中同时有一个正在显示的Activity和一个正在处理消息的BroadcastReceiver,它们都运行在这个进程的主线程中。如果BR的onReceive函数没有返回,此时用户点击屏幕,而onReceive超过5秒仍然没有返回,主线程无法处理用户输入事件,就会引起第1种ANR。如果继续超过10秒没有返回,又会引起第2种ANR。

Android 系统稳定性 - ANR(一)的更多相关文章

  1. Android 系统稳定性 - ANR(二)(转)

    编写者:李文栋P.S. OpenOffice粘贴过来后格式有些混乱. 1.2 如何分析ANR问题 引起ANR问题的根本原因,总的来说可以归纳为两类: 应用进程自身引起的,例如: 主线程阻塞.挂起.死循 ...

  2. 【原创】Android 系统稳定性 - ANR(二)

    文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任. 很久之前写的了,留着有点浪费,共享之.编写者:李文栋P.S. OpenOffice粘贴过来后格式有些混乱. 1.2 如何分析ANR问题 引 ...

  3. [转发]Android 系统稳定性 - ANR(二)

    文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任. 很久之前写的了,留着有点浪费,共享之.编写者:李文栋P.S. OpenOffice粘贴过来后格式有些混乱. http://rayleeya ...

  4. [转发]Android 系统稳定性 - ANR(一)

    文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任.很久之前写的了,留着有点浪费,共享之.编写者:李文栋  http://rayleeya.iteye.com/blog/1955652 如果你 ...

  5. [转发]Android 系统稳定性 - ANR(三)

    文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任. 很久之前写的了,留着有点浪费,共享之. 编写者:李文栋 http://rayleeya.iteye.com/blog/1956056 1. ...

  6. 【转】Android系统开篇

    版权声明:本站所有博文内容均为原创,转载请务必注明作者与原文链接,且不得篡改原文内容.另外,未经授权文章不得用于任何商业目的. 一.引言 Android系统非常庞大.错综复杂,其底层是采用Linux作 ...

  7. Android客户端稳定性测试——Monkey

    修改时间 修改内容 修改人 2016.6.20 创建 刘永志 2016.6.29 完成 刘永志 Monkey简介: Android SDK自带的命令行测试工具,向设备发送伪随机事件流,对应用程序进行进 ...

  8. Android中的ANR

    有过Android开发经历的人都不会对ANR陌生,它和崩溃一样是程序设计的问题.本文将以较为深入的视角来介绍什么是ANR,出现场景,如何避免以及如何定位分析ANR,希望可以帮助大家在编写程序时有所帮助 ...

  9. Android系统中的广播(Broadcast)机制简要介绍和学习计划

    在Android系统中,广播(Broadcast)是在组件之间传播数据(Intent)的一种机制:这些组件甚至是可以位于不同的进程中,这样它就像Binder机制一样,起到进程间通信的作用:本文通过一个 ...

随机推荐

  1. Node安装及搭建简单服务器

    注:本文安装系统为mac,windows及其他系统下载对应安装包 ,mac下载后的安装包为apk文件,windows为msi文件. 安装 1.在网上下载node安装包,官方网站2.双击下载文件,按步骤 ...

  2. poj 3026 Borg Maze bfs建图+最小生成树

    题目说从S开始,在S或者A的地方可以分裂前进. 想一想后发现就是求一颗最小生成树. 首先bfs预处理得到每两点之间的距离,我的程序用map做了一个映射,将每个点的坐标映射到1-n上,这样建图比较方便. ...

  3. C#中文件管理的运用(Twelfth Day)

    又到了总结的时间了,今天在云和学院学习了文件管理的一些运用及复习昨天学的里氏转换.今天我就总结下昨天遗留下的问题以及今天所学的知识. 昨天遗留的问题 里氏转换(父类转子类) 例:在这里定义父类Peop ...

  4. SQL Server:错误处理及事务控制

    目录: 解读错误信息 RAISERROR THROW 实例 使用 @@ERROR 使用 XACT_ABORT 使用TRY/CATCH 现实中的事务语句 删除 更新 银行取钱 解读错误信息 Msg 54 ...

  5. Oracle游标循环更新数据案例

    declare v_XTXMBH number; v_ZJZJZJRQ varchar2(40); cursor c_job is SELECT XT.XTXMBH AS XTXMBH, QJ.ZJZ ...

  6. CocoaPods对于不同Target引入不同的第三方库Podfile的写法

    有的时候我们需要建立多个Target来完成不同的测试环境的区分,而多个Target之间可能会有第三方库的不同引用,如果我们在使用CocoaPods管理我们的第三方库的时候,我们就需要思考我们需要如何实 ...

  7. JavaSE学习总结第10天_面向对象5

      10.01 运动员和教练案例分析 教练和运动员案例:运动员分乒乓球运动员和篮球运动员,教练分乒乓球教练和篮球教练.为了出国交流,跟乒乓球相关的人员都需要学习英语. 分析: 10.02 运动员和教练 ...

  8. Properties的使用

    Properties的各种相对路径,绝对路径的用法 所在包: package com.test.javaAPI.collections; import java.io.File; import jav ...

  9. 基于Win7 Python2.7的Numpy安装包分享

    Numpy-1.9.2安装包: http://pan.baidu.com/s/1i3WZRoT 下载后双击安装即可! 另外分享一个安装教程,mark一下慢慢看: http://blog.csdn.ne ...

  10. Python之路Day17

    算法:冒泡排序.插入排序.快速排序.堆排序 冒泡排序 #! /usr/bin/env python # -*- coding: utf-8 -*- # __author__ = "Q1mi& ...