Compose - 权限申请(含ActivityResult调用)

一、概念

二、使用 Accompanist Permissions

官方介绍&最新版本

单个权限多个权限

添加权限

@Composable
public fun rememberPermissionState(
    permission: String,
    onPermissionResult: (Boolean) -> Unit = {}
): PermissionState

@Composable
public fun rememberMultiplePermissionsState(
    permissions: List<String>,
    onPermissionsResult: (Map<String, Boolean>) -> Unit = {}
): MultiplePermissionsState

发起请求

fun launchPermissionRequest(): Unit

 fun launchMultiplePermissionRequest(): Unit

2.1 添加依赖 

implementation "com.google.accompanist:accompanist-permissions:0.37.0"

2.2 单个权限申请

如果功能和界面无关,业务逻辑可以写到 rememberPermissionState() 的回调里,点击事件直接调用 launchPermissionRequest()。如果有关(例如拍照预览),采用权限判断进行界面切换更合适。

直接调用功能

@Composable
fun Demo() {
    val context = LocalContext.current
    val permissionState = rememberPermissionState(Manifest.permission.RECORD_AUDIO) { isGranted ->
        if (isGranted) {
            startRecord()
        } else {
            Toast.makeText(context, "请授予权限", Toast.LENGTH_SHORT).show()
        }
    }
    Button({
        permissionState.launchPermissionRequest()
    }) { Text("点击录音") }
}

根据有无权限切换界面

@Composable
fun Demo() {
    val context = LocalContext.current
    val permissionState = rememberPermissionState(
        Manifest.permission.CAMERA
    )
    LaunchedEffect(Unit) {
        //直接显示不再询问的界面,并弹出权限框
        //若是第一次申请,点拒绝后才会变成shouldShowRationale界面
        permissionState.launchPermissionRequest()
    }
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        if (permissionState.status.isGranted) {
            Text("已授权")
        } else if (permissionState.status.shouldShowRationale) {
            Text("摄像头对此应用程序非常重要。请授予权限")
            Button(onClick = {
                permissionState.launchPermissionRequest()
            }) { Text("申请权限") }
        } else {
            Text("摄像头对此应用程序非常重要。请授予权限")
            Button(onClick = {
                context.startActivity(
                    Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
                        data = Uri.fromParts("package", context.packageName, null)
                    }
                )
            }) { Text("点击跳转") }
        }
    }
}

2.3 多个权限申请

val permissionState = rememberMultiplePermissionsState(
    listOf(
        Manifest.permission.CAMERA,
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.RECORD_AUDIO
    )
)

LaunchedEffect(Unit) {
    permissionState.launchMultiplePermissionRequest()
}

2.4 封装(根据有无权限切换界面)

2.4.1 SinglePermissionScreen

/**
 * @param permission 单个权限
 * @param content 有权限界面
 */
@Composable
fun SinglePermissionScreen(
    permission: String,
    content: @Composable () -> Unit
) {
    val context = LocalContext.current
    val permissionState = rememberPermissionState(permission)
    LaunchedEffect(Unit) {
        //直接显示不再询问的界面,并弹出权限框
        //若是第一次申请,点拒绝后才会变成shouldShowRationale界面
        permissionState.launchPermissionRequest()
    }
    if (permissionState.status.isGranted) {
        content
    } else {
        Column(
            modifier = Modifier.fillMaxSize(),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(if (permissionState.status.shouldShowRationale) "该功能需要授予权限后使用。" else "请授予权限后使用该功能。")
            Button(onClick = {
                if (permissionState.status.shouldShowRationale) {
                    permissionState.launchPermissionRequest()
                } else {
                    context.startActivity(
                        Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
                            data = Uri.fromParts("package", context.packageName, null)
                        }
                    )
                }
            }) {
                Text(if (permissionState.status.shouldShowRationale) "申请权限" else "跳转到授权界面")
            }
        }
    }
}

2.4.2 MultiplePermissionsScreen

/**
 * @param permissions 权限集合
 * @param grantedContent 有权限界面
 */
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun MultiplePermissionsScreen(
    permissions: List<String>,
    grantedContent: @Composable () -> Unit
) {
    val context = LocalContext.current
    val multiplePermissionsState = rememberMultiplePermissionsState(permissions)
    LaunchedEffect(Unit) {
        multiplePermissionsState.launchMultiplePermissionRequest()
    }
    if (multiplePermissionsState.allPermissionsGranted) {
        grantedContent
    }  else {
        Column(
            modifier = Modifier.fillMaxSize(),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(if (multiplePermissionsState.shouldShowRationale) "该功能需要授予权限后使用。" else "请授予权限后使用该功能。")
            Button(onClick = {
                if (multiplePermissionsState.shouldShowRationale) {
                    multiplePermissionsState.launchMultiplePermissionRequest()
                } else {
                    context.startActivity(
                        Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
                            data = Uri.fromParts("package", context.packageName, null)
                        }
                    )
                }
            }) {
                Text(if (multiplePermissionsState.shouldShowRationale) "申请权限" else "跳转到授权界面")
            }
        }
    }
}

三、使用 rememberLauncherForActivityResult()

参考:Activity Result API

@Composable
fun Demo() {
    val launcher = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
        if (isGranted) {
            takePic()
        }
    }
    Button(
        onClick = { launcher.launch(Manifest.permission.CAMERA) }
    ) {
        Text("点击拍照")
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值