我正在使用Spoon 2.0.0快照使用gradle-spoon-plugin为Android UI测试设置Spoon。我的项目是使用Android Gradle插件3.0.1设置的。

通过spoonRule.screenshot(activity, "hello")截屏时,出现以下RuntimeException异常:

java.lang.RuntimeException: Unable to create output dir: /storage/emulated/0/app_spoon-screenshots
at com.squareup.spoon.SpoonRule.createDir(SpoonRule.java:167)
at com.squareup.spoon.SpoonRule.createDir(SpoonRule.java:164)
at com.squareup.spoon.SpoonRule.createDir(SpoonRule.java:164)
at com.squareup.spoon.SpoonRule.obtainDirectory(SpoonRule.java:108)
at com.squareup.spoon.SpoonRule.screenshot(SpoonRule.java:66)

如果我在Nexus 4 API 19模拟器上运行它,则一切运行正常,但在Pixel 2 API 27模拟器上却无法运行。权限已从19个更改为27个,因此这并不是完全意外的。

我已经尝试了当前可用的大多数建议,包括在androidTest目录中添加 list ,以授予读写外部存储空间(无论是否使用maxSdkVersion):
<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="tv.twitch.android.test">

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="18"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18"/>

    <uses-sdk tools:overrideLibrary="android.support.test.uiautomator.v18"/>

</manifest>

在这两种情况下,我都将这些权限合并到应用程序的AndroidManifest的最终 list 中(不确定如何检查测试应用程序的 list )。

我尝试过通过UIAutomator向应用程序和测试包授予权限:
val device = UiDevice.getInstance(getInstrumentation())
device.executeShellCommand("pm grant tv.twitch.android.test android.permission.READ_EXTERNAL_STORAGE")
device.executeShellCommand("pm grant tv.twitch.android.debug android.permission.READ_EXTERNAL_STORAGE")
device.executeShellCommand("pm grant tv.twitch.android.test android.permission.WRITE_EXTERNAL_STORAGE")
device.executeShellCommand("pm grant tv.twitch.android.debug android.permission.WRITE_EXTERNAL_STORAGE")

这会将Permission denied输出到Logcat,并导致上述相同的异常。

如果我尝试像这样利用GrantPermissionRule:
@get:Rule var runtimePermissionRule = GrantPermissionRule.grant(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)

我得到一个不同的异常(exception):
junit.framework.AssertionFailedError: Failed to grant permissions, see logcat for details
at junit.framework.Assert.fail(Assert.java:50)
at android.support.test.runner.permission.PermissionRequester.requestPermissions(PermissionRequester.java:110)
at android.support.test.rule.GrantPermissionRule$RequestPermissionStatement.evaluate(GrantPermissionRule.java:108)

GrantPermissionCallable: Permission: android.permission.WRITE_EXTERNAL_STORAGE cannot be granted!

删除Manifest.permission.WRITE_EXTERNAL_STORAGE并仅保留已读取的内容即可使我们回到原始异常:java.lang.RuntimeException: Unable to create output dir: /storage/emulated/0/app_spoon-screenshots
从Android Studio内部或使用gradle-spoon-plugin在命令行上运行不会影响以上任何内容。

查看“设置”中授予我的应用程序和测试应用程序的权限,我看到我的应用程序具有“存储”权限,但是我的测试应用程序(tv.twitch.android.test)没有请求的任何权限。

我也尝试使用Barista库:
PermissionGranter.allowPermissionsIfNeeded(Manifest.permission.WRITE_EXTERNAL_STORAGE)

他们也没有运气。

更新:

我尝试将测试应用程序的目标SDK版本设置为22,希望它会获得写权限。
<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="tv.twitch.android.test">

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="22"
        tools:overrideLibrary="android.support.test.uiautomator.v18"/>

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

</manifest>

通过Gradle(./gradlew spoon),我尝试配置gradle-spoon-plugin以请求所有权限:
spoon {
    // Grant all runtime permissions during installation on Marshmallow and above devices.
    grantAll = true
}

没有运气。我什至尝试使用Spoon库1.3.1版也无济于事。

最佳答案

我的问题是由外部库合并到具有WRITE_EXTERNAL_STORAGE权限的maxSdkVersion中引起的。为了解决这个问题,我删除了属性并重新添加了WRITE_EXTERNAL_STORAGE权限。这仅对我的应用程序 list 是必需的,而不是测试应用程序 list 。

<!-- Strip away maxSdkVersion -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
                 tools:remove="android:maxSdkVersion"/>

<!-- Add the permission with no maxSdkVersion defined -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

然后,您可以构建,授予权限并运行测试:
# Uninstall existing APKs and install our app APK and test APK
./gradlew uninstallAll installDebug installDebugAndroidTest

# List all APKs installed with adb shell 'pm list packages -f'
# Grant the app APK write and read to external storage permissions
adb shell pm grant gg.mark.debug android.permission.WRITE_EXTERNAL_STORAGE
adb shell pm grant gg.mark.debug android.permission.READ_EXTERNAL_STORAGE

export APK=build/outputs/apk/debug/debug.apk
export TEST_APK=build/outputs/apk/androidTest/debug/debug-androidTest.apk

# TEST_APK and APK are positional arguments so keep them in this order
# Disable GIF generation because it's slow
java -jar spoon-runner-2.0.0.jar --debug --disable-gif "$TEST_APK" "$APK"

如果在合并的AndroidManifest.xml 中没有正确设置应用程序的权限,则pm grant命令将失败。确保这些命令成功!

10-08 15:52