Skip to content

Instantly share code, notes, and snippets.

@hichamboushaba
Last active November 16, 2021 21:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hichamboushaba/440939bf85300b1fe634580d19bf018d to your computer and use it in GitHub Desktop.
Save hichamboushaba/440939bf85300b1fe634580d19bf018d to your computer and use it in GitHub Desktop.
class PermissionManager(
private val context: Context,
private val activityProvider: ActivityProvider
) {
...
suspend fun requestPermissions(vararg permissions: String): Map<String, PermissionStatus> {
var isLaunched = false
// Restore or generate a new key
val key = activityProvider.currentActivity?.let { activity ->
val savedBundle = activity.savedStateRegistry.consumeRestoredStateForKey(SAVED_STATE_REGISTRY_KEY)
if (savedBundle?.getString(PENDING_PERMISSIONS_KEY) == permissions.joinToString(",")) {
isLaunched = true
generateKey(savedBundle.getInt(LAST_INCREMENT_KEY))
} else {
generateKey(keyIncrement.getAndIncrement())
}
} ?: return permissions.associateWith {
if (hasPermission(it)) PermissionGranted else PermissionDenied(shouldShowRationale = false)
}
// Keep track of the pending permissions
pendingPermission = permissions.joinToString(",")
return activityProvider.activityFlow
.mapLatest { currentActivity ->
if (!isLaunched) {
// If it's the first call, then attach our SavedStateProvider
prepareSavedData(currentActivity)
}
var launcher: ActivityResultLauncher<Array<out String>>? = null
try {
suspendCancellableCoroutine<Map<String, PermissionStatus>> { continuation ->
launcher = currentActivity.activityResultRegistry.register(
key,
ActivityResultContracts.RequestMultiplePermissions()
) { result ->
// Clear the saved data
pendingPermission = null
clearSavedStateData(currentActivity)
continuation.resume(permissions.associateWith {
if (result[it] == true) {
PermissionGranted
} else {
val shouldShowRationale = currentActivity.shouldShowRequestPermissionRationale(it)
PermissionDenied(shouldShowRationale)
}
})
}
if (!isLaunched) {
launcher!!.launch(permissions)
isLaunched = true
}
}
} finally {
launcher?.unregister()
}
}
.first()
}
private fun prepareSavedData(currentActivity: ComponentActivity) {
currentActivity.savedStateRegistry.registerSavedStateProvider(
SAVED_STATE_REGISTRY_KEY
) {
bundleOf(
PENDING_PERMISSIONS_KEY to pendingPermission,
LAST_INCREMENT_KEY to keyIncrement.get() - 1
)
}
}
private fun clearSavedStateData(currentActivity: ComponentActivity) {
currentActivity.savedStateRegistry.unregisterSavedStateProvider(
SAVED_STATE_REGISTRY_KEY
)
// Delete the data by consuming it
currentActivity.savedStateRegistry.consumeRestoredStateForKey(
SAVED_STATE_REGISTRY_KEY
)
}
private fun generateKey(increment: Int) = "permission_$increment"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment