Android App开发之ANR异常的原因分析及处理总结

android anr定位分析,Android ANR产生的原因以及其定位分析 前言ANR是Android中一个独有的概念,它的全称是Application Not Responding(应用程序无响应)。相信从事Android开发的同学,或多或少都遇到过,对于高质量的代码,ANR在开发者自测过程中可能不会经常遇到,但一旦测试人员进行Monkey测试,ANR出现的概率就比较高了,如何快速分析定位并解决,是开发者的必修课。ANR的直观体验是用户在操作APP的过程中,感觉界面卡顿... 阅读详情

Android App开发之ANR异常的原因分析及处理总结

ANR的全称是application not responding,根据它的意思我们就能看出来是应用程序未响应,就像是我们在电脑上碰到的程序未响应,一般电脑出现这种情况,可能是由于我们打开了很多应用程序,占用了大量的内存,或者CPU时间片被一个应用程序长时间占用,不够分配,导致部分应用程序出现了无响应。Android和Windows基本一样,接下来我们就分析一下Android是怎么产生的这个问题。

下图就是我们见到的APP无响应的时候出现的对话框,产生ANR的原因很多,但是只有在Activty中的Anr才会弹出对话框,对话框有两个选项,一个是等待,一个是关闭程序供用户选择:
ANR图片

一、为什么会产生ANR(Application not response)这种情况呢?
在Android里, App的响应能力是由Activity Manager和Window Manager系统服务来监控的.,通常情况下产生ANR有这么三个条件:

1.只有主线程才会产生ANR,主线程就是UI线程;

2.必须发生某些输入事件或特定操作,比如按键或触屏等输入事件,在BroadcastReceiver或Service的各个生命周期调用函数;

3.上述事件响应超时,不同的context规定的上限时间不同

具备了以上三个条件,那么加上这两个环境,就会产生ANR了:

1.5秒内无法对输入事件(按键及触摸)做出响应

2.广播接收器无法在10秒内结束运行

二、ANR时系统做了什么
1.弹出一个对话框

2.将ANR信息输出到traces.txt文件中

traces.txt文件是一个ANR记录文件,用于开发人员调试,目录位于/data/anr中,无需root权限即可通过pull命令获取,下面的命令可以将traces.txt文件拷贝到当前目录下

adb pull /data/anr
3.将ANR信息输出到Logcat中

三、对ANR产生详细分析
为什么会产生ANR,在第一条讲解中,具体剖析(部分文章参考简书作者):

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

b.主线程在执行BroadcastReceiver的onReceive()函数时10秒内没有处理完毕

c.主线程在Service的各个生命周期函数时20秒内没有处理完毕。

那么导致ANR的根本原因是什么呢?简单的总结有以下两点:

1.主线程执行了耗时操作,比如数据库操作或网络编程

2.其他进程(就是其他程序)占用CPU导致本进程得不到CPU时间片,比如其他进程的频繁读写操作可能会导致这个问题。

细分的话,导致ANR的原因有如下几点:

1.耗时的网络访问

2.大量的数据读写

3.数据库操作

4.硬件操作(比如camera)

5.调用thread的join()方法、sleep()方法、wait()方法或者等待线程锁的时候

6.service binder的数量达到上限

7.system server中发生WatchDog ANR

8.service忙导致超时无响应

9.其他线程持有锁,导致主线程等待超时

10.其它线程终止或崩溃导致主线程一直等待。

四、ANR机制的实现原理:

文章:http://gityuan.com/2016/07/02/android-anr/从源码角度详细的分析了ANR机制实现的原理。对于上一章讲到的1-4中情况,分别找到了其源码中是如何实现的,对于每一种大概原理如下:1.在进行相关操作调用hander.sendMessageAtTime()发送一个ANR的消息,延时时间为ANR发生的时间(如前台Service是当前时间20s之后)。2.进行相关的操作3.操作结束后向remove掉该条message。如果相关的操作在规定时间没有执行完成,该条message将被handler取出并执行,就发生了ANR。

