You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Kotlin代码将Android Studio模拟器截图传输至主机?

在JUnit测试中实时将模拟器内截图传输到主机文件系统的实现方案

核心思路

既然模拟器会在每次测试后重启,那就不要等到测试结束后再传输文件,而是在每个测试用例生成截图后,立即通过adb pull命令将模拟器内的截图文件同步到主机文件系统。这样每个测试的截图都会被实时保存,不会因为模拟器重启丢失。

具体实现步骤

  1. 生成截图并保存到模拟器的可读写目录(比如外部存储的Pictures目录下)
  2. 在测试代码中调用adb pull命令,将模拟器内的截图文件拉取到主机的指定路径(比如代码仓库下的截图目录)
  3. 验证命令执行结果,确保传输成功

Kotlin代码示例

1. 保存Bitmap到模拟器

private fun saveBitmapToEmulator(bitmap: Bitmap, fileName: String): String {
    // 选择模拟器外部存储的可访问目录,确保测试有写入权限
    val screenshotDir = File(
        Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
        "test_screenshots"
    )
    if (!screenshotDir.exists()) screenshotDir.mkdirs()

    val screenshotFile = File(screenshotDir, fileName)
    FileOutputStream(screenshotFile).use { out ->
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)
    }
    return screenshotFile.absolutePath
}

2. 执行adb拉取文件到主机

private fun pullScreenshotToHost(emulatorFilePath: String, hostFilePath: String) {
    // 构造adb pull命令
    val adbCommand = listOf(
        "adb", "pull",
        emulatorFilePath,
        hostFilePath
    )

    // 执行命令并处理结果
    val process = ProcessBuilder(adbCommand)
        .redirectErrorStream(true)
        .start()

    process.waitFor()
    val exitCode = process.exitValue()
    if (exitCode != 0) {
        val errorMsg = process.inputStream.bufferedReader().readText()
        throw RuntimeException("拉取截图失败: $errorMsg")
    }
}

3. 在测试用例中调用

@RunWith(AndroidJUnit4::class)
class ScreenshotTest {
    @get:Rule
    val activityRule = ActivityScenarioRule(MainActivity::class.java)
    
    // 授予存储读写权限
    @get:Rule
    val grantPermissionRule = GrantPermissionRule.grant(
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.READ_EXTERNAL_STORAGE
    )

    @Test
    fun testHomeScreenCapture() {
        // 获取根视图并生成Bitmap
        activityRule.scenario.onActivity { activity ->
            val rootView = activity.window.decorView.rootView
            rootView.isDrawingCacheEnabled = true
            val bitmap = Bitmap.createBitmap(rootView.drawingCache)
            rootView.isDrawingCacheEnabled = false

            // 生成唯一文件名,避免重复
            val fileName = "test_home_screen_${System.currentTimeMillis()}.png"
            val emulatorPath = saveBitmapToEmulator(bitmap, fileName)
            
            // 主机目标路径:代码仓库根目录下的screenshots文件夹
            val hostRootPath = System.getProperty("user.dir") ?: "."
            val hostPath = "$hostRootPath/screenshots/$fileName"
            
            // 实时拉取到主机
            pullScreenshotToHost(emulatorPath, hostPath)
        }
    }
}

关键注意事项

  • adb环境配置:确保adb命令在系统PATH中,或者在代码里指定adb的绝对路径(比如/Users/xxx/Library/Android/sdk/platform-tools/adb)
  • 权限问题:必须通过GrantPermissionRule授予测试应用存储读写权限,否则无法写入模拟器外部存储
  • 测试环境:该方案仅适用于Instrumented Test(运行在设备/模拟器上的测试),不适用于本地单元测试
  • 文件名唯一性:建议用测试方法名+时间戳命名截图,避免不同测试的截图覆盖
  • 目录提前创建:主机的目标目录(比如screenshots)需要提前创建,或者在代码里判断并创建

内容的提问来源于stack exchange,提问作者Deep

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 06:02:04