Android 12 doesn't return location with approximate location permission

4.1k Views Asked by At

On Pixel 4a with Android 12 (SPB5.210812.002), when approximate location permission is given by the user, no location is returned from FusedLocationProviderClient. When I change permission to exact location permission, then I'm able to get location.

I have both coarse and fine location permissions in Manifest, as well as requesting both at runtime.

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Once either permission is given, I'm requesting lastKnownLocation, as well as requesting for location updates. With precise location permission, Im getting location shortly, but not when user gives approximate location permission.

For location request priority, I've tried both LocationRequest.PRIORITY_HIGH_ACCURACY and LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY.

On Android 9 everything works as expected, so I guess this is related to precise/approximate location permission, introduced in Android 12.

Here is part of my code:

private val fusedLocationClient by lazy { 
        LocationServices.getFusedLocationProviderClient(requireContext()) 
    }
    private val cts: CancellationTokenSource = CancellationTokenSource()

    private val locationRequest = LocationRequest()
        .setPriority(LOCATION_REQUEST_PRIORITY)
        .setFastestInterval(MIN_TIME_BETWEEN_STAMPS_IN_MILLIS) // 1000
        .setInterval(TIME_BETWEEN_STAMPS_IN_MILLIS) // 10000

    private val locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult?) {
            locationResult?.locations?.firstOrNull()?.let {
                userLocation = it
                onUserLocationUpdated()
            }
        }
    }


    private fun onLocationPermissionGranted() {
        if (!requireContext().isLocationEnabled()) {
            requireContext().showLocationPermissionRequiredDialog {
                onBackPressed()
            }
        } else {
            try {
                getCurrentLocation()
                fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
            } catch (t: Throwable) {
                onBackPressed()
            }
        }
    }

 
    private fun getCurrentLocation() {
        fusedLocationClient.getCurrentLocation(
            LOCATION_REQUEST_PRIORITY,
            cts.token
        ).addOnSuccessListener { location: Location? ->
            if (location != null) {
                userLocation = location
                onUserLocationUpdated()
            }
        }
    }
1

There are 1 best solutions below

1
On

On Android 12 (API level 31) or higher, users can request that your app retrieve only approximate location information, even when your app requests the ACCESS_FINE_LOCATION runtime permission.

To handle this potential user behavior, don't request the ACCESS_FINE_LOCATION permission by itself. Instead, request both the ACCESS_FINE_LOCATION permission and the ACCESS_COARSE_LOCATION permission in a single runtime request.

If you try to request only ACCESS_FINE_LOCATION, the system ignores the request on some releases of Android 12. If your app targets Android 12 or higher, the system logs the following error message in Logcat:

ACCESS_FINE_LOCATION must be requested with ACCESS_COARSE_LOCATION.

Here you can find it in the official Android Documentation:

https://developer.android.com/training/location/permissions