spoon: IllegalAccessException: Unable to create output dir: /storage/emulated/0/app_spoon-screenshots

Spoon fails since dir.mkdirs() returns false…

if(!dir.exists() && !dir.mkdirs()) {
    throw new IllegalAccessException("Unable to create output dir: " + dir.getAbsolutePath());
} else {
    Chmod.chmodPlusRWX(dir);
}

I’ve given WRITE_EXTERNAL_STORAGE permissions in the AndroidManifest.xml and also tried using the GrantPermissionRule, but it keeps failing at that same step. Any help would be greatly appreciated.

Caused by: java.lang.IllegalAccessException: Unable to create output dir: /storage/emulated/0/app_spoon-screenshots at com.squareup.spoon.Spoon.createDir(Spoon.java:269) at com.squareup.spoon.Spoon.createDir(Spoon.java:266) at com.squareup.spoon.Spoon.createDir(Spoon.java:266) at com.squareup.spoon.Spoon.filesDirectory(Spoon.java:231) at com.squareup.spoon.Spoon.obtainScreenshotDirectory(Spoon.java:147) at com.squareup.spoon.Spoon.screenshot(Spoon.java:80) … 41 more

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 6
  • Comments: 15 (1 by maintainers)

Most upvoted comments

similar issue shows up when targeting api 29. I suspect the scoped storage changes are the cause.

Until this is fixed, you can use: android:requestLegacyExternalStorage="true"

Put it in the <application> tag in AndroidManifest.xml. This will only work when targeting API 29.

I hope this issue is fixed until API 30 targeting becomes a requirement.

Figured out my issue! My issue was caused by an external library merging in the maxSdkVersion with the WRITE_EXTERNAL_STORAGE permission. To get around this I removed the attribute and re-added the WRITE_EXTERNAL_STORAGE permission. This is only needed for my application manifest and not the test application manifest.

<!-- 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"/>

Then you can build, grant permissions, and run the tests:

# 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"

The pm grant commands will fail if the permissions for your app are not set up properly. Make sure those commands succeed!

Thanks for the help @tnainani! 😄

add the following to your test class:

@Rule public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE);