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文件 | |
文件修改时间是否对齐ANR时间;是否包含“main”线程堆栈;是否出现“Permission”相关锁等待。 |
| Logcat权限日志 | |
是否包含“checkPermission”调用链;是否存在“onRequestPermissionsResult”超时。 |
| 日志缓冲区 | |
确保缓冲区未被大量WIFI或BLE日志冲掉,保证ANR日志不会遗失。 |
避坑指南: 非Root设备无法直接读取
/data/anr/,必须先执行 adb shell cp /data/anr/traces.txt /sdcard/ 转存后再拉取,否则会报权限错误。
3.3 原因定位(数据视角)
拿到Trace文件和Logcat后,不要马上尝试修复,而是要通过数据特征缩小排查范围。权限回调ANR有非常明显的特征码。
故障树分析(FTA)判断规则:
- 节点1: Trace文件中主线程是否处于
RUNNABLE状态? → 是(继续),否(排查其他锁等待)。 - 节点2: 主线程栈顶是否包含
PermissionManagerService.checkPermission或BinderProxy.transact? → 是(定位为权限IPC阻塞),否(排查其他系统服务IPC)。 - 节点3: Logcat中是否存在
PermissionController的onRequestPermissionsResult超时日志? → 是(确认是回调问题),否(可能是权限Service本身卡死)。
3.4 修复动作(采集流程优化)
针对数据采集过程中可能遇到的问题,我们需要优化采集脚本或设备配置:
- 修复Trace文件为空: 检查设备是否开启“开发者选项”中的“显示所有ANR”,确保应用为Debuggable版本。
- 修复Logcat截断: 增大日志缓冲区大小,并定时保存历史日志:
adb logcat -b main -b system -G 32M - 手动触发补采: 如果系统未自动生成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快速定位回调是否被正确触发。