当前位置: 首页 > news >正文

Compose笔记(八)--权限

        这一节主要了解一下Compose中权限的申请,其中主要用到accompanist-permissions这个权限库,它是一个简化的Android Compose 中权限管理的库,如下使用:

栗子:

依赖添加

dependencies {implementation("com.google.accompanist:accompanist-permissions:0.31.2-alpha")
}

单个权限

@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun PermissionExample() {val permissionState = rememberPermissionState(permission = Manifest.permission.CAMERA)Scaffold(topBar = {TopAppBar(title = { Text("Permission Apply Test") })}) {Column(Modifier.fillMaxSize(),horizontalAlignment = Alignment.CenterHorizontally,verticalArrangement = Arrangement.Center) {when (permissionState.status) {PermissionStatus.Granted -> {Text("已经同意了相机权限")}is PermissionStatus.Denied -> {Column {val text = if (permissionState.status.shouldShowRationale) {"相机权限已拒绝,点击按钮再次请求"} else {"相机权限已被禁止"}Text(text = text)Button(onClick = {permissionState.launchPermissionRequest()}) {Text("点击获取权限")}}}}}}
}

多个权限

清单文件:<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />import android.Manifest
import android.content.pm.PackageManager
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.Button
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.core.app.ActivityCompat
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.PermissionStatus
import com.google.accompanist.permissions.rememberMultiplePermissionsState
import com.google.accompanist.permissions.rememberPermissionState
import com.google.accompanist.permissions.shouldShowRationale@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun MultiplePermissionsExample() {// 创建一个多权限状态对象,用于管理相机和存储权限val permissionsState = rememberMultiplePermissionsState(permissions = listOf(Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE))Column(modifier = Modifier.fillMaxSize(),verticalArrangement = Arrangement.Center,horizontalAlignment = Alignment.CenterHorizontally) {val allPermissionsGranted = permissionsState.allPermissionsGrantedval shouldShowRationale = permissionsState.shouldShowRationaleif (allPermissionsGranted) {Text("所有权限已授予,可以使用相关功能。")} else {Column {if (shouldShowRationale) {Text("为了正常使用应用功能,请授予以下权限:相机、存储。")}Button(onClick = { permissionsState.launchMultiplePermissionRequest() }) {Text("请求权限")}}}}
}

注意:

1 依赖添加:确保在项目的 build.gradle(或 build.gradle.kts)文件中正确添加了 accompanist-permissions 库的依赖。同时,要注意使用与项目中其他 Compose 库版本兼容的 accompanist-permissions 版本,避免因版本不兼容导致编译错误或运行时异常。

2 注解使用:accompanist-permissions 库中的部分 API 被标记为 @ExperimentalPermissionsApi,这表示这些 API 还处于实验阶段,可能会在未来的版本中发生重大变化。在使用这些 API 时,需要在使用的函数或类上添加 @OptIn(ExperimentalPermissionsApi::class) 注解,以表明你已经了解并愿意承担使用实验性 API 的风险。

3 预先检查权限:在请求权限之前,应该先检查应用是否已经拥有该权限,避免不必要的权限请求对话框弹出,提升用户体验。可以使用 rememberPermissionState 或 rememberMultiplePermissionsState 返回的状态对象的相关属性进行检查。

原理

1. 基于 Android 系统的权限管理机制
Android 系统从 Android 6.0(API 级别 23)开始引入了运行时权限机制,应用需要在运行时请求某些危险权限。系统提供了一系列的 API 来处理权限请求,例如 ActivityCompat.requestPermissions 用于发起权限请求,ActivityCompat.checkSelfPermission 用于检查权限状态,ActivityCompat.shouldShowRequestPermissionRationale 用于判断是否需要向用户解释为什么需要该权限。

2 状态管理与响应式编程
Compose 是一种声明式的 UI 框架,它基于响应式编程模型,通过状态的变化来驱动 UI 的更新。accompanist-permissions 库利用了 Compose 的状态管理机制,将权限状态封装成可观察的状态对象,当权限状态发生变化时,自动触发 UI 的更新。

  2.1 rememberPermissionState 和 rememberMultiplePermissionsState这两个函数是 accompanist-permissions 库的核心,用于创建权限状态对象。
rememberPermissionState:用于管理单个权限的状态。它返回一个 PermissionState 对象,该对象包含了权限的当前状态信息,如 hasPermission(权限是否已授予)、shouldShowRationale(是否需要显示权限请求说明)等。这些状态信息会随着权限请求结果的变化而自动更新,从而触发 Compose UI 的重组。
rememberMultiplePermissionsState:用于管理多个权限的状态。它返回一个 MultiplePermissionsState 对象,该对象可以跟踪多个权限的授予情况,通过 allPermissionsGranted 判断所有权限是否都已授予,通过 shouldShowRationale 判断是否有任何权限需要显示请求说明。

