Android ANR详解(上)

本文介绍了Android系统的ANR(App Not Responding)机制,包括ANR的原理、监控方式及如何获取ANR信息等内容。通过了解ANR的工作机制,可以帮助开发者更好地诊断和解决应用中的卡顿问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.ANR简介

ANR 全称 Applicatipon No Response。Android 设计 ANR 的用意,是系统通过与之交互的组件(Activity,Service,Receiver,Provider)以及用户交互(InputEvent)进行超时监控,以判断应用进程(主线程)是否存在卡死响应过慢的问题。

系统在通过Binder通信应用进程发送上述组件消息或 Input 事件时,在 AMS Input 服务端同时设置一个异步超时监控。

针对不同类型事件,设置的超时时长也存在差别,以下是 Android 系统对不同类型的超时阈值设置

二.ANR监控

1.ANR WatchDog检测

既然ANR的原因是进程在一定时间内没有响应,那么我们很自然地想到,向主线程发送一个任务,如果一段时间内没有被执行的话,就认为发生了 ANR。

弊端:不准确,超时时间不固定,有可能是5秒有可能是10秒。且周期也不一定同步。

2.ANR 信号监听

我们注意到当 ANR 发生时会发送 SIGQUIT 信号,那么我们通过监听这一信号不就可以实现 ANR 监控了吗?

默认情况下进程通过SignalCatcher监听SIGQUIT信号,进行堆栈转储生成 ANR Trace 文件。因此当我们监听SIGQUIT信号后,需要重新向SignalCatcher发送SIGQUIT。

如果缺少重新向 SignalCatcher 发送 SIGQUIT 信号的步骤,Android System 管理服务(AMS)将一直等待 ANR 进程写入堆栈信息。直到超过20秒的超时时间,AMS 才会被迫中断,并继续后续流程。这将导致 ANR 弹窗的显示非常缓慢(因为超时时间为20秒),同时在 /data/anr 目录下也无法生成完整的 ANR Trace 文件。

弊端:当监听到 SIGQUIT 信号时,不一定是发生了 ANR。当进程被标为 NOT_RESPONDING 时一定发生了 ANR,但是当进程发生了 ANR 时,不一定会被标记为 NOT_RESPONDING。

解决办法:监听到信号时再进行一次检查,在 ANR 弹窗前,会给发生 ANR 的进程标记一个 NOT_RESPONDING 的 flag,而这个 flag 我们可以通过 ActivityManager 来获取

代码:

/**
 * 当前进程是否处于ANR状态
 */

@RequiresApi(api = Build.VERSION_CODES.M)
public static boolean isAnrErrorState(Application application) {
    if (null == application) return false;
    try {
        ActivityManager activityManager = (ActivityManager) application.getSystemService(Context.ACTIVITY_SERVICE);
        if (null != activityManager) {
            List<ActivityManager.ProcessErrorStateInfo> processErrorStateInfoList = activityManager.getProcessesInErrorState();
            if (null == processErrorStateInfoList) return false;
            for (ActivityManager.ProcessErrorStateInfo proc : processErrorStateInfoList) {
                if (null == proc || proc.pid != android.os.Process.myPid()) {
                    continue;
                }
                if (proc.condition != ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING) {
                    continue;
                }
                return true;
            }
            return false;
        }
    } catch (Throwable ignored) {

    }
    return false;
}

三. 获取 ANR Info

/**
 * 获取ANR状态的进程shortMessage信息
 */

@SuppressLint("ServiceCast")
public static String getAnrShortMessage(Application application) {
    if (null == application) return "";
    ActivityManager.ProcessErrorStateInfo info = (ActivityManager.ProcessErrorStateInfo) application.getSystemService(Context.ACTIVITY_SERVICE);
    return (null != info) ? info.shortMsg : "";
}

/**
 * 获取ANR状态的进程longMsg信息
 */

@SuppressLint("ServiceCast")
public static String getAnrLongMsg(Application application) {
    if (null == application) return "";
    ActivityManager.ProcessErrorStateInfo info = (ActivityManager.ProcessErrorStateInfo) application.getSystemService(Context.ACTIVITY_SERVICE);
    return (null != info) ? info.longMsg : "";
}

更多内容:Android ANR详解(下)_rxjava详解_jianning-wu的博客-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值