How Request Permissions With Jetpack Compose?
Solution 1:
as compose_version = '1.0.0-beta04'
and
implementation 'androidx.activity:activity-compose:1.3.0-alpha06'
you can do request permission as simple as this:
@ComposablefunExampleScreen() {
val launcher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
// Permission Accepted: Do something
Log.d("ExampleScreen","PERMISSION GRANTED")
} else {
// Permission Denied: Do something
Log.d("ExampleScreen","PERMISSION DENIED")
}
}
val context = LocalContext.current
Button(
onClick = {
// Check permissionwhen (PackageManager.PERMISSION_GRANTED) {
ContextCompat.checkSelfPermission(
context,
Manifest.permission.READ_EXTERNAL_STORAGE
) -> {
// Some works that require permission
Log.d("ExampleScreen","Code requires permission")
}
else -> {
// Asking for permission
launcher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
}
}
}
) {
Text(text = "Check and Request Permission")
}
}
Solution 2:
Check out Google Accompanist's Jetpack Compose Permissions.
Bear in mind that, at the time of writing, the API is still considered experimental and will require the @ExperimentalPermissionsApi
annotation when used.
Solution 3:
Google has a library called "Accompanist". It has many help libraries and one of them is the Permission Library.
Check: Library: https://github.com/google/accompanist/
Documentation: https://google.github.io/accompanist/permissions/
Example:
Setup in build.gradle file:
repositories {
mavenCentral()
}
dependencies {
implementation "com.google.accompanist:accompanist-permissions:<latest_version>"
}
Implementation in Code
@ComposableprivatefunRequiresCameraPermission(navigateToSettingsScreen: () -> Unit){
// Track if the user doesn't want to see the rationale any more.var doNotShowRationale by rememberSaveable { mutableStateOf(false) }
val cameraPermissionState = rememberPermissionState(android.Manifest.permission.CAMERA)
PermissionRequired(
permissionState = cameraPermissionState,
permissionNotGrantedContent = {
if (doNotShowRationale) {
Text("Feature not available")
} else {
Column {
Text("The camera is important for this app. Please grant the permission.")
Spacer(modifier = Modifier.height(8.dp))
Row {
Button(onClick = { cameraPermissionState.launchPermissionRequest() }) {
Text("Ok!")
}
Spacer(Modifier.width(8.dp))
Button(onClick = { doNotShowRationale = true }) {
Text("Nope")
}
}
}
}
},
permissionNotAvailableContent = {
Column {
Text(
"Camera permission denied. See this FAQ with information about why we " +
"need this permission. Please, grant us access on the Settings screen."
)
Spacer(modifier = Modifier.height(8.dp))
Button(onClick = navigateToSettingsScreen) {
Text("Open Settings")
}
}
}
) {
Text("Camera permission Granted")
}
}
Solution 4:
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:privateval permissionHandler = PermissionHandler(this)
// onCreate:
setContent {
Providers(
AmbientPermissionHandler provides permissionHandler
) {/* Composable Contnent */}
Usage:
@ComposablefunPermissionHandler(
permissions: Array<outString>,
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
classPermissionHandler(
privateval actualHandler: AppCompatActivity,
) {
suspendfunrequestPermissionsSuspend(requestCode: Int, permissions: Array<outString>): PermissionResult {
return PermissionManager.requestPermissions(actualHandler, requestCode, *permissions)
}
funrequestPermissionsWithCallback(requestCode: Int, permissions: Array<outString>, onResult: (PermissionResult) -> Unit) {
actualHandler.lifecycleScope.launch {
onResult.invoke(PermissionManager.requestPermissions(actualHandler, requestCode, *permissions))
}
}
}
If you prefer a callback the second function works also.
Solution 5:
/**
* Composable helper for permission checking
*
* onDenied contains lambda for request permission
*
* @param permission permission for request
* @param onGranted composable for [PackageManager.PERMISSION_GRANTED]
* @param onDenied composable for [PackageManager.PERMISSION_DENIED]
*/@ComposablefunComposablePermission(
permission: String,
onDenied: @Composable (requester: () -> Unit) -> Unit,
onGranted: @Composable () -> Unit
) {
val ctx = LocalContext.current
// check initial state of permission, it may be already grantedvar grantState by remember {
mutableStateOf(
ContextCompat.checkSelfPermission(
ctx,
permission
) == PackageManager.PERMISSION_GRANTED
)
}
if (grantState) {
onGranted()
} else {
val launcher: ManagedActivityResultLauncher<String, Boolean> =
rememberLauncherForActivityResult(contract = ActivityResultContracts.RequestPermission()) {
grantState = it
}
onDenied { launcher.launch(permission) }
}
}
Post a Comment for "How Request Permissions With Jetpack Compose?"