Jetpack Compose 的最佳处理运行时权限的方法

news2024/7/7 15:15:09

Jetpack Compose 的最佳处理运行时权限的方法

android permission in Jetpack compose
如果您的应用安装在运行Android 6.0(API级别23)或更高版本的设备上,则必须按照本指南中的步骤为用户请求运行时权限。

在Jetpack Compose中获取运行时权限有两种方法。

  • 使用Activity Result
  • 使用Accompanist Permissions库

接下来,让我们仔细研究上述两种方法,并附有示例。

使用Activity Result进行运行时权限

第一步是在manifest.xml文件中定义权限。


<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera"/>

在这个示例应用程序中,我使用相机权限示例来捕获图像。请查看我的其他示例,以了解如何使用相机捕获图像。

如何在 jetpack compose 中使用相机捕获图像 (howtodoandroid.com)

https://www.howtodoandroid.com/capture-image-in-jetpack-compose/

如何在 jetpack compose 中从图库选择图像 (howtodoandroid.com)

https://www.howtodoandroid.com/pick-image-from-gallery-jetpack-compose/

创建一个活动结果启动器来请求我们定义的权限。一旦启动,它将返回结果,无论该权限是否被授予。

val permissionLauncher = rememberLauncherForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) {
        if (it) {
            Toast.makeText(context, "Permission Granted", Toast.LENGTH_SHORT).show()
            cameraLauncher.launch(uri)
        } else {
            Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show()
        }

    }

检查权限

在请求权限之前,我们需要检查权限是否已经被授予。如果已经授予,我们可以继续正常流程。如果权限未被授予,那么我们需要使用我们需要的权限来发起权限请求。

val permissionCheckResult = ContextCompat.checkSelfPermission(context, android.Manifest.permission.CAMERA)

            if (permissionCheckResult == PackageManager.PERMISSION_GRANTED) {
                cameraLauncher.launch(uri)
            } else {
  permissionLauncher.launch(android.Manifest.permission.CAMERA)
            }

最后,使用活动结果实现运行时权限的代码将如下所示:


val context = LocalContext.current
    val file = context.createImageFile()
    val uri = FileProvider.getUriForFile(
        Objects.requireNonNull(context),
        BuildConfig.APPLICATION_ID + ".provider", file
    )

    var capturedImageUri by remember {
        mutableStateOf<Uri>(Uri.EMPTY)
    }

    val cameraLauncher =
        rememberLauncherForActivityResult(ActivityResultContracts.TakePicture()) {
            capturedImageUri = uri
        }
    val permissionLauncher = rememberLauncherForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) {
        if (it) {
            Toast.makeText(context, "Permission Granted", Toast.LENGTH_SHORT).show()
            cameraLauncher.launch(uri)
        } else {
            Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show()
        }

    }

    Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.padding(12.dp)) {
        Button(onClick = {
            val permissionCheckResult = ContextCompat.checkSelfPermission(context, android.Manifest.permission.CAMERA)

            if (permissionCheckResult == PackageManager.PERMISSION_GRANTED) {
                cameraLauncher.launch(uri)
            } else {
                // Request a permission
                permissionLauncher.launch(android.Manifest.permission.CAMERA)
            }

        }) {
            Text(text = "Open Camera")
        }

        if (capturedImageUri.path?.isNotEmpty() == true) {
            Image(
                modifier = Modifier
                    .padding(16.dp, 8.dp)
                    .fillMaxWidth()
                    .size(400.dp),
                painter = rememberImagePainter(capturedImageUri),
                contentDescription = null
            )
        }
    }

上面的效果如下:
在这里插入图片描述

请求多个权限

在某些情况下,我们需要一次请求多个权限,例如,位置权限。为此,我们需要使用不同的启动器方法和权限检查。我们来详细看看。

像往常一样,我们需要在 manifest.xml 文件中定义所需的权限。

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

需要的第一步是创建包含我们要请求的权限列表。

val permissions = arrayOf(
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION
    )

使用ActivityResultContracts.RequestMultiplePermissions() 方法一次性请求多个权限。使用此函数并创建权限启动器。

