android - 如何在 API 23 或更高版本的仪器测试中写入外部存储 "permission denied"

标签 android android-testing

即使在测试用例方法中(在 ActivityInstrumentationTestCase2 的子类中),我也无法写入外部存储:

public void testWriteToStorage() throws Throwable {
    File file = new File(Environment.getExternalStorageDirectory(), "test");
    new FileOutputStream(file); // error thrown here
}

错误:

java.io.FileNotFoundException: /storage/emulated/0/test: open failed: EACCES (Permission denied)
        at libcore.io.IoBridge.open(IoBridge.java:452)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:87)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:72)
        at com.unacademy.activity.GalleryTestCase.testWriteToStorage(GalleryTestCase.java:49)
        at java.lang.reflect.Method.invoke(Native Method)
        at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)
        at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)
        at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192)
        at junit.framework.TestCase.runBare(TestCase.java:134)
        at junit.framework.TestResult$1.protect(TestResult.java:115)
        at android.support.test.internal.runner.junit3.AndroidTestResult.runProtected(AndroidTestResult.java:77)
        at junit.framework.TestResult.run(TestResult.java:118)
        at android.support.test.internal.runner.junit3.AndroidTestResult.run(AndroidTestResult.java:55)
        at junit.framework.TestCase.run(TestCase.java:124)
        at android.support.test.internal.runner.junit3.NonLeakyTestSuite$NonLeakyTest.run(NonLeakyTestSuite.java:63)
        at junit.framework.TestSuite.runTest(TestSuite.java:243)
        at junit.framework.TestSuite.run(TestSuite.java:238)
        at android.support.test.internal.runner.junit3.DelegatingTestSuite.run(DelegatingTestSuite.java:103)
        at android.support.test.internal.runner.junit3.AndroidTestSuite.run(AndroidTestSuite.java:69)
        at android.support.test.internal.runner.junit3.JUnit38ClassRunner.run(JUnit38ClassRunner.java:90)
        at org.junit.runners.Suite.runChild(Suite.java:128)
        at org.junit.runners.Suite.runChild(Suite.java:27)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
        at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
        at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
        at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:54)
        at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:240)
        at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1879)
        Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
        at libcore.io.Posix.open(Native Method)
        at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
        at libcore.io.IoBridge.open(IoBridge.java:438)
        ... 32 more

我在 list 中拥有 WRITE_EXTERNAL_STORAGE 权限,并且我知道在 API 23 之后,危险 权限需要在运行时征得用户同意。

但这不在Application上下文中;它在仪器上下文中。此外,它适用于 AWS device farm sample app .我尽我所能从那里复制了完全相同的代码,但在这里仍然失败。

注意:我只是想截取屏幕截图并将其存储在外部存储中,以便 AWS Device Farm 获取它。如果有人设法以其他方式做到这一点,请告诉我;这也会很有帮助。

最佳答案

我想到的一件事是您以 M 为目标,并且可能没有在运行时处理权限请求。

如您所说,在 M 中,WRITE_EXTERNAL_STORAGE 被视为危险权限,但是权限处理也发生了变化。在 M 之前,权限在 list 中声明,并在安装应用程序时由用户接受。在 M 中,您还必须在运行时请求权限。

请检查这个库,它将帮助您处理 M 中的权限。

https://github.com/aitorvs/allowme

我还建议您尽可能避免使用外部存储,或者最好完全避免使用存储权限。查看 Ian Lake 的精彩演讲。

https://www.youtube.com/watch?v=C28pvd2plBA

关于android - 如何在 API 23 或更高版本的仪器测试中写入外部存储 "permission denied",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34532386/

相关文章:

android - 强制应用程序类关闭

android - Espresso 测试失败

Android:如何不断更新/将值从一个 Activity 传递到另一个 Activity ?

Android 回到上一个 Activity

android - 如何使用 IntentsTestRule 和 launchFragmentInContainer 测试是否从 fragment 发送 Intent

mockito - 如何使用可模拟的AndroidJar?

android - 将 OkHttp 作为依赖项添加到支持 Retrofit 1.x 的项目是否过时了?

android - 从 Gradle 到 IntelliJ 中的标准 Android 项目

android - 相机顶部 OpenGL View 的替代方法

android - 如何使用 Mockito 测试 Presenter 中的 void 方法?