moko-permissions icon indicating copy to clipboard operation
moko-permissions copied to clipboard

Permission requests synchronization

Open xpathexception opened this issue 3 years ago • 0 comments

If couple of permission requests run in different scopes in parallel, at least one request will fail with an exception.

W/Activity: Can request only one set of permissions at a time
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: dev.icerock.moko.samples.permissions.debug, PID: 27897
    java.util.NoSuchElementException: Array is empty.
        at kotlin.collections.ArraysKt___ArraysKt.first(_Arrays.kt:1013)
        at dev.icerock.moko.permissions.ResolverFragment.onRequestPermissionsResult(ResolverFragment.kt:54)
        at androidx.fragment.app.FragmentActivity.onRequestPermissionsResult(FragmentActivity.java:769)
        ...

Simpliest example of such case may look like that:

SampleViewModel.kt

private fun requestPermission() {
    viewModelScope.launch {
        try {
            // Calls suspend function in a coroutine to request some permission.
            permissionsController.providePermission(Permission.RECORD_AUDIO)
            // If there are no exceptions, permission has been granted successfully.
            eventsDispatcher.dispatchEvent { onSuccess() }
        } catch (deniedAlwaysException: DeniedAlwaysException) {
            eventsDispatcher.dispatchEvent { onDeniedAlways(deniedAlwaysException) }
        } catch (deniedException: DeniedException) {
            eventsDispatcher.dispatchEvent { onDenied(deniedException) }
        }
    }
    viewModelScope.launch {
        try {
            // Calls suspend function in a coroutine to request some permission.
            permissionsController.providePermission(Permission.CAMERA)
            // If there are no exceptions, permission has been granted successfully.
            eventsDispatcher.dispatchEvent { onSuccess() }
        } catch (deniedAlwaysException: DeniedAlwaysException) {
            eventsDispatcher.dispatchEvent { onDeniedAlways(deniedAlwaysException) }
        } catch (deniedException: DeniedException) {
            eventsDispatcher.dispatchEvent { onDenied(deniedException) }
        }
    }
}

In real-world cases this may be caused, for example, by requesting couple of different permissions in separate application modules. Moreover, LocationTracker from moko-geo is affected too.

Although problem can be solved by providing synchronization manually, it wold be nice to implement this in library. I think the best possible option is synchronize request across all PermissionController instances, but it will be great to have such thing for at least one instance.

xpathexception avatar Apr 17 '21 14:04 xpathexception