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" }