val launcherMultiplePermissions = rememberLauncherForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { permissionsMap ->
        val areGranted = permissionsMap.values.reduce { acc, next -> acc && next }
        if (areGranted) {
            Toast.makeText(context, "Permission Granted", Toast.LENGTH_SHORT).show()
        } else {
            Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show()
        }
    }

现在,启动器已准备好进行多个权限。下一步是检查权限是否已经授予。如果没有授予,则使用权限列表启动权限启动器。

if(permissions.all {
    ContextCompat.checkSelfPermission(
        context,
        it
    ) == PackageManager.PERMISSION_GRANTED
}) {
    // Get the location
} else {
    launcherMultiplePermissions.launch(permissions)
}

请求多个运行时权限的最终代码将是:

val permissions = arrayOf(
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION
    )

    val launcherMultiplePermissions = rememberLauncherForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { permissionsMap ->
        val areGranted = permissionsMap.values.reduce { acc, next -> acc && next }
        if (areGranted) {
            Toast.makeText(context, "Permission Granted", Toast.LENGTH_SHORT).show()
        } else {
            Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show()
        }
    }

    Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.padding(12.dp)) {
        Button(onClick = {

            if(permissions.all {
                ContextCompat.checkSelfPermission(
                    context,
                    it
                ) == PackageManager.PERMISSION_GRANTED
            }) {
                // Get the location
            } else {
                launcherMultiplePermissions.launch(permissions)
            }

        }) {
            Text(text = "Get Current Location")
        }
      
    }

使用accompanist permissions库

与第一种使用方法相比,使用accompanist permission库是一种更容易获得运行时权限的方法。在build.gradle文件中添加该库。

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

添加依赖项后,需要使用rememberPermissionState()方法来维护我们传递给它的权限状态。同时使用PermissionRequired()来观察运行时的权限状态。它包含所有权限状态的视图,比如允许或拒绝的视图。

val permissionState = rememberPermissionState(permission = Manifest.permission.CAMERA)

    PermissionRequired(
        permissionState = permissionState,
        permissionNotGrantedContent = {
            Toast.makeText(context, "Permission not granted", Toast.LENGTH_SHORT).show()
        },
        permissionNotAvailableContent = {
            Toast.makeText(context, "Permission not available", Toast.LENGTH_SHORT).show()
        }) {
        if (isShowCamera) {
            cameraLauncher.launch(uri)
            isShowCamera = false
        }
    }

由于在这个示例中使用相机,需要创建相机启动器来从活动结果中捕获图像。

val cameraLauncher = rememberLauncherForActivityResult(ActivityResultContracts.TakePicture()) {
            isShowCamera = false
            capturedImageUri = uri
        }

现在我们已经完成了权限状态和相机启动器的设置。下一步是使用权限。点击任何按钮或操作时,我们需要调用permissionState.hasPermission来检查权限是否被授予。 如果没有被授予,我们需要调用权限状态启动器以显示运行时权限对话框。

Button(onClick = {
    if(permissionState.hasPermission) {
        cameraLauncher.launch(uri)
    } else {
        isShowCamera = true
        permissionState.launchPermissionRequest()
    }
}) {
    Text(text = "Open Camera")
}

同样地,您可以使用Accompanist库请求多个权限。查看以下代码以获取使用Accompanist请求多个权限的示例。

val permissionsState = rememberMultiplePermissionsState(
    permissions = listOf(
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION
    )
)

PermissionsRequired(
multiplePermissionsState = permissionsState,
permissionsNotGrantedContent = {
    Toast.makeText(context, "Permission not granted", Toast.LENGTH_SHORT).show()
},
permissionsNotAvailableContent = {
    Toast.makeText(context, "Permission not available", Toast.LENGTH_SHORT).show()
}) {
    //content

}
Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.padding(12.dp)) {
    Button(onClick = {

        if(permissionsState.permissions.all {
                ContextCompat.checkSelfPermission(
                    context,
                    it.permission
                ) == PackageManager.PERMISSION_GRANTED
            }) {
            // access location

        } else {

            permissionsState.launchMultiplePermissionRequest()
        }
    }) {
        Text(text = "Location Permission")
    }

}

