Is there a way to choose which order the user is prompted for permissions in Android Marshmellow's new permissions dialog?
When the user launches the camera in my app, I'm prompting for:
Manifest.permission.CAMERA
Manifest.permission.WRITE_EXTERNAL_STORAGE
Manifest.permission.RECORD_AUDIO
Because it makes the most sense (e.g. open camera, app requests camera permissions), I want the permissions to be requested in that order as well. But they aren't requested in that way - the Permissions dialog seems to just ignore the order I have in the String array.
Code below, using the EasyPermissions library, but the same thing happens without the EasyPermissions library.
ArrayList<String> permissionsToRequest = new ArrayList<String>();
permissionsToRequest.add(Manifest.permission.CAMERA);
permissionsToRequest.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
permissionsToRequest.add(Manifest.permission.RECORD_AUDIO);
EasyPermissions.requestPermissions(
this,
"To take pictures & record video, we need access to your device's camera & storage. Allow?",
R.string.acceptPermission, R.string.declinePermission,
RequestConstants.REQUEST_CAMERA_PERMISSIONS,
permissionsToRequest.toArray(new String[0])
);
Regardless of how I order the permissions in permissionsToRequest, the user is prompted in the same order (Audio, Storage, Camera), which in my opinion is the least intuitive order. Any way to fix this?
Although there isn't a clear way to define the order of permission, I found that it is somehow related to the order defined in the AndroidManifest.xml and in the array passed in Activity.requestPermissions(String[] permissions, String requestCode)
In a device, the order of the permission array was the order it showed in the screen. In a different device, the order defined in the manifest prevailed.
Hope this helps.
Related
I am working on a files app and after targeting to API-30, I need permissions for not just media store permission (WRITE_EXTERNAL_STORAGE), but also need to be an external storage manager (MANAGE_EXTERNAL_STORAGE). In order to do so, I have to show 2 different system dialogs to the customer. The first one is the media store permissions dialog:
/* Code to show this permission */
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.MANAGE_EXTERNAL_STORAGE},
1);
And then I have to show the following one to get external storage manager permissions:
/* Code to show this permission */
final Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
final Uri uri = Uri.fromParts("package", activity.getApplicationContext().getPackageName(), null);
intent.setData(uri);
activity.startActivity(intent);
Is there something in the android system that shows user a dialog that bundles all the storage permissions together, or any android system flow that can be launched that guides user throughout both permission together? Having two different flows seems like a terrible amount of redundant logic that needs to be owned by apps. I was not able to find something like that, so asking here if I missed anything.
Is there something in the android system that shows user a dialog that bundles all the storage permissions together
Not in terms of MANAGE_EXTERNAL_STORAGE, as that is not a runtime permission that you handle via requestPermissions(). READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE can be requested together using requestPermissions().
or any android system flow that can be launched that guides user throughout both permission together?
No, sorry.
Note that I have not tried holding MANAGE_EXTERNAL_STORAGE without WRITE_EXTERNAL_STORAGE. Perhaps WRITE_EXTERNAL_STORAGE is not needed if you hold MANAGE_EXTERNAL_STORAGE. The documentation suggests that this might be the case.
Having two different flows seems like a terrible amount of redundant logic that needs to be owned by apps
Very few apps should be asking the user to grant MANAGE_EXTERNAL_STORAGE. And apparently Google really wants users to think through whether they should be granting that permission to your app.
I want to read contact like this
Should I ask permission for this?
val intent = Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI)
startActivityForResult(intent, RESULT_PICK_CONTACT)
Android platform is moving towards creating a more user-safe experience. There are new safety features coming out that gives the user an option to only enable certain features for the session that the user is during the app's usage. It makes sense to be explicit about these permissions with the end user so they feel more clear about how they will expose themselves.
NOTE: This question IS NOT for customizing the text in a permission request dialog (shouldShowRequestPermissionRationale() mentioned in OP).
Are the message strings displayed when calling requestPermissions() standard, or vendor specific? Are these strings accessible for reuse?
In OnRequestPermissionsResult(), if the user denies Android.Manifest.Permission.WriteExternalStorage, I would like to show a dialog saying "<app-name> requires " + "Allow <app-name> to access photos, media, and files on your device" (or something to that effect), instead of writing a different message like "SD-Card write access required to continue." (which is something more suited shouldShowRequestPermissionRationale()).
I'd prefer the messages match to avoid confusion, so that when the user is re-prompted they know exactly what permissions are required to allow.
Here is an example of my usage of OnRequestPermissionsResult
Are the message strings displayed when calling requestPermissions() standard, or vendor specific?
Anything can be changed by device manufacturers. Even for the subset of devices that are part of the Google Play ecosystem, message text like this could be changed.
Are these strings accessible for reuse?
They appear to come from the description of the <permission-group> to which your permission belongs. Presumably you can use PackageManager and PermissionGroupInfo to get the values at runtime.
update(samusarin):
PermissionGroupInfo pgi = this.PackageManager.GetPermissionGroupInfo(Android.Manifest.Permission_group.Storage, PackageInfoFlags.Permissions);
string desc = pgi.LoadDescription(PackageManager);
I am working with Android API 25 and need to make permissions requests in the app.
There are a ton of code samples on how to make a request as well as how to show the rationale. This link here shows a simple methodology as do these: Android M Request Multiple permission at a single time , Android M request permission non activity
The problem I am having is I am requesting multiple permissions at once (Location, Write storage access, and Contacts) and the ActivityCompatApi23.shouldShowRequestPermissionRationale source code only takes in a String for a single permission and not an array for multiple permissions. (source: android.support.v4.app.ActivityCompat)
So in my code, I can do this:
ActivityCompat.requestPermissions(activity, permissionsStringArray, 123);
And try to request multiple at once, but I can't then show the explanation for the ones needed if they return true from:
ActivityCompat.shouldShowRequestPermissionRationale(activity,
currentPerm.getPermissionManifestName()
Does anyone have any recommendations on how I can show a dialog that includes multiple rationales in it as opposed to one at a time?
I recommend this open source.
https://github.com/ParkSangGwon/TedPermission
You can use simply. for example
private void CheckPermission() {
new TedPermission(this)
.setPermissionListener(permissionlistener)
.setDeniedMessage(getString(R.string.str_permission1))
.setPermissions(Manifest.permission.CAMERA, android.Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
.check();
}
I've a problem with content provider and custom permissions.
Let's suppose that App A have a content provider containing wonderful informations. These informations are a little bit intrusive, that's why it's better to have a permission to read them.
Let's suppose that App B is a 3rd party application and want to access to the content provider of A.
Let's suppose that the permission to read into the content provider is "com.custom.a.readpermission".
In A manifest, there is :
<permission android:name="com.custom.a.readpermission"/>
<provider android:name="com.a.provider.MyProvider"
android:exported="true"
android:authorities="com.a.provider.MyProvider"
android:readPermission="com.custom.a.readpermission"/>
In B manifest, there is :
<uses-permission android:name="com.custom.a.readpermission"/>
So, now, if I install A; after, I install B. B can access to the data.
But, if I install B before A, I get :
java.lang.SecurityException: Permission Denial: opening provider com.a.provider.MyProvider requires com.custom.a.readpermission
So, how to manage a custom permission in that case ?
So, how to manage a custom permission in that case ?
Your primary options are:
Use a built-in system permission, as opposed to a custom one. This is a good idea in general, if the nature of the sensitive data is similar to other data already defended by built-in permissions.
Catch this exception and tell the user that they need to uninstall A and B and install them in the proper order.
If A and B are both by the same author, use a protectionLevel signature permission and have the same <permission> element in both A and B. Then the installation order will not matter, and the user won't be bothered with any prompts to agree to this permission.
However, bear in mind that prior to Android 5.0, the fact that option #3 works means that any app installed before A could do the same thing as B does, except downgrading the protectionLevel from signature to normal. This is a known vulnerability. Android 5.0 requires that custom permissions are defined on a "first one in wins" basis, and the second and subsequent apps trying to define the same <permission> have to be signed by the same signing key as the app that actually did define it.
In truth, permissions are great for pre-installed apps and the OS itself, but defining custom permissions at the app level is... less than great.