Files
matrix-screen-controller/移动端相关内容/安卓app/如何安卓测试/常见问题与排障.md
T

8.4 KiB

Android 测试常见问题与排障

测试前阅读本文件及 可重复测试流程。这里维护可复用的方法;单次失败、重测次数、耗时与验收结果写入 ../测试结果归档/。本页依据 四栏版真机记录 整理,方法有效不等于所有同类错误均有相同根因。

1. root 命令在 instrumentation 中失败

主机 ADB 的 su -c 检查通过,但 UiDevice.executeShellCommand("su -c '...'") 失败时,先检查命令解析。该入口不能假设经过交互 shell;字符串中的引号不保证按 shell 语法处理。已验证做法是调用短时上传的 LF shell 辅助文件,由文件内部执行 su -c "$*"。布局检查使用 authorized_root_command.sh;点击、滑动、编辑使用有前台限制的 authorized_app_input.sh。运行器结束清理手机临时文件。

区分命令构造错误与真实权限不足。真实 root/ADB/授权不可用时停止等待用户,不继续测试、不使用普通注入或无障碍动作替代。辅助文件只用于已授权的本软件调试,不扩大用途。

2. Windows 写出的 shell 文件无法执行

CRLF 会破坏 Android/Linux shell 的解释器或参数。生成 .sh 使用显式 UTF-8/LF(例如 Path.write_bytes,或文本写入指定 newline="\n"),不要依赖 Windows 文本默认换行。上传前检查不含 CRLF;Git 的 *.sh eol=lf 不能代替对本次生成文件的检查。不要因脚本解析失败反复请求 root。

3. 布局变更终止测试进程

在 instrumentation 运行中改变密度、字体或方向,可能使应用/测试进程重建或终止。不要把此类 Process crashed 直接当成产品崩溃,也不要在同一进程里继续依赖原窗口句柄。

使用 run_ui_layout_test.py:电脑端先保存原密度覆盖、字体和旋转设置,在每组测试启动前设置目标布局;测试启动后显式启动 Activity,再读取语义节点并执行 root 输入。电脑端 finally 在正常结束或失败时恢复原值,原设置不存在时删除对应项,原密度未覆盖时使用 reset。字体/方向回读核验;若新增 USB 保持唤醒等设置改动,同样必须先保存、恢复并核验,不以默认值猜测。安全锁屏不能正常解锁时等待用户,不绕过密码。

4. 窗口转储看不到控件、文字重复或节点不可点击

独立 uiautomator dump 在本机 MIUI 上曾无法稳定读取 App 控件。使用已验证的持久 instrumentation 入口读取语义节点;读取不是无障碍动作注入。不要盲点坐标,也不要因此改用无障碍点击。

Compose 的可见文字节点未必有 clickable 标志,导航“连接”也可能与扫描结果按钮同名。先限制 App 包、当前页面/条目容器,再筛选可见且边界非空的节点;底栏可按同名可见节点位置选择。检查边界在当前屏幕内,重新读取中心点后执行 root tap。等待页面加载完成再取位置,布局变化后不可复用旧坐标。列表滚动只在语义识别出的本 App 可见滚动区域内执行 root swipe。

5. 找不到 DHCP 开关或密码可见复选框

Compose 语义树不保证使用 android.widget.Switch/CheckBox 类名。定位标签附近的 checkable 节点:按标签实时纵向范围筛选,并结合行内左右位置区分 DHCP 开关与密码可见复选框。点击后检查 checked 状态或静态地址字段是否出现;不要只认按钮类名,也不能用一个任意 checkable 节点代替。

6. 文本未清空、中文/密码输入失败、返回键退出 App

Ctrl+A 在该测试环境下不可靠。现有做法:App 前台进程设置临时剪贴板,root 点击实时字段位置,按 MOVE_END,再按当前文本长度加余量执行有界 DEL,最后 root paste。清空操作计数有上限,输入后回读字段核验。剪贴板在 finally 清理,密码不放 ADB 参数、日志或公开转储中。

仅在输入法实际显示时发送 BACK 收起键盘;否则 BACK 可能退出页面。使用 helper 的 hide-keyboard 分支检查 mInputShown。等“屏幕方向”等设置数据就绪后才展开 WiFi 表单,避免数据加载改变控件位置。

7. 保存按钮的禁用断言失败

Compose 的禁用语义可能位于父节点,文字节点自身仍 enabled。检查文字所在控件及祖先链的 enabled 状态,并结合实际行为(空名称不能打开确认/提交)判断;不要只断言文字节点的 enabled。

8. 安装成功后权限又被 MIUI 重置

adb install 成功不证明蓝牙权限稳定。现有运行器在覆盖安装后通过 root 授予本 App 必需权限,等待 3 秒并回读;最多三轮,仍未稳定则停止等待用户。不能无限重试,不能修改其他系统安全开关。测试前仍检查登记、ADB、root、前台和必要权限。

9. 连续测试的 BLE 扫描或握手偶发失败

每个正常测试阶段结束时通过连接页显式断开,等待释放后再结束进程;不要只依赖紧接着的 force-stop。异常时按失败阶段记录扫描、GATT、握手/任务是否已开始,清理旧测试会话后重新扫描,不跨会话复用临时句柄。主机超时不会自动终止 instrumentation,运行器还需结束本 App 的旧测试进程。

确需核验板端服务恢复时,先确认手机已断开,再执行 check_mobile_lifecycle.py --restart-service;它会真实停启服务并核验运行目录、持久摘要和接口恢复。保留首次失败,恢复后通过不证明偶发扫描失败的根因。若重现持续存在,停止反复重启,针对具体阶段排查,不降低超时/断言来制造通过。

10. WiFi 专项不具备第二网络、错误密码时 SSH 断开

--validate-only、--wrong-only、--final-check 不要求电脑热点;错误密码单测使用当前受管网络。跨 SSID 的 DHCP/静态往返才需要第二个可用网络;缺少时标未验证,不拿重应用原网络或表单测试替代。

任何真实切网先保存受保护原 NetworkManager 配置,并核验定时恢复已建立。错误密码可能使 SSH 断开,继续通过 BLE 查看任务,等待定时恢复;连通后比较原配置摘要、活动网络与服务状态,再清理备份和定时器。网络恢复没有核验就不能写通过,也不能提前删除唯一恢复材料。

失败任务必须区分提交前握手失败与已经提交后的网络失败。“密码错误”只在可靠认证证据/结构化 AUTH_FAILED 下通过验收;超时、缺少 secret 或未知错误不能强行归类。确认密码未进入日志,清理手机私有文件和临时剪贴板,最后执行 --final-check。

11. 测试完成后的固定复盘

每轮检查:本轮有哪些失败/调整、是否已有可重复防范步骤、恢复是否核验、哪些原因仍未知。已验证解法更新本页和对应流程/构建说明;一次性证据留归档,不能将未证实推测写成固定根因。

最终反馈写明经验已更新的文档,以及尚未解决的问题或未验证边界。若没有新增经验,说明沿用现有方法即可,不复制重复条目。遵守根协作规则:不写真实凭据、手机标识、开发机绝对路径,文档更新后执行仓库卫生检查。

12. 轮询或滑动后节点失效、名称可见但按钮无法点击

本轮三种布局已验证:读取语义节点期间可能出现 StaleObjectException,应在原有有界期限内丢弃旧节点并重新查找,不复用旧坐标、不放宽断言。滚动定位使用 connection_list 的实时可见边界;扫描按钮还要限制在目标设备条目容器,检查按钮启用且 visibleBounds 非空。名称露出不证明兄弟按钮可见,空边界不能取中心点点击。

滑动后通过两次间隔400毫秒的实时边界相等检查确认目标停稳(最多5秒),然后仅发送一次 root 点击;不因未看到中间状态而重复点击连接。记录初次连接、连接中扫描、两处预览、条目断开、手动重连等阶段。短暂“连接中”未被观测不代表未发起请求,终态以认证连接和条目状态核验为准。

本轮失败、恢复与最终结果见 ../测试结果归档/2026-09-27_界面细节优化/;重测通过不证明此前连接未出现的唯一根因。字体、旋转和密度恢复后均回读核验。