3. 数据采集准备:开启ANR日志、抓取trace文件、获取logcat权限相关日志

3.1 现象识别

在开始数据采集前,必须确认系统已进入ANR状态,且环境具备可诊断条件。权限回调导致的ANR通常伴随以下现象:

  • UI冻结: 界面点击无反馈,触摸事件无法传递。
  • 系统ANR对话框: 弹出“应用无响应”提示,等待或关闭按钮可能无效。
  • 日志特征: logcat 中会出现 ANR in com.xxx 标志性消息。
判断规则: 如果通过 adb logcat -v threadtime | grep "ANR" 看到目标包名的ANR记录,且时间与用户上报卡死时间一致,即可100%确认现象。

3.2 数据采集

本阶段核心目标是“快照现场”,通过多渠道获取ANR发生时刻的完整系统状态。数据采集的质量直接决定定位效率。

数据源采集命令/位置核心检查点
ANR Trace文件
adb shell ls -l /data/anr/
adb pull /data/anr/traces.txt
文件修改时间是否对齐ANR时间;是否包含“main”线程堆栈;是否出现“Permission”相关锁等待。
Logcat权限日志
adb logcat -v threadtime | grep -E "Permission|permission|PermissionController"
是否包含“checkPermission”调用链;是否存在“onRequestPermissionsResult”超时。
日志缓冲区
adb logcat -G 16M
确保缓冲区未被大量WIFI或BLE日志冲掉,保证ANR日志不会遗失。
避坑指南: 非Root设备无法直接读取 /data/anr/,必须先执行 adb shell cp /data/anr/traces.txt /sdcard/ 转存后再拉取,否则会报权限错误。
权限回调ANR数据采集流程 现象:应用发生ANR 数据源:Trace文件 数据源:Logcat日志 检查:权限调用栈 定位:主线程等待回调 动作:提取Trace与Logcat 核心检查点 1. 主线程堆栈 2. Binder调用链 3. Permission IPC

3.3 原因定位(数据视角)

拿到Trace文件和Logcat后,不要马上尝试修复,而是要通过数据特征缩小排查范围。权限回调ANR有非常明显的特征码。

故障树分析(FTA)判断规则:
  1. 节点1: Trace文件中主线程是否处于 RUNNABLE 状态? → 是(继续),否(排查其他锁等待)。
  2. 节点2: 主线程栈顶是否包含 PermissionManagerService.checkPermission 或 BinderProxy.transact? → 是(定位为权限IPC阻塞),否(排查其他系统服务IPC)。
  3. 节点3: Logcat中是否存在 PermissionController 的 onRequestPermissionsResult 超时日志? → 是(确认是回调问题),否(可能是权限Service本身卡死)。

3.4 修复动作(采集流程优化)

针对数据采集过程中可能遇到的问题,我们需要优化采集脚本或设备配置:

  1. 修复Trace文件为空: 检查设备是否开启“开发者选项”中的“显示所有ANR”,确保应用为Debuggable版本。
  2. 修复Logcat截断: 增大日志缓冲区大小,并定时保存历史日志:
    adb logcat -b main -b system -G 32M
  3. 手动触发补采: 如果系统未自动生成Trace,立即通过 adb shell kill -3 <pid> 手动触发Java线程dump。

3.5 复测

验证数据采集配置是否生效:

  • 复测用例: 编写测试脚本,高频触发 ActivityCompat.requestPermissions,模拟用户连续点击授权弹窗场景。
  • 通过标准: 发生ANR后,adb pull /data/anr/traces.txt 能成功获取到文件,且文件内容包含 main 线程在 PermissionController 上的阻塞堆栈。
  • 失败标准: 拉取的Trace文件为空,或Logcat日志在ANR前后被大量其他日志覆盖。
复测技巧: 使用 adb shell dumpsys activity processes | grep "anr" 可以实时监控系统是否正在记录ANR状态。

3.6 预防

在项目初期建立标准化的数据采集规范,能极大提升ANR问题诊断效率:

  • 自动化采集脚本: 利用 adb 实时监控 ANR 关键词,一旦命中自动执行 adb pull /data/anr/ 和 adb logcat -d > log.txt。
  • 日志轮替策略: 设置 adb logcat -G 64M 并配合 logrotate 策略,确保关键日志不被冲掉。
  • 埋点与监控: 在 onRequestPermissionsResult 回调入口和出口各添加一条唯一的Log.e埋点,便于后续通过Logcat快速定位回调是否被正确触发。