I am setting up Spoon for Android UI Testing using the gradle-spoon-plugin using the Spoon 2.0.0 snapshot. My project is set up using Android Gradle plug-in 3.0.1.
When taking screenshots via spoonRule.screenshot(activity, "hello")
, I get this 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)
Things work fine if I run it on a Nexus 4 API 19 emulator but it does not work on a Pixel 2 API 27 emulator. Permissions have changed a bunch from 19 to 27 so this is not totally unexpected.
I've tried most of the advice currently available including adding a manifest in my androidTest
directory that grants the read and write external storage (with and without the 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>
I see these permissions being merged into my final manifest of my app's AndroidManifest (unsure how to check the test app's manifest) in both cases.
I've tried granting permissions via UIAutomator to both the app and test package:
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")
This outputs a Permission denied
to Logcat and results in the same exception above.
If I try leveraging GrantPermissionRule
like:
@get:Rule var runtimePermissionRule = GrantPermissionRule.grant(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
I get a different 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!
Removing Manifest.permission.WRITE_EXTERNAL_STORAGE
and leaving just the read one gets us back to the original exception: java.lang.RuntimeException: Unable to create output dir: /storage/emulated/0/app_spoon-screenshots
Running from within Android Studio or on the command-line using gradle-spoon-plugin
doesn't affect any of the above.
Looking at the permissions my app and test app are granted in Settings, I see my app has Storage permission but my test app (tv.twitch.android.test) does not have any permissions requested.
I also tried using the Barista library:
PermissionGranter.allowPermissionsIfNeeded(Manifest.permission.WRITE_EXTERNAL_STORAGE)
With no luck their either.
Updates:
I tried making my test app target SDK version 22 in hopes it would get write permissions.
<?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>
Via Gradle (./gradlew spoon
) I tried configuring the gradle-spoon-plugin to request all permissions:
spoon {
// Grant all runtime permissions during installation on Marshmallow and above devices.
grantAll = true
}
With no luck. And I even tried using Spoon library version 1.3.1 to no avail as well.