Skip to content

Location Permissions

Geofencing needs location permissions — including background location, since geofence transitions happen while your app is closed. The SDK already declares these in its manifest:

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

Your job is requesting them at runtime, in the right order.

Android enforces a two-step flow:

  1. Request foreground location (ACCESS_FINE_LOCATION + ACCESS_COARSE_LOCATION) and wait for the grant.
  2. Only then request background location (ACCESS_BACKGROUND_LOCATION) — Android takes the user to the app’s settings page (“Allow all the time”) instead of showing a dialog.

Show a priming screen before each step explaining why you need it — this measurably improves opt-in rates and Google may require it during review (Google Play Approval).

class LocationPermissionFragment : Fragment() {
private val requestForegroundLocation =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { results ->
val granted = results[Manifest.permission.ACCESS_FINE_LOCATION] == true ||
results[Manifest.permission.ACCESS_COARSE_LOCATION] == true
if (granted) {
// Step 2 becomes available — show your background-location priming screen
showBackgroundPrimingScreen()
}
}
private val requestBackgroundLocation =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
if (granted) { /* geofencing fully enabled */ }
}
// Step 1 — from your foreground priming screen:
private fun requestForeground() {
requestForegroundLocation.launch(
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
),
)
}
// Step 2 — from your background priming screen, only after step 1 is granted:
private fun requestBackground() {
requestBackgroundLocation.launch(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
}
}

Users can grant only approximate location. Request FINE and COARSE together (as above) and handle the case where only COARSE is granted — geofencing works with reduced accuracy.

  • Foreground priming screen → request FINE + COARSE
  • Background priming screen (explain “Allow all the time”) → request BACKGROUND
  • Handle “approximate only” grants gracefully
  • Prepare your Google Play background-location declaration