In android to do some tasks we require the user to grant related permissions. Complete process of checking and requesting permission involves 3 steps: checking permission, requesting permission and checking result. If the permission is denied, then don't need to run that task. So to simplify this, I wrote the following interface and extension function in ActivityExtensions.kt
private val permissionTaskSource = HashMap<Int, TaskCompletionSource<Boolean>>()
interface PermissionHandler {
@RequiresApi(Build.VERSION_CODES.M)
fun Activity.permissionRequest(requestCode: Int, vararg permissions: String): Task<Boolean> {
requestPermissions(permissions, requestCode)
val tcs = TaskCompletionSource<Boolean>()
permissionTaskSource[requestCode] = tcs
return tcs.task
}
fun permissionResult(requestCode: Int, grantResults: IntArray) {
permissionTaskSource[requestCode]!!.setResult(grantResults.all { it == PERMISSION_GRANTED })
permissionTaskSource.remove(requestCode)
}
}
suspend fun <T> T.requiresPermission(vararg permissions: String): Unit? where T : Activity, T : PermissionHandler {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
return Unit // If version lower than M then no need of runtime permissions.
if (permissions.all { ContextCompat.checkSelfPermission(this, it) == PERMISSION_GRANTED })
return Unit // If already all permissions granted, then no need to ask again.
val granted = permissionRequest(System.currentTimeMillis().toInt(), *permissions).await()
if (granted)
return Unit // Permission granted now
return null // Permission denied now
}
Whenever required some permissions to do a task in an activity or fragment, I can use this line:
private suspend fun someTask() {
requiresPermission(/* list of required permissions */) ?: run{ /*permission denied. handle properly*/ return }
// Inside fragment this has to be called with requiresActivity() receiver.
...
}
This whole thing is working fine.. but in every activity/fragment I have to write these 4 lines of code.
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<out String>, grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
permissionResult(requestCode, grantResults)
}
Is there some way I can move these codes also to ActivityExtensions.kt
file to make it much neater and avoid repetitive code?