问题
How should be implemented requesting permission from Jetpack Compose View? I'm trying implement application accessing Camera with Jetpack Compose. I tried example from How to get Current state or context in Jetpack Compose Unfortunately example is no longer working with dev06.
fun hasPermissions(context: Context) = PERMISSIONS_REQUIRED.all {
ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
}
}
}
回答1:
A little late but this might help as I had the problem today:
With ContextAmbient.current
it is not guaranteed that you have an activity or fragment thus I created my own ambient for handling permissions.
val AmbientPermissionHandler: ProvidableAmbient<PermissionHandler> =
ambientOf { throw IllegalStateException("permission handler is not initialized") }
// Activity:
private val permissionHandler = PermissionHandler(this)
// onCreate:
setContent {
Providers(
AmbientPermissionHandler provides permissionHandler
) {/* Composable Contnent */}
Usage:
@Composable
fun PermissionHandler(
permissions: Array<out String>,
requestCode: Int,
granted: @Composable() () -> Unit,
denied: @Composable() () -> Unit,
deniedPermanently: (@Composable() () -> Unit)? = null,
rational: (@Composable() () -> Unit)? = null,
awaitResult: (@Composable() () -> Unit)? = null,
) {
val permissionHandler = AmbientPermissionHandler.current
val (permissionResult, setPermissionResult) = remember(permissions) { mutableStateOf<PermissionResult?>(null) }
LaunchedEffect(Unit) {
setPermissionResult(permissionHandler.requestPermissionsSuspend(requestCode, permissions))
}
when (permissionResult) {
is PermissionResult.PermissionGranted -> granted()
is PermissionResult.PermissionDenied -> denied()
is PermissionResult.PermissionDeniedPermanently -> deniedPermanently?.invoke()
is PermissionResult.ShowRational -> rational?.invoke()
null -> awaitResult?.invoke()
}
}
Implementation of PermissionHandler with dependency https://github.com/sagar-viradiya/eazypermissions
class PermissionHandler(
private val actualHandler: AppCompatActivity,
) {
suspend fun requestPermissionsSuspend(requestCode: Int, permissions: Array<out String>): PermissionResult {
return PermissionManager.requestPermissions(actualHandler, requestCode, *permissions)
}
fun requestPermissionsWithCallback(requestCode: Int, permissions: Array<out String>, onResult: (PermissionResult) -> Unit) {
actualHandler.lifecycleScope.launch {
onResult.invoke(PermissionManager.requestPermissions(actualHandler, requestCode, *permissions))
}
}
}
If you prefer a callback the second function works also.
回答2:
private const val PERMISSIONS_REQUEST_CODE = 10
private val PERMISSIONS_REQUIRED = arrayOf(Manifest.permission.CAMERA)
@Composable
fun PermissionButton() {
val context = ContextAmbient.current
Button(onClick = {
if (!hasPermissions(context)) {
requestPermissions(
context as Activity,
PERMISSIONS_REQUIRED,
PERMISSIONS_REQUEST_CODE
)
}
}
) {}
}
fun hasPermissions(context: Context) = PERMISSIONS_REQUIRED.all {
ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
}
来源:https://stackoverflow.com/questions/60608101/how-request-permissions-with-jetpack-compose