compose 权限使用accompanist

发布于:2025-06-21 ⋅ 阅读:(18) ⋅ 点赞:(0)

compose使用accompanist来处理权限.网上查了一圈,都是差不多的示例.没有实现我要的效果.

主要需求:

点击一个按钮,如果没有申请权限,则先申请.

如果申请过,但被拒绝了,弹出自定义弹窗,提示被拒绝.

确认再申请,如果被拒绝,而且不再询问,弹出窗口,被拒绝了,确认后进入系统设置.

问题出在它没有处理不再询问这种状态,只有被拒绝了的状态.

依赖:accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanist" }

我要申请录音权限.在点击按钮的时候触发.

@Composable
fun AIDetailScreen(){
    val permissionState = rememberPermissionState(Manifest.permission.RECORD_AUDIO)
    var showPermissionRationaleDialog by remember { mutableStateOf(false) }
    var showGoToSettingsDialog by remember { mutableStateOf(false) }
    // 记录权限是否被拒绝过
    var permissionDeniedBefore by remember { mutableStateOf(false) }
}

这里有几个变量,一个是弹出窗口,这是未申请权限时,让用户开始申请.一个是被拒绝了,且不再询问时弹出,让用户去系统设置修改权限.

点击事件触发的:

onRecordClick = {
                        when {
                            permissionState.status.isGranted -> {
                               //开始处理录音
                            }

                            permissionState.status.shouldShowRationale -> {
                                showPermissionRationaleDialog = true
                            }

                            permissionDeniedBefore && !permissionState.status.shouldShowRationale -> {
                                // 用户之前拒绝过,并且现在选择了"不再询问"
                                showGoToSettingsDialog = true
                            }

                            else -> {
                                permissionState.launchPermissionRequest()
                                permissionDeniedBefore = true
                            }
                        }
                    }

关键点在于:permissionDeniedBefore && !permissionState.status.shouldShowRationale ->

因为第一次未申请时,会走到else,而被拒绝且不再询问时也会走到else.

然后就是显示两个弹窗:确认时permissionState.launchPermissionRequest()进入申请.

// 弹窗显示
            if (showPermissionRationaleDialog) {
                PermissionDialog(
                    title = stringResource(R.string.permission_record_required),
                    message = stringResource(R.string.permission_record_rationale_message),
                    onConfirm = {
                        showPermissionRationaleDialog = false
                        permissionState.launchPermissionRequest()
                    },
                    onDismiss = {
                        showPermissionRationaleDialog = false
                    }
                )
            }
            if (showGoToSettingsDialog) {
                GoToSettingsDialog(
                    title = stringResource(R.string.permission_record_required),
                    message = stringResource(R.string.permission_recording_denied),
                    onOpenSettings = {
                        val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                        intent.data = Uri.fromParts("package", context.packageName, null)
                        context.startActivity(intent)
                        showGoToSettingsDialog = false
                    },
                    onDismiss = {
                        showGoToSettingsDialog = false
                    }
                )
            }

自定义弹窗就简单了.弹窗有两个按钮,一个确认,一个取消,然后回调全部在业务中处理就行了.

@Composable
fun PermissionDialog(
    title: String,
    message: String,
    onConfirm: () -> Unit,
    onDismiss: () -> Unit
) 
@Composable
fun GoToSettingsDialog(
    title: String,
    message: String,
    onOpenSettings: () -> Unit,
    onDismiss: () -> Unit
)

最近compose重写了语音识别的app,效果比flutter写的app要好的多.比以前的view/xml这套也舒服多了,尤其在列表方面,各种头,尾的处理.代码量还少了,不过包体积大了不小.


网站公告

今日签到

点亮在社区的每一天
去签到