Skip to content

运行时权限 (Permissions)

源:Accompanist Permissions

在 Compose 中处理运行时权限比传统 View 系统简单得多,我们主要使用 rememberLauncherForActivityResult API。

虽然 Accompanist 提供了非常好用的 Permissions 库,但随着 Compose 的发展,使用原生的 ActivityResultContracts 也是完全可行的。不过,为了开发体验,目前最推荐的方案仍然是使用 Accompanist Permissions 库(Google 官方实验室项目)。

1. 依赖配置

kotlin
implementation("com.google.accompanist:accompanist-permissions:0.34.0")

2. 单个权限申请

kotlin
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun CameraPermissionSample() {
    // 1. 获取权限状态
    val cameraPermissionState = rememberPermissionState(
        android.Manifest.permission.CAMERA
    )

    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        if (cameraPermissionState.status.isGranted) {
            Text("相机权限已授予!可以拍照了。")
        } else {
            Column {
                val textToShow = if (cameraPermissionState.status.shouldShowRationale) {
                    // 如果用户之前拒绝过,说明需要解释为什么需要这个权限
                    "相机权限对于此应用至关重要,请授权。"
                } else {
                    // 第一次请求,或用户选择了“不再询问”
                    "需要相机权限才能使用此功能。"
                }
                
                Text(textToShow)
                Spacer(Modifier.height(8.dp))
                Button(onClick = { cameraPermissionState.launchPermissionRequest() }) {
                    Text("请求权限")
                }
            }
        }
    }
}

3. 多个权限申请

例如同时申请读写存储权限。

kotlin
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun MultiplePermissionsSample() {
    val multiplePermissionsState = rememberMultiplePermissionsState(
        listOf(
            android.Manifest.permission.READ_EXTERNAL_STORAGE,
            android.Manifest.permission.CAMERA
        )
    )

    if (multiplePermissionsState.allPermissionsGranted) {
        Text("所有权限都已搞定!")
    } else {
        Column {
            Text(
                getTextToShowGivenPermissions(
                    multiplePermissionsState.revokedPermissions,
                    multiplePermissionsState.shouldShowRationale
                )
            )
            Button(onClick = { multiplePermissionsState.launchMultiplePermissionRequest() }) {
                Text("请求权限")
            }
        }
    }
}

4. 原生方式 (不依赖 Accompanist)

如果你不想引入额外库,可以使用原生的 ActivityResultLauncher

kotlin
@Composable
fun NativePermissionSample() {
    var hasPermission by remember { mutableStateOf(false) }
    
    val launcher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.RequestPermission()
    ) { isGranted ->
        hasPermission = isGranted
    }

    Button(onClick = { launcher.launch(android.Manifest.permission.CAMERA) }) {
        Text(if (hasPermission) "已授权" else "点击授权")
    }
}