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

Espresso UI测试截图:无需修改Manifest自动授权存储权限方案

无需修改Manifest自动授予UI测试外部存储权限的方案

当然有更简洁的方案!不用折腾主App的Manifest文件,也不用手动开启权限,下面这几个方法能帮你在UI测试过程中自动搞定存储权限问题:

1. 使用Android Test Orchestrator + 权限注解

这是官方推荐的最省心的方式,Test Orchestrator会在每个测试类执行前重置应用状态,配合@GrantPermission注解可以自动授予指定权限:

步骤:

  • 首先确保你的项目依赖了AndroidX Test库,然后在app模块的build.gradle中启用Test Orchestrator:
android {
  defaultConfig {
    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    testInstrumentationRunnerArguments useTestOrchestrator: 'true'
  }
  testOptions {
    execution 'ANDROIDX_TEST_ORCHESTRATOR'
  }
}

dependencies {
  androidTestUtil 'androidx.test:orchestrator:1.4.2'
}
  • 然后在你的Espresso测试类或测试方法上添加权限注解:
import androidx.test.rule.GrantPermissionRule;
import org.junit.Rule;

public class MyUiTest {
    @Rule
    public GrantPermissionRule permissionRule = GrantPermissionRule.grant(
            android.Manifest.permission.WRITE_EXTERNAL_STORAGE
    );

    @Test
    public void testScreenshot() {
        // 执行你的测试逻辑,调用takeScreenshot()时权限已自动授予
        UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
        device.takeScreenshot(new File(getContext().getExternalFilesDir(null), "test_screenshot.png"));
    }
}

2. 在测试初始化阶段通过ADB命令授权

如果不想用Test Orchestrator,也可以在测试开始前通过ADB命令直接给测试应用授予权限,无需手动操作:

import android.content.pm.PackageManager;
import androidx.test.platform.app.InstrumentationRegistry;

@Before
public void setUp() {
    String packageName = InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName();
    String permission = android.Manifest.permission.WRITE_EXTERNAL_STORAGE;

    // 检查权限是否已授予,避免重复执行命令
    if (InstrumentationRegistry.getInstrumentation().getTargetContext().checkSelfPermission(permission)
            != PackageManager.PERMISSION_GRANTED) {
        try {
            // 执行ADB授权命令
            Runtime.getRuntime().exec(String.format(
                    "adb shell pm grant %s %s",
                    packageName,
                    permission
            ));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

注意:这种方式需要测试设备处于调试模式,且ADB连接正常,一般模拟器或开发用真机都满足条件。

3. 改用内部存储保存截图(无需权限)

其实UiDevice.takeScreenshot()支持传入任意File对象,你可以把截图保存到App的内部存储目录,这样完全不需要WRITE_EXTERNAL_STORAGE权限:

UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
// 获取App内部存储的files目录
File internalDir = InstrumentationRegistry.getInstrumentation().getTargetContext().getFilesDir();
File screenshotFile = new File(internalDir, "test_screenshot.png");
device.takeScreenshot(screenshotFile);

内部存储的文件只有你的App能访问,测试完成后可以通过Android Studio的Device File Explorer导出查看,路径一般是data/data/你的包名/files/。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:36:15