I'm invoking the following:
ActivityCompat.requestPermissions(activity, permissions, requestCode);
I request the following permissions:
Manifest.permission.ACCESS_FINE_LOCATION
Manifest.permission.ACCESS_BACKGROUND_LOCATION
Manifest.permission.RECORD_AUDIO
Manifest.permission.MODIFY_AUDIO_SETTINGS
Now, my app requires that the user select "All the time" for the location permission. So if the user selects "Only while using this app", Android will show a subsequent screen asking them to select "All the time".
The problem is that the user sees the initial location permission request, followed by the audio request, followed by the "All the time" location request.
It seems no matter what order I make the list "permissions" parameter in the requestPermissions method, I can't make audio be requested first.
Any ideas of how to get this done? Or if Android by default requests them in a fixed order?
You need to request course or precise location FIRST, then when one or both of them is granted you can request background permission. You can't request them at the same time.
Or you can just use this library that I have been working on for a while. It is inspired by how google fit is doing it.
https://github.com/warting/permissions-ui
It is also dealing with different android SDK:s, rationales and permanent denied scenarios.
Only ask for background and audio permissions when needed. Not both at the same time just because you might need it later.
Related
As the title says, I'm currently in the process of updating my app to SDK 30 and having trouble with the ACCESS_BACKGROUND_LOCATION permission. Upon requesting the permission, the user is taken to the app location permission settings and is given 4 options:
Allow all the time
Allow only while using the app
Ask every time
Deny
All choices except "Allow all the time" do not grant the permission and return a -1 in the grantResults IntArray inside the onRequestPermissionsResult() callback function. Why? This is incredibly confusing. The naming would lead one to believe the permission would be granted and background permission requests only be made when the app is in focus. Is it possible to remove the "Allow only while using the app" option from the choices? How can I fix this?? I only see these choices confusing the user since the permission won't be granted unless they choose "Allow all the time".
Background location permission does not work like other permissions. It's a request to elevate location permission from foreground-only to foreground & background.
User has to consciously select "Allow all the time" in order to do that and grant background location permission. Otherwise that permission is considered denied.
You cannot even request background location unless foreground location is already granted - when system permission activity shows up it should already have option 2 or 3 selected.
See https://developer.android.com/training/location/permissions#request-background-location
I've set my app to target AP 29 and removed requestLegacyExternalStorage=true from manifest.
Now I'm checking if the user has this permission and if result is denied I request for permission.
My problem is that the request for permission is returning Granted without showing the prompt... I know the flow is working since I'm able to read the GPS location from picture after being granted.
I see permission status = Denied and as soon as I explicitly request this permission, it returns Granted without any user interaction.
Eveything looks OK but I'm confused about not seeing the prompt... is this expected? I saw this permission qualifies as "Dangerous" so I was expecting a prompt. I'm testing on a Android 10 device.
I'm not showing any code since the project is Xamarin and the permission logic is handled through a third party library, don't think my code will help as the platform logic to request the permission is hidden by the component.
From
Android 10: fetch the gallery via MediaStore with location information :
This requires holding the ACCESS_MEDIA_LOCATION permission. Note, this permission is not "user visible in the settings UI" (source), which means the user won't see a popup asking for permission, even though it is a runtime permission. This means you have to ask for permission during runtime (in contrast to just the manifest file) but the user won't have to consent to it. Adding this here because you might be wondering why no extra UI popups are shown.
I'm still getting my head around the logic though. I'm in favour of the user being asked for permission but I don't understand why it should be necessary to "request" it if the user doesn't actually grant permission.
I was able to reproduce the issue in a simpler app. I have posted a slightly different question with code snippets.
This is an answer by HilaryN that I believe should not have been deleted (I removed the off-topic bits).
My app must have Camera and Audio access without being requested each time (I don't want to get into details, but trust me on this one).
Is there a way to know on Android 11+ if the user clicked "Only this time" on either Camera or Audio permission?
You cannot say, when the user will disable the permissions given to your app.
If you want to have the permissions always (irrespective of when you actually gonna need it), ask the user to give the permission at the launch of your app. Other than this, you cannot stop the user to disable the permissions later.
Kind of like:
if (isPermissionGiven){
//Permission given, continue...
} else {
//Permisson not given, ask for permission...
}
By this you would be able to do your work unless you are doing any work to access the user's camera in background without the user's consent which is not Legitimate.
If your app needs a dangerous permission, you must check whether you have that permission every time you perform an operation that requires that permission.
https://developer.android.com/training/permissions/requesting
(in the case of API 23 and above)
Does it mean:
The permission dialog will popup every time that operation is about to be performed to grant permission.
Just to ContextCompat.checkSelfPermission() (programmatically) if permission is granted, if so then no permission dialog will popup.
or something else...
Why I need this answer:
I have a service that works in background multiple times a day(requesting location) NON-CONTINUOUSLY, lets say 3 times/day, does this mean that runtime permission dialog has to show up 3 times a day whenever my service is going to perform its work -or- it has to show up only the first time my service starts and then it checks programmatically (only) the remaining 2 times if permission was granted ? (same question above reformed here).
does this mean that runtime permission dialog has to show up 3 times a day whenever my service is going to perform its work
Probably not.
it has to show up only the first time my service starts and then it checks programmatically (only) the remaining 2 times if permission was granted ?
Probably not.
The quote from the documentation means that you need to call ContextCompat.checkSelfPermission() before you try performing an operation that needs a runtime permission (dangerous permissions). This does not display any UI. It merely lets you know whether or not you hold the permission.
If you do not hold the permission, you will to request the permission from the user before you will be able to do whatever it is that you are trying to do. That needs to be performed from an activity or fragment, using requestPermissions().
In your case, before you schedule the background work (WorkManager, JobScheduler, etc.), use requestPermissions(), and only schedule that work if the user grants you your desired permission(s).
However, it is possible that the user will revoke the granted permissions. That is why your background work will need to call checkSelfPermission(). If that indicates that you do not hold the permission, you will need to raise a Notification that leads the user to your UI, where you can once again requestPermissions().
It means you need to call checkSelfPermission each time, and make sure the user didn't remove your permission (because if they did the action will fail, either with an error return or an exception). However if that returns false, the only way to get permission is to show the dialog. Or you can just not do whatever you were planning to.
The Android M Preview docs shows us how to check and request permissions with the new permissions model. In the chart below that it shows us a group of Permission Groups and their associated Permissions.
When I try to to checkSelfPermission with a permission_group (ie Manifest.permission_group.CAMERA) on first start, predictably I get PackageManager.PERMISSION_DENIED.
Then try to requestPermissions for that same permission_group and i don't get any type of dialog to pop up. 'onRequestPermissionsResult' returns immediately with -1.
When i try the same sequence with Manifest.permission.Camera - things seem to work as normal. But for a simple app that I'm making, I need to record video with audio, and requesting the two separate permissions, CAMERA and MICROPHONE (aka RECORD_AUDIO) seems like poor design.
The question: Is checkSelfPermission and requestPermission supposed to work with Manifest.permission.* and Manifest.permission_group.* but there's a bug that I should file since it won't show request? Or was this intentional design?
*Note - I understand that I can create a requestPermissions(String[], int) string array with multiple permissions in it myself, but id still have plenty of if statements to check the combinations of permissions i need and to request them as a group, when i should only need to request a permission_group
When I try to to checkSelfPermission with a permission_group (ie Manifest.permission_group.CAMERA) on first start, predictably I get PackageManager.PERMISSION_DENIED.
That is because checkSelfPermission() checks permissions, not permission groups.
Then try to requestPermissions for that same permission_group and i don't get any type of dialog to pop up. 'onRequestPermissionsResult' returns immediately with -1.
That is because requestPermissions() works with permissions, not permission groups.
Is checkSelfPermission and requestPermission supposed to work with Manifest.permission.*
Yes.
and Manifest.permission_group.*
No.
Or was this intentional design?
Presumably, yes. At least on the checkSelfPermission(), it layers atop other pre-existing methods that date back to API Level 1 and work on permissions, not permission groups.
when i should only need to request a permission_group
You are making assumptions about the future of Android that may not be accurate. Right now, pre-M, permission groups are not especially important, and permissions are what matter. In M, permission groups climb in importance, as that is what M uses in its presentation to end users regarding what the user can control. However, versions of Android after that might offer finer granularity on this, whether to individual users or to enterprises via policies, and that would likely go back to permissions.
The API suggests that Google is leaving the door open for those sorts of moves. In effect, the permission group stuff is a UX decision, more so than a technical one.