Skip to content Skip to sidebar Skip to footer

How Request Permissions With Jetpack Compose?

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 C

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