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.
The required order (Android 11+, API 30+)
Android enforces a two-step flow:
- Request foreground location (
ACCESS_FINE_LOCATION+ACCESS_COARSE_LOCATION) and wait for the grant. - 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).
Implementation
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)
}
}
Android 12+ note (API 31+)
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.
Checklist
- 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

