1. Overview
In this article, we will summarize the permission changes for location in Android 12 and also compare it with previous versions. If your app requests ACCESS_COARSE_LOCATION
but not ACCESS_FINE_LOCATION
, then this change doesn’t affect your app and you can skip this article.
This change permits the user to enforce that the app has access to only approximate location information.
- Precise: Provides the location accuracy that the
ACCESS_FINE_LOCATION
permission provides. - Approximate: Provides the location accuracy that the
ACCESS_COARSE_LOCATION
permission provides.
2. Behavior before Android 12
You can skip this section and proceed with the next section if you already have an idea of the existing behavior prior to Android 12.
2.1 Prior to Android 11:
If you request for the location permission ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION at runtime, then you see a system dialog asking users for their consent. Users can deny or allow the permission and don’t have any other options.
Let’s see a sample code to request runtime permission ACCESS_FINE_LOCATION.
First, let’s specify the permission in the Manifest file.
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
package com.tedblob.android12.location import android.Manifest import android.content.Context import android.content.Context.* import android.content.pm.PackageManager import android.location.LocationManager import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Toast import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat class MainActivity : AppCompatActivity() { companion object { const val PERMISSIONS_REQUEST = 101 } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) checkOrAskLocationPermission { Toast.makeText(this, "Permission already exists", Toast.LENGTH_LONG).show() } } fun checkOrAskLocationPermission(callback: () -> Unit) { val permission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) if (permission == PackageManager.PERMISSION_GRANTED) { callback.invoke() } else { // callback will be inside the activity's onRequestPermissionsResult( ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION), PERMISSIONS_REQUEST ) } } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == PERMISSIONS_REQUEST) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "Permission granted", Toast.LENGTH_LONG).show() } } } }
If you run the above code, you will see a system dialog asking to allow or deny the location permission. So once the user provides the location permission, the app will have access to the location always unless the user turns it off in the device setting.


2.2 Location permission in Android 11
Android 11 adds one-time location access and changes to background location access.
Whenever your app requests access to the foreground location, the system permissions dialog includes a new option called Only this time. So user allows the app to access the location only once and the next time app has to request again for the location. If you run the same code on an Android 11 device, then you will see the below system dialog.
Android 11 system dialog provides users with the below options
- While using the app
- Only this time
- Deny

3. Location Permissions in Android 12 & above
If your app targets Android 12 or above and uses ACCESS_FINE_LOCATION
permission, then you should also request ACCESS_COARSE_LOCATION
permission at runtime and in the Manifest file. This change allows users to restrict the app to only approximate location information, even when the app requests the ACCESS_FINE_LOCATION
runtime permission.
The user is provided with the below options
- Precise or Approximate location
- While using the app
- Only this time
- Deny
You should request for ACCESS_COARSE_LOCATION also along with ACCESS_FINE_LOCATION as in the below code. It is up to the user to decide whether he wants to allow precise or approximate location. In onRequestPermissionsResult
, you can check the permission (Approximate or precise) provided by the user.
fun checkOrAskLocationPermission(callback: () -> Unit) { val permission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) if (permission == PackageManager.PERMISSION_GRANTED) { callback.invoke() } else { // callback will be inside the activity's onRequestPermissionsResult( ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION), PERMISSIONS_REQUEST ) } } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == PERMISSIONS_REQUEST) { if (grantResults.length > 0) { boolean coarseLocation = grantResults[1] == PackageManager.PERMISSION_GRANTED; boolean fineLocation = grantResults[0] == PackageManager.PERMISSION_GRANTED; } } } }

After selecting a precise or approximate option, the user can allow the app to access the location whenever it is in the foreground or only once.
4. Conclusion
In this article, we have summarized the location changes in Android 12 and compared the experience with previous versions. You can refer to Android documentation for more information on this change.