效果如下
demo effect

完整代码地址

https://github.com/velmurugan-murugesan/JetpackCompose/tree/master/RuntimePermissionJetpackCompose

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/601572.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法与数据结构-复杂度分析

文章目录 什么是大 O 复杂度表示法为什么要用大 O 复杂度表示法如何分析一段代码的时间复杂度1、只关注循环执行次数最多的一段代码2、加法法则&#xff1a;总复杂度等于量级最大的那段代码的复杂度3、乘法法则&#xff1a;嵌套代码的复杂度等于嵌套内外代码复杂度的乘积 几种常…

计算机网络常见面试题

参考:小林coding 1.TCP/IP模型 2.说一下TCP的三次握手? 第一次握手:客户端向服务端发起建立连接请求,客户端会随机生成一个起始序列号x,客户端向服务端发送的字段中包含标志位SYN=1,序列号seq=x。第一次握手前客户端的状态为CLOSE,第一次握手后客户端的状态为SYN-SENT。…

海外网红合作攻略:如何在转化率战场上脱颖而出

在当今社交媒体时代&#xff0c;与海外网红合作已成为企业推广产品与服务的重要途径之一。与海外网红合作不仅可以扩大品牌知名度&#xff0c;还能够吸引更多目标受众。然而&#xff0c;仅仅与网红合作并不能保证高转化率。本文Nox聚星将详细介绍几种有效的方法&#xff0c;帮助…

DDR跑不到速率,调整下PCB叠层就搞掂了?

高速先生成员--姜杰 关于DDR的案例&#xff0c;高速先生已经分享过很多期的文章了&#xff0c;有通过修改主控芯片的驱动解决问题的&#xff0c;有通过修改PCB走线的拓扑来解决问题的&#xff0c;也有通过调节端接电阻来解决问题的&#xff0c;相对于下面即将登场的解决方法而…

【Java|golang】2559. 统计范围内的元音字符串数

给你一个下标从 0 开始的字符串数组 words 以及一个二维整数数组 queries 。 每个查询 queries[i] [li, ri] 会要求我们统计在 words 中下标在 li 到 ri 范围内&#xff08;包含 这两个值&#xff09;并且以元音开头和结尾的字符串的数目。 返回一个整数数组&#xff0c;其中…

Flutter学习一:安装配置

目录 1 官方文档 2 安装配置 2.1 第一步&#xff1a;下载配置Flutter 2.2 第二步&#xff1a;下载配置Android Studio 2.3 第三步&#xff1a;下载配置VScode 1 官方文档 在 Windows 操作系统上安装和配置 Flutter 开发环境 - Flutter 中文文档 - Flutter 中文开发者网站…

从一个励志故事,读懂网络工程师的职业规划

这个励志故事主人公的起点&#xff0c;是在伟创力的工厂打螺丝。 改变 他很早不上学了&#xff0c;出社会的时候学历和技能什么也没有&#xff0c;就只能去工厂打螺丝。他在伟创力的工厂打螺丝打了好多年&#xff0c;在接近30岁的时候&#xff0c;他哥跟他说&#xff1a;你不能…

黑客零基础从入门到精通学习成长路线(超多图、非常详细),看完这一篇就够了

前言 近几年&#xff0c;随着移动互联网、大数据、云计算、人工智能等新一代信息技术的快速发展&#xff0c;围绕网络和数据的服务与应用呈现爆发式增长&#xff0c;丰富的应用场景下暴露出越来越多的网络安全风险和问题。 但是&#xff0c;我国网络安全整体投入不高。网络安…

基于YOLOv7开发构建红外高空小目标检测识别分析系统

基于yolo系列的模型开发构建红外场景下的目标检测系统&#xff0c;在我之前的文章中已经有好几次实践了&#xff0c;感兴趣的话可以自行移步阅读&#xff1a; 《红外海洋目标检测实践&#xff0c;基于目标检测模型识别红外海洋目标》 《基于YOLO开发构建红外场景下无人机航拍…

【Java基础】简单参数和springboot方式形参传递法

