Keywords: Android Runtime Permissions | Location Permission Request | FusedLocationProvider
Abstract: This article provides an in-depth exploration of runtime location permission implementation for Android 6.0 and above. Through analysis of common error cases, it details permission checking, request workflows, user interaction handling, and special requirements for background location access. The guide offers modern implementation using FusedLocationProviderClient and compares permission handling differences across Android versions.
Runtime Permission Mechanism Overview
Starting from Android 6.0 (API level 23), Google introduced the runtime permission model, requiring applications to explicitly request user authorization at runtime when accessing sensitive permissions such as location information. This mechanism significantly enhances user control over personal data while imposing higher technical requirements on developers.
Common Issue Analysis
In the original code, while the developer correctly declared permissions and added <uses-permission> tags in the manifest file, they failed to implement the runtime permission request logic. The permission checks in the code only returned TODO comments, causing the permission request flow to never execute. This is a typical reason why location services fail to work properly on Android 6.0+ devices.
Permission Declaration Configuration
Correctly declaring location permissions in AndroidManifest.xml is the foundational prerequisite:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
For Android 10 (API 29) and above, background location permission requires separate declaration and request, representing an important evolution in the permission model.
Modern Location Service Implementation
Using Google Play Services' Fused Location Provider API is recommended, as it provides more efficient and power-optimized location acquisition. First, add the dependency in build.gradle:
implementation "com.google.android.gms:play-services-location:18.0.0"
Permission Request Flow Design
A complete permission request flow should include the following key steps:
private fun checkLocationPermission() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
showPermissionExplanation()
} else {
requestLocationPermission()
}
} else {
checkBackgroundLocation()
}
}
User Interaction and Explanation
When users have previously denied permission requests, an explanatory dialog should be displayed to clarify the necessity of the permission:
private fun showPermissionExplanation() {
AlertDialog.Builder(this)
.setTitle("Location Permission Needed")
.setMessage("This app needs location permission to provide positioning services")
.setPositiveButton("OK") { _, _ ->
requestLocationPermission()
}
.create()
.show()
}
Permission Request Execution
The actual permission request is implemented through the ActivityCompat.requestPermissions method:
private fun requestLocationPermission() {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
MY_PERMISSIONS_REQUEST_LOCATION
)
}
Permission Result Handling
Override the onRequestPermissionsResult method to handle user responses:
override fun onRequestPermissionsResult(requestCode: Int,
permissions: Array<String>,
grantResults: IntArray) {
when (requestCode) {
MY_PERMISSIONS_REQUEST_LOCATION -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startLocationUpdates()
checkBackgroundLocation()
} else {
handlePermissionDenied()
}
}
}
}
Background Location Permission Handling
Android 10+ introduced independent management of background location permissions:
private fun checkBackgroundLocation() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q &&
ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestBackgroundLocationPermission()
}
}
Location Update Management
After obtaining permissions, start the location listening service:
private fun startLocationUpdates() {
val locationRequest = LocationRequest.create().apply {
interval = 30000
fastestInterval = 10000
priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY
maxWaitTime = 60000
}
fusedLocationProvider?.requestLocationUpdates(
locationRequest,
locationCallback,
Looper.getMainLooper()
)
}
Lifecycle Management
Manage location updates in onResume and onPause to optimize battery usage:
override fun onResume() {
super.onResume()
if (hasLocationPermission()) {
startLocationUpdates()
}
}
override fun onPause() {
super.onPause()
if (hasLocationPermission()) {
stopLocationUpdates()
}
}
Permission Denial Handling Strategy
When users select "Don't ask again", guide them to the system settings page:
private fun handlePermissionDenied() {
if (!ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
data = Uri.fromParts("package", packageName, null)
}
startActivity(intent)
}
}
Version Compatibility Considerations
Adopt differentiated strategies for different Android versions:
- Android 6.0-8.1: Only foreground location permission required
- Android 9.0: Introduced background location restrictions
- Android 10+: Explicit background location permission request needed
- Android 12+: Provides approximate location options
Best Practices Summary
Implementing robust location permission management should follow these principles: progressive permission requests, clear user explanations, graceful denial handling, and complete lifecycle management. By adopting Fused Location Provider and modern permission handling patterns, developers can build location service applications that comply with platform specifications while providing excellent user experience.