API 26+: WRITE_EXTERNAL_STORAGE permission is always denied - android

I have switched my app to target API 27 and now it can't be granted WRITE_EXTERNAL_STORAGE permission -- grantResult is always -1.
My app needs this permission since it doesn't use apps private external storage space (which doesn't require WRITE_EXTERNAL_STORAGE starting from API 19).
I know that in API 26 there have been behavior changes for permissions. However this doesn't explain my problem.
I'm requesting both READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions in a standard way:
ActivityCompat.requestPermissions(activity, new String[] {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, requestCode);
(both permissions are declared via <uses-permission in manifest).
The dialog appears and I click "Allow":
However inside onRequestPermissionsResult callback I'm getting a -1(denied) for WRITE_EXTERNAL_STORAGE (and 0 (granted) for READ_EXTERNAL_STORAGE).
Shouldn't the result be 0 for both since I have requested and, presumably, granted both?
I have tried to request WRITE_EXTERNAL_STORAGE alone, but in this case the dialog doesn't appear at all.
One more detail: I have just checked the merged manifest in build/intermediates/manifests/full/debug and noticed that WRITE_EXTERNAL_STORAGE permission has attribute android:maxSdkVersion="18" (there is no such attribute in my manifest). This could be happening because my app has minApiVersion=21, but I'm not sure.

Somewhere along the line, you are picking up that android:maxSdkVersion="18" attribute. My guess is that it is coming from a library. Check the "Merged Manifest" tab in Android Studio, when you are editing your own manifest. It will have details of what is contributing the various elements and attributes.
android:maxSdkVersion has the effect of removing your <uses-permission> element on higher Android SDK versions, at least in terms of how runtime permissions work.
Since you need this permission for all versions, adding tools:remove="android:maxSdkVersion" on the <uses-permission> element should revert the android:maxSdkVersion="18" and give you what you expect.

I noticed a space in my permission in manifest, it was <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE "/> and I changed it to <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> and problem solved.

Related

Can Android normal level permissions be requested at installation time (in the manifest)?

In later versions of Android (like 8.0.0), can we still declare normal level permissions in the manifest, like INTERNET permission and expect it to be granted at installation time?
<uses-permission android:name="android.permission.INTERNET" />
or do we need to explicitly request them through the code?
If the second, do we need to ask for it on every single activity?
can we still declare normal level permissions in the manifest, like INTERNET permission and expect it to be granted at installation time?
Yes. Only dangerous ones need to be requested at runtime.
Yes, you can declare normal level permissions in the manifest. But in 6.0 and above you have to check that permission is granted or not by user at runtime.

android ContextCompat.checkSelfPermission always returns PERMISSION_GRANTED

In my android application (minSdkVersion 15), i have to create directory and write files into it. In my AppManifest i am using :
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Before creating directory or file, i am checking if permission is allowed or deny, as
boolean isAllow = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
But it is always returning true or PERMISSION_GRANTED, even when someone set deny permission from Settings -> Apps -> Permissions
Why checkSelfPermission is always returning PERMISSION_GRANTED ? Is there any way to check if permission is denied ?
To invoke permission i have used :
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
But its not showing permission Dialogue??
In the new permission model permissions with protection level dangerous are runtime permissions. For apps targeting M and above the user may not grant such permissions or revoke them at any time. For apps targeting API lower than Marshmallow(<23) these permissions are always granted as such apps do not expect permission revocations and would crash. Therefore, when the user disables a permission for a legacy app in the UI the platform disables the APIs guarded by this permission making them a no-op which is doing nothing or returning an empty result or default error.
for more information visit PermissionChecker
For those who develop with Xamarin make sure that you explicitly set the targetSDK version >= 23 in your manifest.
Don't use automatic for your targetSDK!!!
if your targetSdkVersion is minimum 23 then your problem can be solved by code as below:
int permissionCheck = PermissionChecker.checkSelfPermission(getReactApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);

How to request permission on Android Things?

I'm trying to write to a value on AT. I've already declared required permission as follow in manifest,
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
And try to request permission at run-time, AT shows windows regarding permission setup. However the switch is not clickable. Regarding AT document
Requesting Permissions at Runtime is not supported because embedded
devices aren't guaranteed to have a UI to accept the runtime dialog.
Declare permissions that you need in your app's manifest file. All
normal and dangerous permissions declared in your app's manifest are
granted at install time.
However Settings.System.canWrite() always returns false.
Are there any special methods to enable permission WRITE_SETTINGS?
Like you said, the documents say:
Declare permissions that you need in your app's manifest file. All normal and dangerous permissions declared in your app's manifest are granted at install time.
Therefore you don't see the normal Android permissions UI.
From the release notes:
Dangerous permissions requested by apps are not granted until the next device reboot. This includes new app installs and new elements in existing apps.
So try powering off and on your Android Things device
After install application with the statement on AndroidManifest.xml as follow
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
It needs to be also run Settings as follow via adb
adb shell am start -S com.android.settings/.Settings
Then click APPS>YOUR_APP, then click permission.
Now the switch is clickable. So AT not granted to permission. It needs to be granted manually.
This permission is having Protection level: signature.Which means this permission is only granted to system apps.
Please find the below screenshot for your reference :

MarshMallow Permission for gmaps

If gmaps needs this permissions:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
should I ask for each one to the user with requestPermissions ?
I checked some times and it only crash saying that the user didnt give permissions for android.permission.ACCESS_FINE_LOCATIONbut not the others, why?
should I ask for each one to the user with requestPermissions ?
First when to use requestPermission ?
requestPermission is only call after checkSelfPermission when this method doesn't return PERMISSION_GRANTED.
You can find a list of permission that android M requires during the runtime. Each of these Permissions are part of a Permission group. WRITE_EXTERNAL_PERMISSION is from android.permission-group.STORAGE and ACCESS_COARSE_LOCATION / ACCESS_FINE_LOCATION are from android.permission-group.LOCATION.
If the user allows the access to a permission -for example ACCESS_COARSE_LOCATION-, then android will automatically grant the access of this permission group -i.e. permission-group.LOCATION-. So if you later checkSelfPermission for ACCESS_FINE_LOCATION, you should receive PackageManager.PERMISSION_GRANTED.
If you app crashes, it means that you tried to call, for example LocationServices.FusedLocationApi.requestLocationUpdates before requesting from the user the permission-group Location.
Edit:
Do not forget that requestPermission is asynchronous. So do not call a method that requires a permission right after requestPermission. To call a method that requires a permission, you should override onRequestPermissionsResult that give you a list of permission and their state -granted/denied-.
You should only need to request permission for the LOCATION and STORAGE groups. I'm also pretty sure Fine location includes permission for Coarse, so you don't need to include that line in your manifest.

App requesting undeclared permission - "Test access to protected storage"

I've added to my manifest permission declaration for WRITE_EXTERNAL_STORAGE, and after some time I've noticed it asks also for Test access to protected storage when installing.
I declare in my manifest the minSdk as 14 and my targetSdk as 19.
How can I get rid of that ?
That prompt would appear to be tied to READ_EXTERNAL_STORAGE, which you are presumably being given automatically since you requested WRITE_EXTERNAL_STORAGE.
How can I get rid of that ?
Remove your WRITE_EXTERNAL_STORAGE permission. This, of course, has side effects. :-)
You have to be more specific. Setting WRITE_EXTERNAL_STORAGE permission also sets Test access to protected storage as this is a sub permission. I believe there is no way around this. Also you can see here: Development tools permission I did not set

Categories

Resources