一、知识点整理 1、Postman 2、在原始的web程序中获取请求参数需通过HttpServletRequest对象手动获取 二、操作步骤 1、参考链接1下载postman&#xff0c;并创建工作空间。 2、打开idea&#xff0c;新建项目&#xff0c;选择Spring Initializar&#xff0c;依赖库勾选Web下…

Locust接口性能测试

谈到性能测试工具&#xff0c;我们首先想到的是LoadRunner或JMeter。LoadRunner是非常有名的商业性能测试工具&#xff0c;功能非常强大。但现在一般不推荐使用该工具来进行性能测试&#xff0c;主要是使用也较为复杂&#xff0c;而且该工具体积比较大&#xff0c;需要付费且价…

temu,速卖通,国际站如何稳定安全的测评补单,提升权重不降权

随着互联网和电子商务的快速发展&#xff0c;越来越多的企业和个人通过测评&#xff0c;补单进行产品推广和销售。然而&#xff0c;在测评&#xff0c;补单过程中&#xff0c;如何稳定安全地进行&#xff0c;以提升权重而不降权&#xff0c;成为了许多经营者关注的重要问题。林…

day44_项目1

今日内容 零、 复习昨日 零、 复习昨日 一、web开发流程 1.公司部门的组成人事部门HR技术部门(研发部/IT部/java组/h5组/c组/ui组/产品)行政部门财务部门市场部门运营部门总经理老板/董事/CEO2.项目部人员的组成 各种开发人员: UI/前端/后端(java/c/Python/c/android/Object-c…

CTFShow-WEB入门篇--信息搜集详细Wp

CTFShow-WEB入门篇详细Wp 信息收集&#xff1a;web1&#xff1a;web2&#xff1a;web3&#xff1a;web4&#xff1a;web5&#xff1a;web6&#xff1a;web7&#xff1a;web8&#xff1a;web9&#xff1a;web10&#xff1a;web11&#xff1a;web12&#xff1a;web13&#xff1a;…

基于linux的程序库文件打包和调用的实现(二)——动态库文件打包和调用

随着技术的发展&#xff0c;基于linux项目的软件代码越发复杂&#xff0c;原来一个人可以完成的软件项目&#xff0c;现在可能需要多个人合作、多个部门合作、多个企业合作&#xff0c;每个人、每个部门、每个企业可能负责部分软件模块的开发。各个软件模块在调试过程由于涉及企…

测试思想-集成测试 关于接口测试 Part 2

5. 用例设计思想(举例说明) 如上表&#xff0c;是某个接口说明文档中的一个接口&#xff0c;课程检索&#xff0c;其中“v1/Lesson/testsrch/?” 为接口调用地址&#xff0c;此外&#xff0c;还给出了接口函数输出(即Server Response)及返回值。 问&#xff1a;怎么设计&…

如何免费在线把Figma转成Sketch

我相信所有的设计师都非常熟悉新的设计工具。Figma以其在线合作的特点受到设计师的欢迎。然而&#xff0c;对于设计师来说&#xff0c;在实际工作中&#xff0c;有时需要使用Sketch编辑Figma文件。 今天推荐一款Figma转换Sketch文件格式的免费工具。 下面具体介绍如何通过即时…

chatgpt赋能python:Python内置函数表

Python内置函数表 Python是一种高级编程语言&#xff0c;具有许多内置函数&#xff0c;可用于各种用途&#xff0c;例如处理字符串、操作文件、执行数学计算等等。在本文中&#xff0c;我们将介绍Python内置函数表并讨论其中的一些常见用途。 什么是Python内置函数&#xff1…

JavaFX 树视图TreeView

JavaFX 树视图TreeView 1、TreeView基础查看2、显示案例 1、TreeView基础查看 javafx.scene.control.TreeView<T> javafx.scene.control.TreeItem<T> w3cschool&#xff1a;JavaFX 树视图 DOC-03-14 树视图(Tree View) JavaFX视频教程第101课&#xff0c;TreeView…

List 的使用

1. List 列表视图实现增删改操作 /// 列表视图 struct ListBootcamp: View {/// 水果State var fruits: [String] ["apple", "orange", "banana", "peach"]/// 蔬菜State var veggies: [String] ["tomato", "potato…