在AndroidTest中写入外部存储

Raf*_*l T 5 java testing android android-permissions android-external-storage

我想AndroidTest为某个应用编写一个涉及写入外部存储的应用,但是以某种方式我无法使其正常工作。(在Pixel2,Lg G6,Huawai P8等多种设备上进行测试)

因此,我简化了所有操作,只是为了测试是否可以完全写入外部存储。我尝试了GrantPermissionRule并在Granter上进行了编写,但没有成功。

我可能最终做了太多不必要的事情,所以这是我所做的:

  1. 在没有活动的情况下创建新项目 AndroidStudio
  2. 向清单添加了权限
  3. 加入AndroidManifestuses-permission标签
  4. 自己写 PermissionRequester
  5. 编写测试以尝试在/ sdcard / Download中添加文件夹并将其删除

以下是上面编号列表引用的摘录

2。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.company.android.testpermissions">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="com.company.TestPermissions"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme" />
</manifest>
Run Code Online (Sandbox Code Playgroud)

3。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.company.android.testpermissions.test">
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

</manifest>
Run Code Online (Sandbox Code Playgroud)

也尝试过

<manifest package="com.company.android.testpermissions">...
Run Code Online (Sandbox Code Playgroud)

省略“测试”后缀

4。

public class MyPermissionRequester {

    public static final String TAG = MyPermissionRequester.class.getSimpleName();

    public static void request(String... permissions) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            UiAutomation auto = InstrumentationRegistry.getInstrumentation().getUiAutomation();
            String cmd = "pm grant " + InstrumentationRegistry.getTargetContext().getPackageName() + " %1$s";
            String cmdTest = "pm grant " + InstrumentationRegistry.getContext().getPackageName() + " %1$s";
            String currCmd;
            for (String perm : permissions) {
                execute(String.format(cmd, perm), auto);
                execute(String.format(cmdTest, perm), auto);
            }
        }
        GrantPermissionRule.grant(permissions);
    }

    private static void execute(String currCmd, UiAutomation auto){
        Log.d(TAG, "exec cmd: " + currCmd);
        auto.executeShellCommand(currCmd);
    }
}
Run Code Online (Sandbox Code Playgroud)

5,

@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
    @Test
    public void sdcardTest(){

        //check sdcard availability 
        Assert.assertEquals("Media is not mounted!", Environment.getExternalStorageState(), Environment.MEDIA_MOUNTED);
       //get and check Permissions
MyPermissionRequester.request(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        int grantResult = ActivityCompat.checkSelfPermission(InstrumentationRegistry.getTargetContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
        Assert.assertEquals(PackageManager.PERMISSION_GRANTED, grantResult);
        grantResult = ActivityCompat.checkSelfPermission(InstrumentationRegistry.getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
        Assert.assertEquals(PackageManager.PERMISSION_GRANTED, grantResult);

        //finally try to create folder
        File f = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "CompanyTest");
        if (!f.exists()){
            boolean mkdir = f.mkdirs();
            Assert.assertTrue("Folder '"+f.getAbsolutePath() + "' not Present!", mkdir);
        }
        boolean delete = f.delete();
        Assert.assertTrue("Folder '"+f.getAbsolutePath() + "' is Present!", delete);
    }
}
Run Code Online (Sandbox Code Playgroud)

测试的结果是:

junit.framework.AssertionFailedError:文件夹'/ storage / emulated / 0 / Download / CompanyTest'不存在!在

junit.framework.Assert.fail(Assert.java:50)在

junit.framework.Assert.assertTrue(Assert.java:20)在

com.company.android.testpermissions.ExampleInstrumentedTest.sdcardTest(ExampleInstrumentedTest.java:69)

在...的java.lang.reflect.Method.invoke(本机方法)处(省略了其余部分,来自TestRunner)

我在这里想念什么或做错了什么?

Raf*_*l T 5

在尝试了很多不起作用的东西之后,我终于找到了解决方案:

谷歌声称

if your application already requests write access, it will automatically get read access as well.
Run Code Online (Sandbox Code Playgroud)

https://developer.android.com/about/versions/android-4.1.html#Permissions

或在 WriteExternalStorage 文档中:

Note: If your app uses the WRITE_EXTERNAL_STORAGE permission, then it implicitly has permission to read the external storage as well.
Run Code Online (Sandbox Code Playgroud)

https://developer.android.com/training/data-storage/files.html#WriteExternalStorage

或在清单权限中:

Any app that declares the WRITE_EXTERNAL_STORAGE permission is implicitly granted this permission.
Run Code Online (Sandbox Code Playgroud)

https://developer.android.com/reference/android/Manifest.permission.html#READ_EXTERNAL_STORAGE

除了它没有!

如果我明确添加READ_EXTERNAL_STORAGE到我的清单以及在运行时请求它,它就像我习惯的那样工作。

所以 3. 必须添加

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.company.android.testpermissions.test">
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
</manifest>
Run Code Online (Sandbox Code Playgroud)

测试应该是这样的:

@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
    @Test
    public void sdcardTest(){

        //check sdcard availability 
        Assert.assertEquals("Media is not mounted!", Environment.getExternalStorageState(), Environment.MEDIA_MOUNTED);
       //get and check Permissions
MyPermissionRequester.request(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE);
        int grantResult = ActivityCompat.checkSelfPermission(InstrumentationRegistry.getTargetContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
        Assert.assertEquals(PackageManager.PERMISSION_GRANTED, grantResult);
        grantResult = ActivityCompat.checkSelfPermission(InstrumentationRegistry.getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
        Assert.assertEquals(PackageManager.PERMISSION_GRANTED, grantResult);

        //finally try to create folder
        File f = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "CompanyTest");
        if (!f.exists()){
            boolean mkdir = f.mkdirs();
            Assert.assertTrue("Folder '"+f.getAbsolutePath() + "' not Present!", mkdir);
        }
        boolean delete = f.delete();
        Assert.assertTrue("Folder '"+f.getAbsolutePath() + "' is Present!", delete);
    }
}
Run Code Online (Sandbox Code Playgroud)

一切正常。

剩下的唯一问题是是否/为什么这是自 Android 8.1 以来的预期行为