关于 capturing-screenshots-and-screenrecord
该技能指导 Android 开发者通过 ADB 获取 PNG 截图和 MP4 屏幕录制,并在 JUnit4 测试失败时收集截图与日志。重点说明二进制流完整性、录制限制及失败时采集模式。
主要功能
- 01通过 ADB 获取 PNG 截图
- 02录制设备屏幕为 MP4
- 03JUnit4 失败时收集截图与日志
- 04避免二进制输出损坏
- 05处理录制时长与停止限制
适用场景
- 01为失败的 CI 测试保存截图和 logcat
- 02从参考设备生成视觉回归截图
- 03录制 QA 复现视频并关联日志
- 04修复 Windows CI 中损坏的截图流
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ skydoves/ android-testing-skills --skill capturing-screenshots-and-screenrecord安装后在 Claude Code 中输入/capturing-screenshots-and-screenrecord确认已加载。
详细介绍
截取屏幕截图和录屏——用于测试的视觉产物
此技能介绍如何通过 adb 从设备截取 PNG 屏幕截图和录制 MP4 视频,以及如何使用 JUnit4 TestWatcher 模式在测试失败时捕获内容。本节不涉及 Android Studio 的屏幕截图工具、Compose captureToImage(),或第三方串流工具(scrcpy/Vysor)。
何时使用此技能
- 不稳定的 CI 测试需要在失败时截取屏幕截图并转储 logcat。
- 团队需要从参考设备生成视觉回归测试的黄金截图。
- QA 需要录制一段 30 s 的问题复现视频,附在缺陷报告中。
- 开发者运行
adb shell screencap /sdcard/out.png生成了损坏的文件——缺少-p标志导致写入的是原始 RGBA,而不是 PNG。 - Windows CI Agent 收到的屏幕截图存在 CRLF 损坏——解决方法是
adb exec-out screencap -p。
何时不使用此技能
- 使用
captureToImage()/ Roborazzi / Paparazzi 的 Compose 层屏幕截图测试。这些属于单元测试机制,应使用 Compose 套件,而不是 ADB。 - 持续实时镜像设备(演示、展示)。请使用 scrcpy 或 Vysor——
screenrecord无法串流。 - 先操作设备(点击、按键事件)。请使用
../../control/injecting-input-and-state/SKILL.md。 - 常规拉取文件(不只是屏幕截图)。请使用
../../transfer/extracting-test-artifacts/SKILL.md。
前提条件
adb get-state返回device。请参阅../../devices/connecting-to-devices/SKILL.md。- 使用
screenrecord:设备 API 19+(Android 4.4)——screenrecord是在 KitKat 中加入的。 - 使用 Wear OS 的
screenrecord:不支持。该工具会拒绝执行(developer.android.com/tools/adb#screenrecord)。 - API 30+ 上写入
/sdcard/:需遵循分区存储规则;shell用户仍可通过 FUSE/sdcardfs 访问,但应用私有写入会转到/sdcard/Android/data/<pkg>/。
screencap——PNG 屏幕截图
“
screencap命令是一个 shell 工具,用于截取设备显示内容。”——developer.android.com/tools/adb#screencap
screencap [-h] [-p] [-d <displayId>] [<path-on-device>]
| 标志 | 含义 |
|---|---|
| (无标志) | 将原始 RGBA 帧缓冲区写入文件。不是 PNG。 |
-p | 编码为 PNG。向主机的标准输出流式传输时必须使用。 |
-d <displayId> | 捕获指定的逻辑显示屏(多显示屏设备)。 |
-h | 帮助。 |
三种惯用调用方式:
# 1. Save to device, then pull (good when the test continues running).
adb shell screencap -p /sdcard/screen.png
adb pull /sdcard/screen.png ./screen.png
# 2. Stream PNG bytes back to host without an intermediate file.
adb exec-out screencap -p > screen.png
# 3. Multi-display capture: external display + main.
adb shell screencap -p -d 0 /sdcard/main.png
adb shell screencap -p -d 1 /sdcard/external.png
exec-out 与 shell——二进制数据干净传输的陷阱
adb shell 默认会建立 PTY,在某些主机上(尤其是 Windows)会在输出时将 \n 转换为 \r\n。对于二进制流(PNG、MP4、tar 归档),这会损坏文件。adb exec-out 是可干净传输二进制数据的标准输出方式。
操作建议——在 Windows 上,流式传输时切勿使用 adb shell screencap -p > out.png。请始终使用:
adb exec-out screencap -p > out.png
如果先将文件写入设备,再拉取到主机,则不会出现此问题(adb pull 可干净传输二进制数据)。
screenrecord——MP4 录屏
“
screenrecord命令是一个 shell 工具,用于录制运行 Android 4.4(API 级别 19)及更高版本的设备显示内容。该工具会将屏幕活动录制为 MPEG-4 文件。”——developer.android.com/tools/adb#screenrecord
screenrecord [--size WIDTHxHEIGHT] [--bit-rate RATE] [--time-limit TIME]
[--rotate] [--bugreport] [--verbose] <path-on-device>
| 标志 | 原文含义(developer.android.com/tools/adb#screenrecord) |
|---|---|
--help | “显示命令语法和选项”。 |
--size WxH | “设置视频尺寸。默认值为设备的原生显示分辨率(如果支持),否则为 1280x720。” |
--bit-rate R | “设置视频的比特率,单位为兆比特每秒。默认值为 20Mbps。” |
--time-limit T | “设置最长录制时间,单位为秒。默认值和最大值均为 180(3 分钟)。” |
--rotate | “将输出旋转 90 度。此功能为实验性功能。” |
--bugreport | 嵌入用于缺陷报告附件的文本帧信息 / 时间戳叠加层。 |
--verbose | “在命令行屏幕上显示日志信息。” |
硬性限制(原文)
- “视频文件中不会录制音频。”
- “运行 Wear OS 的设备不支持视频录制。”
- “某些设备可能无法以原生显示分辨率录制。如果屏幕录制遇到问题,请尝试使用较低的屏幕分辨率。”
- “录制期间不支持旋转屏幕。”
- 默认和最长时限为 180 s。若要捕获更长的场景,请串联多次调用并在事后合并,或使用 scrcpy。
没有流式传输标志 — 此限制
screenrecord 会将单个 MP4 写入设备端路径;它不会将内容流式传输到 stdout。要进行实时镜像(演示、展示),请使用 scrcpy 或 Vysor(不属于此技能的范围——两者都会完全绕过 screenrecord)。
输出路径
| 路径 | 使用时机 |
|---|---|
/sdcard/run.mp4 | 默认路径。用户可见的视频。API 30+ 适用分区存储规则,但 shell 用户可通过 FUSE/sdcardfs 访问。 |
/data/local/tmp/run.mp4 | 当测试应用必须在 SD 卡挂载前生成输出,或要避免触碰公共存储时使用。shell 始终可以拉取此文件。 |
提前停止
screenrecord 会持续运行,直到 --time-limit 到期或收到 SIGINT。从交互式 shell 中按 Ctrl+C。从脚本中向设备端进程发送信号:
adb shell screenrecord --time-limit 180 /sdcard/run.mp4 &
REC=$!
# … run instrumentation; on failure, send SIGINT to the on-device process …
adb shell pkill -INT screenrecord
wait $REC
adb pull /sdcard/run.mp4 ./run.mp4
--bugreport 叠加层
--bugreport 会为每一帧添加帧信息和时间戳叠加层,这对于 QA 复现很有用,可使错误报告中的时间戳与 logcat 对齐。搭配 adb logcat -v threadtime,year,UTC,即可关联帧编号和日志行(参见 ../../observability/extracting-logs-with-logcat/SKILL.md)。
失败时捕获模式(JUnit4 TestWatcher)
标准模式:TestRule 或 TestWatcher 在测试失败时触发 failed(),运行 screencap + logcat -d,并将生成的文件拉取到每个测试各自的目录中。
class CaptureOnFailureRule(private val outputDir: File) : TestWatcher() {
override fun failed(e: Throwable, description: Description) {
val testName = "${description.className}.${description.methodName}"
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
val target = File(outputDir, testName).apply { mkdirs() }
// PNG screenshot
device.executeShellCommand("screencap -p /sdcard/fail.png")
device.executeShellCommand("logcat -d -v threadtime").let { log ->
File(target, "logcat.txt").writeText(log)
}
// The test process can pull /sdcard/fail.png via Context.getExternalFilesDir
// or push through TestStorageService — see ../../transfer/extracting-test-artifacts/SKILL.md.
}
}
CI 脚本中的主机端等效做法(完整版本参见 ../../automation/scripting-adb-for-ci/SKILL.md):
set +e
./gradlew connectedDebugAndroidTest
RC=$?
set -e
if [ "$RC" -ne 0 ]; then
mkdir -p artifacts
adb shell screencap -p /sdcard/fail.png
adb pull /sdcard/fail.png artifacts/fail.png
adb logcat -d -v threadtime > artifacts/logcat.txt
adb logcat -d -b crash -v threadtime > artifacts/crash.txt
fi
exit $RC
此操作仅在失败时捕获设备的最后一帧以及 logcat 转储(绿色运行时可节省 CI 存储空间)。如需更丰富的逐测试文件路由,建议使用 AndroidX TestStorageService API — 参见 ../../transfer/extracting-test-artifacts/SKILL.md。
模式
模式:错误做法 — screencap 未加 -p
# WRONG
adb shell screencap /sdcard/out.png
file /sdcard/out.png # → "data" (not a PNG)
# WRONG because: without -p, screencap writes a raw RGBA framebuffer (header + naked pixel
# bytes), not a PNG. Image viewers refuse to open it. The .png extension is misleading.
# RIGHT
adb shell screencap -p /sdcard/out.png
adb pull /sdcard/out.png ./out.png
模式:错误做法 — 在 Windows 上运行 adb shell screencap -p > out.png
# WRONG (on Windows / certain CI hosts)
adb shell screencap -p > out.png
# WRONG because: `adb shell` allocates a PTY and translates LF to CRLF on stdout. For
# binary streams (PNG bytes) this corrupts the file.
# RIGHT (binary-clean stdout)
adb exec-out screencap -p > out.png
模式:长时间捕获超过 3 分钟上限
# WRONG — assumes a single screenrecord can capture 10 minutes
adb shell screenrecord --time-limit 600 /sdcard/run.mp4
# WRONG because: --time-limit is capped at 180. The utility silently truncates to 180.
# RIGHT — chain
for i in 1 2 3 4; do
adb shell screenrecord --time-limit 180 /sdcard/run-$i.mp4
done
adb pull /sdcard/run-1.mp4 ./
adb pull /sdcard/run-2.mp4 ./
adb pull /sdcard/run-3.mp4 ./
adb pull /sdcard/run-4.mp4 ./
# Concatenate with ffmpeg if needed:
# ffmpeg -f concat -i list.txt -c copy out.mp4
(或者改用 scrcpy 进行无限时长捕获。)
模式:用于 QA 复现的错误报告叠加层
adb shell screenrecord --bugreport --time-limit 60 \
--bit-rate 8000000 --size 720x1280 /sdcard/repro.mp4
# Each frame has a frame-info + timestamp overlay aligning with logcat -v threadtime,year,UTC.
adb pull /sdcard/repro.mp4 ./repro.mp4
adb logcat -d -v threadtime,year,UTC > repro-logcat.txt
强制规则
- 必须为
screencap传入-p以输出 PNG。否则文件将是原始 RGBA 格式,无法在图像查看器中使用。 - 必须在流式捕获时优先使用
adb exec-out screencap -p > out.png,而不是adb shell screencap -p > out.png;尤其是在 Windows 或任何可能应用\n → \r\n转换的 CI 主机上。 - 必须将
screenrecord --time-limit视为最长不超过 180 s。任何更长的捕获都需要串联操作或使用 scrcpy。 - 必须使用
adb shell pkill -INT screenrecord停止screenrecord(不能从主机端使用kill -9)——SIGKILL 会导致 MP4 未完成封装而无法播放。 - 不得假定
screenrecord会捕获音频——它不会(developer.android.com/tools/adb#screenrecord)。 - 不得在 Wear OS 上使用
screenrecord——不受支持。 - **优先:**仅在失败时捕获(而非每次运行都捕获)。这样可节省 CI 存储空间,并直接定位到失败的测试。
- **优先:**每次使用
screenrecord --bugreport时,都搭配同时捕获的logcat -v threadtime,year,UTC转储。否则叠加层很难与日志关联。
验证
- 执行
adb shell screencap -p /sdcard/out.png && adb pull /sdcard/out.png后,file ./out.png报告PNG image data。 - 在 Windows CI 上,通过
adb exec-out screencap -p > out.png流式传输屏幕截图(不会因\r\n导致损坏)。 - 仅当测试退出代码非零时,CI 才会捕获
screencap和logcat -d。 - 任何脚本中都不存在
screenrecord --time-limit <N>且N > 180的情况。 - 不对
screenrecord进程执行kill -9——只使用pkill -INT screenrecord,以便完成 MP4 文件。 - CI 工件归档包含以
Class.method命名的各测试子目录。
参考资料
- developer.android.com/tools/adb#screencap —
screencap语法、-p标志、exec-out 流式传输。 - developer.android.com/tools/adb#screenrecord —
screenrecord语法、标志、硬性限制(“不录制音频”、180 秒上限、不支持 Wear OS、录制期间不能旋转)。 - developer.android.com/tools/adb#shellcommands — 引号处理,以及
exec-out与shell的区别。 - developer.android.com/training/testing/instrumented-tests/stability — 插桩测试中的屏幕截图与复现规范。
- 研究笔记
tasks/research/A2-adb-shell-commands.md— 完整的screencap/screenrecord标志表。 - 研究笔记
tasks/research/A3-adb-observability-automation.md— 失败时捕获的 CI 模式;使用exec-out的理由。 - 同级技能:
../../architecture/understanding-adb-architecture/SKILL.md— 服务端 / 守护进程 /adb shell与adb exec-out。 - 同级技能:
../../devices/connecting-to-devices/SKILL.md—adb get-state、多设备定向。 - 同级技能:
../../devices/connecting-over-wifi/SKILL.md— 用于无线捕获的adb pair。 - 同级技能:
../../apps/installing-and-managing-apps/SKILL.md— 安装 APK,以便针对其进行捕获。 - 同级技能:
../../tests/running-instrumented-tests-via-adb/SKILL.md—am instrument调用。 - 同级技能:
../../control/injecting-input-and-state/SKILL.md— 捕获前执行手势。 - 同级技能:
../../observability/extracting-logs-with-logcat/SKILL.md— 失败时捕获时配套捕获 logcat。 - 同级技能:
../../transfer/extracting-test-artifacts/SKILL.md—adb pull和 TestStorageService。 - 同级技能:
../../automation/scripting-adb-for-ci/SKILL.md— 完整的失败时捕获 CI 模式。 - 跨集合:
../../../instrumentation/runner/running-instrumented-tests-with-androidjunit4/SKILL.md— JUnit4TestWatcher机制。 - 跨集合:
../../../instrumentation/scenarios/launching-activities-with-activityscenario/SKILL.md— 捕获前,将 Activity 驱动至失败状态。 - 跨集合:
../../../fundamentals/strategies/applying-testing-strategies/SKILL.md— 何时选择失败时捕获,而非每次运行都截屏。