下面以BroadcastReceiver为例详细介绍:

BroadcastQueue.processNextBroadcast()

final void processNextBroadcast(boolean fromMsg) { … synchronized (mService) { … do { if (mOrderedBroadcasts.size() == 0) { … if (mService.mProcessesReady && r.dispatchTime > 0) { long now = SystemClock.uptimeMillis(); if ((numReceivers > 0) && (now > r.dispatchTime + (2 * mTimeoutPeriod * numReceivers))) { //1.发送延时消息 broadcastTimeoutLocked(false); // forcibly finish this broadcast forceReceive = true; r.state = BroadcastRecord.IDLE; } } if (r.state != BroadcastRecord.IDLE) { if (DEBUG_BROADCAST) Slog.d(TAG, “processNextBroadcast(” + mQueueName + “) called when not idle (state=” + r.state + “)”); return; } if (r.receivers == null || r.nextReceiver >= numReceivers || r.resultAbort || forceReceive) { // No more receivers for this broadcast! Send the final // result if requested… if (r.resultTo != null) { try { //2. 处理广播消息 performReceiveLocked(r.callerApp, r.resultTo, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, false, false, r.userId); // Set this to null so that the reference // (local and remote) isn’t kept in the mBroadcastHistory. r.resultTo = null; } catch (RemoteException e) { … } } //3.取消延时消息 cancelBroadcastTimeoutLocked(); … } } while (r == null) ; … } } }
1.发送延时消息:broadcastTimeoutLocked(false): final void broadcastTimeoutLocked(boolean fromMsg) { … long now = SystemClock.uptimeMillis(); if (fromMsg) { if (mService.mDidDexOpt) { // Delay timeouts until dexopt finishes. mService.mDidDexOpt = false; long timeoutTime = SystemClock.uptimeMillis() + mTimeoutPeriod; setBroadcastTimeoutLocked(timeoutTime); return; } if (!mService.mProcessesReady) { return; } long timeoutTime = r.receiverTime + mTimeoutPeriod; if (timeoutTime > now) { setBroadcastTimeoutLocked(timeoutTime); return; } }
他调用了setBroadcastTimeoutLocked(long timeoutTime): final void setBroadcastTimeoutLocked(long timeoutTime) { if (! mPendingBroadcastTimeoutMessage) { Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this); mHandler.sendMessageAtTime(msg, timeoutTime); mPendingBroadcastTimeoutMessage = true; } }
传入setBroadcastTimeoutLocked(long timeoutTime)的时间xxx + mTimeoutPeriod,mTimeoutPeriod就是onRecieve()可以执行的时间,在BroadcastQueue初始化时候被赋值,前台队列为10s后台队列为60s:
ActivityManagerService.java: public ActivityManagerService(Context systemContext) { … static final int BROADCAST_FG_TIMEOUT = 10 * 1000; static final int BROADCAST_BG_TIMEOUT = 60 * 1000; … mFgBroadcastQueue = new BroadcastQueue(this, mHandler, “foreground”, BROADCAST_FG_TIMEOUT, false); mBgBroadcastQueue = new BroadcastQueue(this, mHandler, “background”, BROADCAST_BG_TIMEOUT, true); … }
performReceiveLocked()为广播的实际处理,就不展开了

cancelBroadcastTimeoutLocked() :

该方法的主要工作是当service启动完成,则移除服务超时消息SERVICE_TIMEOUT_MSG。

final void cancelBroadcastTimeoutLocked() {
if (mPendingBroadcastTimeoutMessage) {
mHandler.removeMessages(BROADCAST_TIMEOUT_MSG, this);
mPendingBroadcastTimeoutMessage = false;
}

五、如何避免ANR呢?
1.避免在主线程执行耗时操作,所有耗时操作应新开一个子线程完成,然后再在主线程更新UI。

2.BroadcastReceiver要执行耗时操作时应启动一个service,将耗时操作交给service来完成。

3.避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。如果你的应用程序在响应Intent广 播时需要向用户展示什么,你应该使用Notification Manager来实现。

UI线程尽量只做跟UI相关的工作

耗时的工作()比如数据库操作,I/O,网络操作),采用单独的工作线程处理

用Handler来处理UIthread和工作thread的交互

UI线程,例如:

Activity:onCreate(), onResume(), onDestroy(), onKeyDown(), onClick(),etc

AsyncTask: onPreExecute(), onProgressUpdate(), onPostExecute(), onCancel,etc

Mainthread handler: handleMessage(), post*(runnable r), etc

…

ANR分析:需要关注CPU/IO,trace死锁等数据。

六、总结
ANR在我们开发APP中也比较常见,总的来说,我们需要执行耗时得操作就在子线程中执行,避免在主线程中执行。

Android应用程序中的ANR异常及其解决方式 例如,可以使用RecyclerView替代ListView,使用ViewHolder模式减少View的创建和销毁,避免过多的嵌套布局,合理使用ViewStub等等。通过以上几种方式,可以有效地解决Android应用程序中的ANR异常问题,提高应用程序的性能和用户体验。开发者应根据具体的场景和需求选择适合的解决方式,并进行合理的线程管理和UI优化,以确保应用程序的稳定运行。在实际应用中,应根据具体需求进行适当的异常处理和线程同步操作,以确保代码的健壮性和安全性。 阅读详情

相关推荐

若依Vue整合积木报表实战:Token安全校验全流程解析

本文详细解析了在若依Vue后台系统中安全集成积木报表的全流程,重点阐述了Token安全校验的核心机制。通过前端菜单配置、Token传递、后端权限拦截及自定义Token服务实现,构建了一套完整的企业级报表访问安全防线,确保核心业务数据的安全可控。

t8u9v0的博客 577

Android中的ANR异常

一、概念: ANR(application not response或者是activity not response)应用程序无响应,如果一个比较耗时间的进程长期占用着主线程,那么主线程的UI就会长期无响应,这个时候就会出现应用程序无响应的现象,所以为了避免这样的情况的出现,那么一般使用的是将“耗时间”的线程放到子线程中执行,这样就避免了UI无响应的情况的出现。 二、主线程: 主线程也成

u013470176的专栏 834

Cadence 17.2配置CIS数据库报错?手把手解决ODBC驱动位数不匹配问题

本文详细解析了Cadence 17.2配置CIS数据库时常见的ODBC驱动位数不匹配问题,提供了从系统环境检查到分步解决方案的完整指南。重点解决32位应用程序与64位ODBC驱动之间的架构冲突,包含驱动安装、DSN配置及高级排查技巧,帮助电子工程师快速恢复设计环境。

play7的博客 970

ANR异常总结

在Android中ANR异常是初学者经常发生的一个异常,这个异常也是Android独有的一个特性了,那么如何解决ANR异常呢,那么就得先了解什么是ANR异常,ANR异常是如何产生的,再去解决ANR异常。1.什么是ANR异常?ANR异常是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR。2.那么哪些场景会造...

LQ的博客 3581

彻底卸载Ubuntu双系统,并完美回收100G空间给D盘

本文记录了安全卸载Ubuntu双系统并回收磁盘空间的全过程。作者首先通过Windows命令行彻底清除Ubuntu启动项,避免GRUB引导报错;随后在磁盘管理中删除Linux分区,将100G未分配空间合并至相邻的D盘。针对C盘空间不足问题,作者采用Dism++清理系统文件,并将用户文档、聊天记录等迁移至扩容后的D盘。最终实现了引导纯净、空间合理分配的目标,特别强调分区扩展必须遵循"相邻原则",建议通过间接迁移而非直接扩容来优化系统盘空间管理。

2403_85993278的博客 1512

Accelstepper 库中的参数计算公式

要完全调试电机的各个参数,例如最大速度,加速度等,就需要了解其计算公式和原理。 以下是代码注释: /// This code uses speed calculations as described in /// "Generate stepper-motor speed profiles in real time" by David Austin/// http://fab.cba.mi...

wenguitao的博客 4455

android中的ANR异常

ANR异常(Application Not Responding) 1.出现ANR异常的原因: 1.主要是在主线程中做了耗时操作(在5秒时间内还没用响应) 2.在BroadcastReceiver的10秒内没有完成返回。 3.Service在特定的时间内无法处理完成(在20秒的时间内,这个情况很少出现) 主要出现这些是:主线程中做了网络操作,或则在主线程中做了一些缓慢的磁盘操作。

android丿Studio` 558

Arcgis栅格裁剪批处理工具

Arcgis栅格裁剪批处理工具

yilvyangguang520的博客 2172

常见ANR问题解决办法

android 常见anr问题分析解决办法

山水之间 4042

【Python_PySide6学习笔记(二十四)】菜单栏QMenuBar类的基本用法

此篇文章中介绍 PySide6 中 QMenuBar 类的基本用法,包括"创建菜单栏"、"创建一级菜单"、"创建二级菜单"等,会持续更新,有需要的读者可以点赞收藏,也欢迎在评论区进行讨论。

禾戊之昂的博客 1623

实战交易策略 篇二十二:情绪流龙头交易策略

在股票市场中,机构主导趋势,游资驱动热点,散户易被情绪裹挟,形成“金字塔”式生态链,并存在情绪传递、强者恒强、物极必反的规律特点。股市是资金驱动的情绪博弈场,价格波动由群体心理、资金博弈和预期差共同驱动,核心是资本逐利性与人性贪婪恐惧的交织,兼具资源配置、财富再分配与风险定价功能。涨停加速与逃逸缺口(主升强化)凹字板/平台突破(趋势延续)天量弱转强(分歧买点)不参与首波(二波策略)情绪周期(道术合一)主线思维(聚焦核心)开盘抢筹(竞价博弈)一字助攻(情绪强化)分批进出(滚动操作)

生活在别处 1487

Android 系统(55)---Android App开发之ANR异常的原因分析及处理总结

Android App开发之ANR异常的原因分析及处理总结Android App开发之ANR异常的原因分析及处理总结ANR的全称是application not responding,根据它的意思我们就能看出来是应用程序未响应,就像是我们在电脑上碰到的程序未响应,一般电脑出现这种情况,可能是由于我们打开了很多应用程序,占用了大量的内存,或者CPU时间片被一个应用程序长时间占用,不够分配,导致部分应...

zhangbijun1230的专栏 507

【Segment Anything Model】三:SAM模型微调自定义数据集,更改混合提示方式:点,框,点框混合

1.微调SAM预备知识。

cvxiayixiao的博客 1万+

crash 和 anr的区别

crash 和 anr的区别 crash 表现:程序奔溃或闪退。 影响:1、程序无法继续运行,数据丢失。2、糟糕的用户体验 产生原因: 从Android框架可区分为Application Crash和Native Crash。 Application Crash由于java层线程因未捕获异常而终止,由系统的void uncaughtException(Thread t,Throwable e) 方法进行捕获和处理,通常会给出界面弹窗提示“***已停止运行。”。 Application Crash常见

sinat_26192119的博客 1万+

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Android ANR 原因分析与检测

ANR,即应用程序不响应(Application Not Responding)。在主线程中进行某些耗时操作,超过一定时间,系统就会弹出ANR对话框。此时可以选择等待,让程序跑完,也可以选择关闭应用程序。 一、 ANR 原因分析只有当应用程序的UI线程响应超时才会引起ANR,超时产生的原因一般有两种: 当前事件没有机会得到处理,例如UI线程正在响应另一个事件,当

half_bottle的博客 2161

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Android ANR程序无响应及其异常定位

android 开发过程中有时会遇见项目无响应异常,这类异常异常并不像Crash那样打印log信息,因此无法被捕获。所以来看一下这个ANR异常的出现原因及其定位。关键字:        主线程阻塞:网络访问等的线程阻塞,CPU满负荷, I/O阻塞,内存不够用等都会造成代码长时间执行,后面统称为 主线程阻塞。1 首先什么是ANR?       在一般的理解中ANR就是将主线程阻塞,当主线程阻塞超过相...

lijinzhao3141592的博客 8761

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

安卓ANR问题最全解析

安卓ANR问题最全解析

似霰的博客 7746

Android开发——APP ANR治理

ANR(Application Not Response)指应用程序无响应,通常出现在主线程被阻塞时,并伴随ANR弹窗出现。ANR的治理难点是不像Crash一样有崩溃日志,定位问题比较困难,但是ANR带来的用户体验是极差的,是必须要解决的问题。

关于Android开发的一些技术点总结 ╮( ̄▽ ̄”)╭ 8176

Android App异常检测及处理

Android App常见的异常可分为三种:ANR,Crash及OOM。当异常发生时如何正确的获取日志定位问题非常重要。本文针对这三种异常分别给出了处理建议,并提供了一些日志收集框架及日志上传的思路。 ANR ANR(Application No Response),俗称应用卡顿。在Android中所有KeyEvent和TouchEvent都是按照先后顺序放入队列中,依次执行,并且只有当前一个事件...

lbcwnu的博客 4422

android ANR异常分析技巧总结

前言 ANR异常是android开发中比较常见的异常之一,最近为了看ANR异常,差了不少资料,现在做一个总结。 本文将从以下几个角度来总结ANR异常分析: 1.ANR类型 2.ANR产生的原因 3.ANR日志来源 4.分析ANR问题的套路 1. ANR类型 ANR类型按报错类型主要有Input(输入事件)、Broadcast(广播)、Service(服务), 对应产生ANR的时间分别为: 类型 前台应用 后台应用 Input 5s 5s Broadcast 10s 6...

转载和创作优秀的博客 4002

xCrash 捕获ANR异常

ANR异常 android ANR 异常的英文全称是 “Application Not Responding”,中文意思即为应用无响应。 在介绍xCrash捕获ANR异常时,先简单介绍一下ANR异常,以及产生ANR异常的原因,以及ANR常用的处理方式。 ANR异常产生的类型 KeyDispatchTimeout。UI主线程对于输入事件,即Inputdispatch事件超过5S没有处理产生ANR。...

cxmfzu的博客 2245

Android ANR 总结

解决ANR一直是Android 开发者需要掌握的重要技巧,一般从三个方面着手。开发阶段:通过工具检查各个方法的耗时,卡顿情况,发现一处修改一处。线上阶段:这个阶段主要依靠监控工具发现ANR并上报,比如matrix。分析阶段:如果线上用户发生ANR,并且你获取了一份日志,这就涉及了本文要分享的内容——ANR日志分析技巧。

easonguolong的博客 1594

android 异常测试,Android App异常检测及处理

Android App常见的异常可分为三种:ANR,Crash及OOM。当异常发生时如何正确的获取日志定位问题非常重要。本文针对这三种异常分别给出了处理建议,并提供了一些日志收集框架及日志上传的思路。ANRANR(Application No Response),俗称应用卡顿。在Android中所有KeyEvent和TouchEvent都是按照先后顺序放入队列中,依次执行,并且只有当前一个事件执行...

weixin_40006185的博客 1273

android ANR报错异常处理

ANR 是android开发中常见的异常,报错的原因多种多样,还需要根据具体的现象找原因。 通常最常见的是在处理耗时的任务或者连接时间过长会导致ANR 1. 10-27 09:08:37.031 648 1118 E ActivityManager: +0% 924/kworker/2:0: 0% user + 0% kernel 10-27 09:08:37.031 648 1118 E ActivityManager: +0% 1014/logcat: 0% user + 0% ...

lsbsheng的博客 4414

【Android】 ANR异常分析

ANR异常分析

Crazy程序猿 2611
上一篇: JAVA开发之MYSQL数据库知识点全掌握
下一篇: 关于Android大数据收集,埋点统计的详细讲解以及案例代码分析附github代码
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值