3. 权限请求处理
accompanist-permissions 库封装了权限请求的逻辑,通过 launchPermissionRequest 和 launchMultiplePermissionRequest 方法来发起权限请求。
 3.1 内部实现
当调用 launchPermissionRequest 或 launchMultiplePermissionRequest 方法时,库会使用 Android 系统的 ActivityResultLauncher 来发起权限请求。ActivityResultLauncher 是 Android 系统提供的一种用于处理 Activity 结果的机制,它可以在请求权限后自动接收权限请求结果,并将结果传递给回调函数。

class PermissionStateImpl(private val permission: String,private val activity: ComponentActivity
) : PermissionState {private val _hasPermission = mutableStateOf(false)private val _shouldShowRationale = mutableStateOf(false)override val hasPermission: Booleanget() = _hasPermission.valueoverride val shouldShowRationale: Booleanget() = _shouldShowRationale.valueprivate val permissionLauncher = activity.registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->_hasPermission.value = isGranted_shouldShowRationale.value = activity.shouldShowRequestPermissionRationale(permission)}override fun launchPermissionRequest() {permissionLauncher.launch(permission)}
}

4. 状态更新与 UI 重组
        当权限请求结果返回时,accompanist-permissions 库会更新权限状态对象的状态信息。由于这些状态信息是使用 Compose 的 MutableState 封装的,当状态发生变化时,Compose 会自动检测到这些变化,并触发相关 UI 组件的重组,从而更新 UI 显示。例如,当用户授予相机权限后,cameraPermissionState.hasPermission 的值会从 false 变为 true,Compose 会重新执行 if (cameraPermissionState.hasPermission) 语句块,更新 UI 显示为 “相机权限已授予”。

相关文章:

Compose笔记(八)--权限

这一节主要了解一下Compose中权限的申请&#xff0c;其中主要用到accompanist-permissions这个权限库&#xff0c;它是一个简化的Android Compose 中权限管理的库&#xff0c;如下使用&#xff1a; 栗子: 依赖添加 dependencies {implementation("com.google.accompani…...

单例模式:确保一个类只有一个实例

目录 引言 1. 单例模式的核心思想 2. 单例模式的实现方式 2.1 饿汉式单例 2.2 懒汉式单例 2.3 线程安全的懒汉式单例 2.4 双重检查锁定&#xff08;Double-Checked Locking&#xff09; 2.5 静态内部类实现单例 2.6 枚举实现单例 3. 单例模式的使用场景 4. 单例模式…...

推荐一个好用的在线文本对比网站 - diffchecker

推荐网址&#xff1a;https://www.diffchecker.com UI设计也很不错&#xff0c;响应也很快&#xff0c;广告少 生成的对比还可以生成在线链接&#xff1a;&#xff08;点击右上角“分享”&#xff09; 可设置过期时间等 我生成的示例&#xff1a;https://www.diffchecker.c…...

学习第八十五行

