I'm updating an app that currently uses the ACCESS_FINE_LOCATION permission and with new API 30 requirements, will now require the ACCESS_BACKGROUND_LOCATION permission as well.
While updating the app to add this permission, I'm also trying to use the new ActivityResultLauncher callback method of requesting permissions (https://developer.android.com/training/permissions/requesting#allow-system-manage-request-code)
This seems to work well using launching single requests along these lines:
ActivityResultLauncher<String> launcher = registerForActivityResult(
new ActivityResultContracts.RequestPermission(), this::processPermissionResult);
launcher.launch(somePermission);
However, since I need both ACCESS_FINE_LOCATION and ACCESS_BACKGROUND_LOCATION it requires some extra code to keep track of the results from multiple callbacks (since each request will generate its own callback) so that I can take appropriate action if one, both, or none of the permissions were granted.
To simplify this a bit, I was looking to use the RequestMultiplePermissions method instead, which would conveniently give me one callback with all the results in a map:
ActivityResultLauncher<String[]> launcher = registerForActivityResult(
new ActivityResultContracts.RequestMultiplePermissions(), this::processPermissionResult);
launcher.launch(new String[] {
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION
});
However I found that the moment I request both ACCESS_FINE_LOCATION and ACCESS_BACKGROUND_LOCATION in the same request, I am no longer prompted with either permissions dialog and the callback comes back with false for both the permissions.
I can, however, make individual requests for these permissions using RequestMultiplePermissions by giving it an array containing a single permission, and then calling launch multiple times using the same approach as if I was using the single RequestPermission call, and that will work.
It seems that there some conflict/interaction between the ACCESS_FINE_LOCATION and ACCESS_BACKGROUND_LOCATION permissions when it comes to RequestMultiplePermissions? I was able to take out ACCESS_BACKGROUND_LOCATION and use a different permission, like WRITE_EXTERNAL_STORAGE, and I would get two separate permission dialog prompts.
Am I misunderstanding something about the ACCESS_FINE_LOCATION and ACCESS_BACKGROUND_LOCATION permissions? Should I not be requesting them simultaneously?
Related
Right now I am trying to ask the user for permission to track his/her fine location, following the docs. I was playing around with the code, and it seems that I'm able to request a single permission from the user no problem, but when trying to request multiple permissions (Fine, Course, Background location) the permission UI doesn't even show. What the heck gives? The code is nearly the same.
The code for multiple permissions is here
private fun requestPermissions() {
val requestPermissionLauncher =
registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { granted ->
Timber.tag("ASDASD").e(granted.toString())
// We can check if either the FINE or APPROX permission location has been
// granted.
}
if (TrackingUtility.hasLocationPermissions(requireContext())) {
return
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
requestPermissionLauncher.launch(
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
)
} else {
requestPermissionLauncher.launch(
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION
)
)
}
}
https://imgur.com/a/AIDCy4Q - Single permission request works
https://imgur.com/a/T8sTznX - Multiple permission doesn't show anything
I tried following the documentation to a T, but it seems that nothing wants to work unless I use a SingleRequestPermission
According to the documentation:
Even if several features in your app require location access, it's likely that only some of them require background location access. Therefore, it's recommended that your app performs incremental requests for location permissions, asking for foreground location access and then background location access. By performing incremental requests, you give users more control and transparency because they can better understand which features in your app need background location access.
And then then afterwards it highlights:
Caution: If your app targets Android 11 (API level 30) or higher, the system enforces this best practice. If you request a foreground location permission and the background location permission at the same time, the system ignores the request and doesn't grant your app either permission.
So for For Android 11 and up, if you request background location together with fine or coarse location the system will ignore the request. You need to request for background location separately (After being granted the fine or coarse location access)
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.
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).
From app I gave the required permission for my app. While my app is running, I went to system settings page and revoked the permission. The app is crashing. Will we be able to handle this?.
Android 6.0 (Marshmallow, API 23) switched from an install-time permission model to a runtime permission model. Now instead of the user granting all permissions at runtime, you the developer are responsible for requesting permissions at runtime and responding appropriately.
You should begin by reading the Requesting Permissions at Run Time documentation. So that you can properly request permissions on devices running Marshmallow.
To prevent your app from crashing, you need to call ContextCompat.checkSelfPermission() to see if you have a permission before attempting to call a method that requires a permission. However, this is only half the equation since you still need to request the permission if you don't already have it.
I'm trying to access ACCESS_FINE_LOCATION and if it cannot be found access ACCESS_COARSE_LOCATION. So I request for those 2 permission, but they give me the same dialog asking for location permission. I know those are both in the same group but Google says:
Note: Your app still needs to explicitly request every permission it needs, even if the user has already granted another permission in the same group. In addition, the grouping of permissions into groups may change in future Android releases. Your code should not rely on the assumption that particular permissions are or are not in the same group.
This means I ask for those 2 permissions within a second, which results in 2 dialog in a row. THis does not seem very user friendly to me. Is there a better way?
You do not need ACCESS_COARSE_LOCATION permission when you define ACCESS_FINE_LOCATION permission.
From Android Documentation:
Requesting User Permissions
In order to receive location updates from NETWORK_PROVIDER or
GPS_PROVIDER, you must request user permission by declaring either the
ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission,
respectively, in your Android manifest file. For example:
<manifest>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
.......
</manifest>
Without these permissions, your application will fail at runtime when
requesting location updates.
Note: If you are using both NETWORK_PROVIDER and GPS_PROVIDER, then
you need to request only the ACCESS_FINE_LOCATION permission, because
it includes permission for both providers. (Permission for
ACCESS_COARSE_LOCATION includes permission only for NETWORK_PROVIDER.)
Please look at https://developer.android.com/guide/topics/location/strategies.html
I have resolved the same problem.Try to give it runtime permission and Firstly check the manifest SDK version and if your version is greater than 6.0 or equal to 6.0 then you need to check permissions for your permission and pass permission Fine location only in request location then definitely it will work.
if you got stuck in code then you may ask for code I will update you but firstly go through these steps.
if you got success to perform your task then rate it.