Reputation: 12352
I am writing a test class and I am trying to grant the permissions using the rule GrantPermissionRule
:
@Rule
public GrantPermissionRule permissionsRule = GrantPermissionRule.grant(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
But I get the following error at the beginning of the test execution:
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:128)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
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 android.support.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:101)
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:56)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:384)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1886)
And this is the logcat output (Errors only):
12-23 13:03:21.196 13242-13242/? E/dex2oat: Failed to create oat file: /data/dalvik-cache/arm/data@[email protected]@app_chimera@m@[email protected]@classes.dex: Permission denied
12-23 13:03:21.721 13306-13306/? E/dex2oat: Failed to create oat file: /data/dalvik-cache/arm/data@[email protected]@app_chimera@m@[email protected]@classes.dex: Permission denied
12-23 13:03:22.361 13328-13328/? E/dex2oat: Failed to create oat file: /data/dalvik-cache/arm/data@[email protected]@app_chimera@m@[email protected]@classes.dex: Permission denied
12-23 13:03:26.303 13436-13467/my.app.package E/GrantPermissionCallable: Permission: android.permission.READ_EXTERNAL_STORAGE cannot be granted!
But this seems to happen only in my Redmi 4 with Android 6.0.1. But in a Samsung Galaxy Tab S with 6.0.1 it works, as well in some emulators...
What am I missing?
Upvotes: 21
Views: 14577
Reputation: 1234
I faced same problem:
WRITE_EXTERNAL_STORAGE
POST_NOTIFICATIONS
For first issue Deni answer helped, but the second one can't be resolved the same way.
So I created a new TestRule
class based on original GrantPermissionRule:
/**
* Custom realization of [GrantPermissionRule] with ability to skip grant check.
*
* [isActualPermission] - pass here your api check. If FALSE - permission check will be skipped.
*/
@SuppressLint("RestrictedApi")
@ExperimentalTestApi
class GrantPermissionApiRule(
private val isActualPermission: Boolean,
private val permissionGranter : PermissionGranter,
vararg permissions: String
) : TestRule {
init {
val permissionSet = satisfyPermissionDependencies(*permissions)
permissionGranter.addPermissions(*permissionSet.toTypedArray())
}
@VisibleForTesting
private fun satisfyPermissionDependencies(vararg permissions: String): Set<String> {
val permissionList: MutableSet<String> = LinkedHashSet(listOf(*permissions))
/**
* Explicitly grant READ_EXTERNAL_STORAGE permission when WRITE_EXTERNAL_STORAGE was
* requested.
*/
if (permissionList.contains(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
permissionList.add(Manifest.permission.READ_EXTERNAL_STORAGE)
}
return permissionList
}
override fun apply(base: Statement, description: Description): Statement {
return RequestPermissionStatement(base, isActualPermission, permissionGranter)
}
private class RequestPermissionStatement(
private val base: Statement,
private val isActualPermission: Boolean,
private val permissionGranter: PermissionGranter
) : Statement() {
@Throws(Throwable::class)
override fun evaluate() {
if (isActualPermission) {
permissionGranter.requestPermissions()
}
base.evaluate()
}
}
companion object {
fun grant(
isActualPermission: Boolean,
vararg permissions: String
): GrantPermissionApiRule {
val granter = ServiceLoaderWrapper.loadSingleService(PermissionGranter::class.java) {
PermissionRequester()
}
return GrantPermissionApiRule(isActualPermission, granter, *permissions)
}
}
}
If function permissionGranter.requestPermissions()
not called - you will not receive exception on wrong API.
All you need to do with this realization is check current API version and pass isActualPermission
inside this TestRule
.
Like this:
/**
* If current device api >= TIRAMISU (33) - permission rule will be skipped.
*/
@get:Rule
val writeExternalGrantRule: GrantPermissionApiRule = GrantPermissionApiRule.grant(
Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
Upvotes: 1
Reputation: 1819
In my case I don't declare WRITE_EXTERNAL_STORAGE
in manifest and it was provided from some library, but in the new version of that library they set maxSdkVersion
So I just add that permission to my manifest and ignore maxSdkVersion
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:remove="android:maxSdkVersion"
tools:ignore="ScopedStorage" />
Upvotes: 1
Reputation: 490
Following code fixed my issue, my test now are passing in all supported versions of my application.
// Android 13 requires more specific permission to read media
// https://stackoverflow.com/questions/53903976
private val requiredMediaPermissions = if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
Manifest.permission.READ_MEDIA_IMAGES
} else {
Manifest.permission.READ_EXTERNAL_STORAGE
}
Upvotes: 0
Reputation: 306
I faced this error when I tried to grant the POST_NOTIFICATIONS
permission on a device with Android lower than 13. So check if the devices API level is high or low enough for the permissions you grant.
Upvotes: 4
Reputation: 11
in my case, the READ_EXTERNAL_STORAGE
permission is no longer granted since API level 32. changed to an emulator/device that has an API level of 31 or lower fixed the issue
Upvotes: 1
Reputation: 1375
For what it's worth: For me I just forgot specifying the permission in the app's manifest.
Upvotes: 1
Reputation: 2710
The above-answered option wasn't available in my OPPO device.
But there is an option called "Disable Permissions Monitoring" which does the same functionality.
To fix this issue, Turn ON the option of "Disbale Permission Functionality" under the Developer Options
Upvotes: 18
Reputation: 12352
Found the solution. I had to grant permission in the developer options menu:
Upvotes: 17