用途
本技能面向测试与 QA 工程师,讲解如何通过 adb shell 从主机端驱动 Android 设备,模拟用户手势、覆盖屏幕配置、切换系统设置、重置应用状态并启动 Activity,从而在 CI 中脚本化用户旅程,而无需编写 instrumentation 测试。
主要能力
input — 合成用户事件
input 是设备端对 InputManager.injectInputEvent() 的封装,语法为 input [<source>] <command> [<arg>...]。
- 点击、滑动、拖放:
adb shell input tap <x> <y>adb shell input swipe <x1> <y1> <x2> <y2> [<duration_ms>]adb shell input draganddrop <x1> <y1> <x2> <y2> [<duration_ms>]adb shell input roll <dx> <dy>adb shell input motionevent <DOWN|UP|MOVE|CANCEL> <x> <y>
- swipe 省略时长时默认约 300 ms;长按可用原地滑动实现:
input swipe <x> <y> <x> <y> 1000。draganddrop 与 swipe 不同,它发出可被 View.OnDragListener 消费的拖放手势序列(DOWN → MOVE → UP)。 - 文本输入:
adb shell input text "<string>"。空格必须编码为%s;shell 元字符需双重转义;非 ASCII/Unicode 不可靠,应改用 UiAutomator 的 UiObject2.setText(...)。 - 按键事件:
adb shell input keyevent [--longpress|--doubletap] <KEYCODE> [<KEYCODE>...],也支持数字码。常用 KEYCODE 包括 HOME(3)、BACK(4)、DPAD 方向键(19-23)、音量键(24/25/164)、POWER(26)、TAB(61)、ENTER(66)、DEL(67)、MENU(82)、APP_SWITCH(187)、WAKEUP(224)、SLEEP(223)。 - 来源前缀:touchscreen、touchpad、dpad、keyboard、mouse、trackball、gamepad/joystick、stylus,用于多输入监听或非触摸硬件场景。
wm — 显示尺寸与密度覆盖
adb shell wm size读取/覆盖/重置逻辑尺寸;adb shell wm density读取/覆盖/重置 dpi。adb shell wm dismiss-keyguard、adb shell wm user-rotation [free|lock [<rotation>]]。- 可在不重建模拟器的情况下构建屏幕尺寸/密度矩阵,但必须在 teardown 中调用 reset,否则设备会停留在修改后的配置。wm size/density 会触发配置变更并重建前台 Activity,应作为测试间旋钮而非测试中操作。
settings — 封闭测试状态
- 语法:
adb shell settings [--user <id>] get|put|delete|reset|list <namespace> <key> ...,namespace 为 global、system、secure。 - 封闭测试前导:将 window_animation_scale、transition_animation_scale、animator_duration_scale 三个动画缩放设为 0,或使用 Gradle 的 testOptions.animationsDisabled = true。
- 其他测试相关键:system/font_scale、secure/accessibility_enabled、secure/enabled_accessibility_services、secure/default_input_method、secure/show_ime_with_hard_keyboard、secure/long_press_timeout、global/airplane_mode_on、global/policy_control。
应用状态 — am force-stop 与 pm clear
am force-stop <pkg>:杀进程,不清数据/缓存/偏好,不重置运行时权限。pm clear <pkg>:杀进程并清数据/缓存/偏好,重置运行时权限。cmd activity stop-app <pkg>:现代等价(API 28+),仅杀进程。- 测试间封闭重置应使用 pm clear;仅需冷启动时 am force-stop 足够。
启动 Activity — am start
- 显式组件:
adb shell am start -n com.example.app/.MainActivity - 冷启动:
adb shell am start -S -W -n com.example.app/.MainActivity(-S 先强制停止,-W 阻塞至启动完成)。 - 按 action + URI:
adb shell am start -a android.intent.action.VIEW -d 'https://example.com' - 传递类型化 extras:
--es、--ez、--ei、--el、--ef、--eu、--ecn、--eia/--ela/--efa等。 - 返回启动器:
adb shell am start -a android.intent.action.MAIN -c android.intent.category.HOME
cmd <service> — 现代包装
自 API 24 起可用,调用 binder 服务的 onShellCommand。测试相关入口包括:cmd activity stop-app、cmd activity broadcast、cmd package install、cmd package compile、cmd appops set、cmd jobscheduler run、cmd uimode night、cmd locale set-app-locales、cmd statusbar expand-notifications/collapse、cmd wifi set-wifi-enabled、cmd connectivity airplane-mode、cmd testharness enable。
svc 在 API 30+ 的弃用
svc data、svc wifi、svc bluetooth 在 API 30+ 上除非从特权 shell 调用,否则静默无操作。应改用上述 cmd 包装命令。
使用方式
典型封闭测试前导:
adb shell settings put global window_animation_scale 0
adb shell settings put global transition_animation_scale 0
adb shell settings put global animator_duration_scale 0
adb shell pm clear com.example.app
adb shell am start -S -W -n com.example.app/.MainActivity
TV/焦点导航:
adb shell input dpad keyevent KEYCODE_DPAD_DOWN
adb shell input dpad keyevent KEYCODE_DPAD_CENTER
适用场景
- 从 CI 脚本化用户旅程,无需编写 instrumentation。
- 需要特定屏幕尺寸或密度复现 bug,而不重建模拟器 AVD。
- 因动画导致测试不稳定,需要封闭前导。
- 需要在测试间清除应用数据。
- 需要启动带类型化 extras 的深链 Activity。
限制与强制规则
- API 30+ 必须使用 cmd wifi set-wifi-enabled / cmd connectivity airplane-mode / cmd bluetooth_manager enable,不得依赖 svc。
- 测试间封闭重置必须使用 pm clear,而非 am force-stop。
- input text 中空格必须编码为 %s;含 shell 元字符的字符串必须双重 shell 引号(Platform Tools 23+)。
- 套件覆盖 wm size/density 后必须在 teardown 中 reset。
- 任何 UI 断言测试前必须将三个动画缩放设为 0。
- 不得在 adb shell input 调用之间使用 Thread.sleep;instrumentation 内使用 Compose idle 同步,主机脚本使用 am start -W 阻塞启动。
- 不得假设 adb shell am instrument 在无 -w 时返回有意义的退出码。
- 推荐使用 am start -S -W -n pkg/.Activity 进行冷启动。
验证清单
- 测试前 settings get global window_animation_scale 返回 0。
- 脚本中无 svc wifi/bluetooth/data。
- 每个 am force-stop 均配对或替换为 pm clear。
- 无含空格的 input text 字符串,空格均为 %s。
- 每个 wm size 覆盖均有对应 reset。
- CI 连续 50 次运行无“设备进入先前配置”的抖动。
前置条件
- 可达的设备或模拟器(adb get-state 返回 device)。
- 主机上 Platform Tools 23+。
- cmd 包装 API 与可靠 shell 退出码需设备 API 24+。
不适用场景
- 需要从设备取出字节(截图、日志、数据库)。
- 从 instrumentation 测试内部驱动设备。
- 安装或卸载 APK。
- 首次连接设备。