Stricter "ask once" policy¶
The default policy lets Android prompt twice and iOS once, matching system behavior. If you want one prompt, ever, on both platforms, configure a PermissionPolicy with a persistent store.
The configuration¶
val controller = rememberPermissionController(
policy = PermissionPolicy(
maxRequestsAndroid = 1,
maxRequestsIos = 1,
store = rememberDataStorePermissionStore(), // Android
),
)
On iOS, swap the store factory:
PermissionPolicy(
maxRequestsAndroid = 1,
maxRequestsIos = 1,
store = UserDefaultsPermissionStore(),
)
In a shared KMP module you can wire both up via expect/actual or with platform-specific factories.
What happens¶
After the first call to requestPermission(...):
- Aagya records the prompt in the store (
incrementRequestCount). - Subsequent calls hit the policy gate first and return
PermissionResult.PolicyExhaustedimmediately if the count has reached1. - The system prompt is never shown a second time.
The user's only path forward is Settings.
When PolicyExhausted lands, route to Settings¶
when (val result = controller.requestPermission(AppPermission.Location.Fine)) {
is PermissionResult.Granted -> ...
is PermissionResult.Denied -> if (!result.canAskAgain) controller.openAppSettings()
is PermissionResult.PolicyExhausted -> controller.openAppSettings()
is PermissionResult.Cancelled -> Unit
}
Trade-offs¶
Stricter policies are safer for the user's tolerance budget but harsher for retention. You only get one shot to convince the user. Treat the prompt as a high-signal moment:
- Surface the prompt only when the user has just tapped a feature that needs it ("Show me nearby stops"), not on a cold app launch.
- Lead with copy that explains why. The system dialog cannot do this for you on Android. iOS uses your
NSLocationWhenInUseUsageDescriptionstring.
Resetting the count¶
For testing or "reset onboarding" UX:
val store: PermissionStore = rememberDataStorePermissionStore()
LaunchedEffect(Unit) {
store.reset(AppPermission.Location.Fine)
}
Note that resetting the count does not restore the system-level prompt. iOS will still refuse to show a dialog if the user previously denied. The "Open Settings" affordance remains the canonical recovery path.