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这套也舒服多了,尤其在列表方面,各种头,尾的处理.代码量还少了,不过包体积大了不小.