[capture](parameters) -> return_type {// function body }capture: 捕获列表&#xff0c;指定如何捕获周围作用域中的变量。parameters: 参数列表&#xff0c;与普通函数类似。return_type: 返回类型&#xff0c;可以省略&#xff0c;编译器会自动推断。function body: 函…...

基于Django创建一个WEB后端框架(DjangoRestFramework+MySQL)流程

一、Django项目初始化 1.创建Django项目 Django-admin startproject 项目名 2.安装 djangorestframework pip install djangorestframework 解释: Django REST Framework (DRF) 是基于 Django 框架的一个强大的 Web API 框架&#xff0c;提供了多种工具和库来构建 RESTf…...

【Python 2D绘图】Matplotlib绘图(统计图表)

【Python 2D绘图】Matplotlib绘图&#xff08;统计图表&#xff09; 1. 概述1.1 简介1.2 安装1.3 导入1.4 保存1.5 数据来源1.5.1 Numpy ndarray1.5.2 Pandas DataFrame 1.6 中文显示 2. 基础样式2.1 颜色2.1.1 简称2.1.2 全称 2.2 布局2.2.1 Matplotlib 画布划分2.2.2 绘制子图…...

vue3框架的响应式依赖追踪机制

当存在一个响应式变量于视图中发生改变时会更新当前组件的所以视图显示&#xff0c;但是没有视图中不写这个响应式变量就就算修改该变量也不会修改视图&#xff0c;这是为什么&#xff1f;我们能否可以理解宽泛的理解为vue组件的更新就是视图的更新&#xff0c;单当视图中不存在…...

.Net 6 上传文件接口 文件大小报错整体配置

/// <summary>/// 上传文件/// </summary>/// <param name"file"></param>/// <returns></returns>[HttpPost("UploadifyFile")][RequestSizeLimit(2000 * 1024 * 1024)] // 设置最大请求体大小为 100MBpublic async …...

Git基础之工作原理

基础概念 git本地有三个工作区域&#xff0c;工作目录 Working Directory&#xff0c;暂存区Stage/Index和资源区Repository/Git Directory&#xff0c;如果在加上远程的git仓库就是四个工作区域 四个区域与文件交换的命令之间的关系 WorkSpace&#xff1a;工作区&#xff0c;就…...

小程序 wxml 语法 —— 41列表渲染 - 进阶用法

这一节讲解列表渲染的两个进阶用法&#xff1a; 如果需要对默认的变量名和下标进行修改&#xff0c;可以使用 wx:for-item 和 wx:for-item&#xff1a; 使用 wx:for-item 可以指定数组当前元素的变量名使用 wx:for-index 可以指定数组当前下标的变量名 将 wx:for 用在 标签上&…...

ElasticSearch 入门教程

ElasticSearch 入门教程 ElasticSearch 是一个分布式、可扩展的搜索和分析引擎&#xff0c;基于 Apache Lucene 构建&#xff0c;支持全文检索、结构化查询和聚合分析。本教程将带你深入了解 ElasticSearch 的核心概念、安装配置、常见操作&#xff0c;并提供示例代码&#xf…...

用Python写一个算24点的小程序

一、运行界面 二、显示答案——递归介绍 工作流程&#xff1a; 1. 基本情况&#xff1a;函数首先检查输入的数字列表 nums 的长度。如果列表中只剩下一个数字&#xff0c;它会判断这个数字是否接近 24&#xff08;使用 abs(nums[0] - 24) < 1e-10 来处理浮点数精度问题&…...

分布式网络

分布式网络&#xff08;Distributed Network&#xff09;指的是一种计算机网络架构&#xff0c;其中计算资源&#xff08;计算、存储、数据处理等&#xff09;分布在多个物理或逻辑上的节点上&#xff0c;而不是集中在单一的服务器或数据中心中。这种架构的主要目标是提高系统的…...

忘记dedecms后台超级管理员账号和密码的解决方案

解决方案&#xff1a; 方案一、数据库修改&#xff1a; 1、前提是您能登录到数据库后台&#xff0c;登录MySQL数据库管理工具&#xff08;如phpMyAdmin&#xff09; 2、打开数据库中的 dede_admin 表&#xff0c;找到管理员记录&#xff0c;将 pwd 字段的值改成 f297a57a5a7…...

【Linux学习笔记】Linux基本指令分析和权限的概念

【Linux学习笔记】Linux基本指令分析和权限的概念 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;Linux学习笔记 文章目录 【Linux学习笔记】Linux基本指令分析和权限的概念前言一. 指令的分析1.1 alias 指令1.2 grep 指令1.3 zip/unzip 指…...

Git基础之分支

常用指令 git branch 列出本地所有分支 git branch -r 列出所有远程分支 git branch [branch-name] 新建一个分支&#xff0c;但依然停留在当前分支 git checkout -b [branch] 新建一个分支&#xff0c;并切换到该分支 git merge [branch] 合并指定分支当前分支 git branch -d …...

MAC电脑常用操作

环境&#xff1a;M3芯片 &#xff0c;macOS15.2 &#x1f680; 快捷键 &#x1f5a5;️ 窗口管理 ✅ 退出/进入全屏模式 • 浏览器等应用&#xff1a;⌘ Command Ctrl F ✅ 最小化当前窗口 • ⌘ Command M • &#x1f4a1; 隐藏窗口但保留应用在后台运行 ✅ 关闭当前标…...

【计算机网络】深入解析 HTTP 协议的概念、工作原理和通过 Fiddler 抓包查看 HTTP 请求/响应的协议格式

网络原理— HTTP 1. 什么是HTTP? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议&#xff1a; HTTP 往往是基于传输层的 TCP 协议实现的 (HTTP1.0,HTTP1.1,HTTP2.0 均为TCP,HTTP3基于UDP实现) 我们平时打开一个网站&#xff0c;就是通过HTTP协议来…...

Springboot redis bitMap实现用户签到以及统计,保姆级教程

项目架构&#xff0c;这是作为demo展示使用&#xff1a; Redis config&#xff1a; package com.zy.config;import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.Ob…...

【C++】:STL详解 —— 红黑树封装map和set

目录 红黑树的源代码 正向迭代器的代码 反向迭代器的代码 set的模拟实现 map的模拟实现 红黑树的源代码 #pragma once #include <iostream>using namespace std; // set ->key // map ->key/value// set ->key // map ->key/valueenum Colour {RED,BLAC…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

SpringTask-03.入门案例

一.入门案例 启动类&#xff1a; package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...