[Android]实现一个权限申请类

[Android]实现一个权限申请类

在这里插入图片描述

导言

在引入了动态权限申请之后,Android的权限申请就变得尤为繁琐,若是按照原有的方法一板一眼地进行申请,样板代码未免太多。因此本篇文章就使用ActivityResult API,来实现一个简单的权限申请类来帮助我们简化权限申请的过程。

在此之前,你可能需要了解一些关于ActivityResult API相关的知识:使用Activity Result API 清爽地请求权限 和 启动Activity。

前置知识

在介绍正式的实现过程之前还是先简单介绍一下ActivityResult API,这是AndroidX中的内容,旨在解耦Activity的职责,避免Activity中出现的大量的集中的回调代码的出现。

该API有两个重要的概念:Launcher(启动器),Contract(契约)。其中,启动器是真正帮我们去执行操作(比如申请权限)的类,而契约类则规定了启动器的行为,比如说申请权限还是启动另一个Activity。但是在我们今天的这个主题下,只需要关注申请权限这一个行为就OK了,所以也无需太过关注契约类。

除此之外,还需要注意的一点是ActivityResult 的启动器 必须要在宿主的生命周期到达 CREATED 之前就创建完毕,所以我们在设计申请类的时候必须把这一点考虑进去。

具体实现

权限检查

首先我们从简单地做起,一个权限相关的工具类必备的就是权限的检查,这个我们用原有的方法就可以了,代码如下:

    //检查权限
    fun checkPermission(context:Context,target:Array<String>):Boolean {
        for (permission in target) {
            val result = ContextCompat.checkSelfPermission(context,permission)
            if (result != PackageManager.PERMISSION_GRANTED) {
                return false
            }
        }
        return true
    }

核心设计

关于权限申请的权限的设计,由于有Launcher的存在,所以我们有存储Launcher的诉求,自然而然我们会想到用一张HashMap去存储。之后我们需要考虑的就是如何将权限,宿主。启动器这三者映射起来,所以可以用一张二维的HashMap去存储。具体结构是这样:一个宿主对应一张HashMap,该HashMap中一个权限对应一个Launcher,如下图所示:
在这里插入图片描述
我们用这么一个HashMap去存储对应的关系:

private val ownerMap = mutableMapOf<ComponentActivity,MutableMap<String,ActivityResultLauncher<String>>>()

注册启动器 & 注销注册器

有了上边所说的Map来存储映射关系之后,我们就需要填充这张Map了,具体来说就是注册启动器的过程,这个过程也十分简单,主要就是依次找对应项,如果对应项不存在的话就新创建一项进行填充:

    //注册启动器
    fun registerLauncher(owner: ComponentActivity, permission:String, callback:ActivityResultCallback<Boolean> = Empty_Callback) {
        val launcher = owner.registerForActivityResult(ActivityResultContracts.RequestPermission(),callback)
        if (!ownerMap.containsKey(owner)) {
            ownerMap[owner] = mutableMapOf()
        }
        ownerMap[owner]!!.put(permission,launcher)

        //注册一个事件自动移除启动器
        owner.lifecycle.addObserver(object :LifecycleEventObserver{
            override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    unRegisterLauncher(owner,permission)
                    Log.d(TAG, "onStateChanged: Removed")
                }

            }
        })
    }

这里比较特殊的一点是为了防止内存泄漏的问题,若宿主的生命周期已经达到onDestroy则会自动将二次映射的数据项进行移除。注销注册器的代码如下所示:

    //注销启动器
    fun unRegisterLauncher(context: Context,permission: String) {
        if (ownerMap.containsKey(context) && ownerMap[context]!!.containsKey(permission)) {
            ownerMap[context]!!.remove(permission)
        }
    }

完整代码

最后,给出完整的代码,如下所示:

object PermissionUtil {
    //若不需要回调,使用此空实现
    public val Empty_Callback = object :ActivityResultCallback<Boolean> {
        override fun onActivityResult(result: Boolean) {

        }
    }

    private const val TAG = "PermissionUtil"

    private val ownerMap = mutableMapOf<ComponentActivity,MutableMap<String,ActivityResultLauncher<String>>>()

    //注册启动器
    fun registerLauncher(owner: ComponentActivity, permission:String, callback:ActivityResultCallback<Boolean> = Empty_Callback) {
        val launcher = owner.registerForActivityResult(ActivityResultContracts.RequestPermission(),callback)
        if (!ownerMap.containsKey(owner)) {
            ownerMap[owner] = mutableMapOf()
        }
        ownerMap[owner]!!.put(permission,launcher)

        //注册一个事件自动移除启动器
        owner.lifecycle.addObserver(object :LifecycleEventObserver{
            override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    unRegisterLauncher(owner,permission)
                    Log.d(TAG, "onStateChanged: Removed")
                }

            }
        })
    }

    //申请权限
    fun requestPermission(context: Context,permission: String):Boolean {
        val launcher = ownerMap[context]?.get(permission)
        if (launcher == null) {
            Log.e(TAG, "Launcher 未注册!")
            return false
        } else {
            launcher.launch(permission)
            Log.d(TAG, "requestPermission: 请求ing")
            return (checkPermission(context, arrayOf(permission)))
        }
    }

    //检查权限
    fun checkPermission(context:Context,target:Array<String>):Boolean {
        for (permission in target) {
            val result = ContextCompat.checkSelfPermission(context,permission)
            if (result != PackageManager.PERMISSION_GRANTED) {
                return false
            }
        }
        return true
    }

    //注销启动器
    fun unRegisterLauncher(context: Context,permission: String) {
        if (ownerMap.containsKey(context) && ownerMap[context]!!.containsKey(permission)) {
            ownerMap[context]!!.remove(permission)
        }
    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【漏洞复现】Kubernetes PPROF内存泄漏漏洞(CVE-2019-11248)

Nx01 产品简介 Kubernetes&#xff08;简称K8S&#xff09;是Google在2014年开源的一个容器集群管理系统。它用于容器化应用程序的部署、扩展和管理&#xff0c;目标是让部署容器化应用简单且高效。 Nx02 漏洞描述 漏洞存在于Kubernetes的1.18.6版本之前&#xff0c;可能导致未…

「解析」Jetson配置 git服务

这两天感冒了在家休养&#xff0c;想着把之前买的 Jetson 开发板用起来&#xff0c;买Jetson的初衷就是用来学习Linux系统&#xff0c;顺道可以部署算法&#xff0c;以及一些其他需求&#xff0c;相比树莓派而言&#xff0c;Jetson开发相对更贵&#xff0c;但是其配备了英伟达的…

conda 安装, 配置以及使用

文章目录 1. 安装2. 配置2.1 如何配置2.2 快速设置取消自动进入 base 环境conda 添加清华源pip 添加清华源pip 更新为最新版本 3. 使用 conda 是 python 的环境管理工具包&#xff0c;非常好用&#xff0c;特别是 miniconda 相对于 conda 不需要安装其他的工具&#xff0c;而且…

详细讲解Python中的aioschedule定时任务操作

目录 前言1. 基本概念2. 基本API3. Demo 前言 如果下面的函数库无法执行&#xff0c;出现类似&#xff1a;&#xff08;前提是python3.7以上&#xff09; AttributeError: module ‘asyncio‘ has no attribute ‘run‘请检查run是否可跳转&#xff0c;如果无法跳转&#xff…

Jenkins实现基础CI操作配合python

条件&#xff1a; gitlab准备好 jenkins准备好 (不会java项目, 故跳过Maven打jar包) jenkins配置 在配置里通过插件Git Parameter配置Git&#xff0c;以便于从gitlab 拉去代码到Jenkins r容器内 /var/jenkins_home/ 刚接触python 项目好像不需要构建&#xff0c;直接推送到远…

深度学习弱光图像增强入门学习贴及相关可参考工作推荐

0 引言 先表明身份&#xff0c;在过去三年的时间里&#xff0c;发表弱光图像增强的SCI工作多篇&#xff0c;后续会在Github的代码库构建好之后&#xff0c;分享代码链接&#xff0c;欢迎关注&#xff08;由于工作过于垃圾&#xff0c;因此咱还是以大佬的工作作为参考 首先&am…

推荐一款低成本半桥驱动器集成电路 SIC631CD-T1-GE3

SIC631CD-T1-GE3 是经过优化的集成功率级解决方案用于同步降压应用&#xff0c;提供大电流、高电压效率高&#xff0c;功率密度高。使电压调节器设计能够提供高达50 A的电流每相持续电流。内部功率MOSFET利用Vishay的最先进的第四代TrenchFET技术行业基准绩效将显著降低开关和传…

深入浅出Spring AOP

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;咱们今天要聊的是Java中Spring框架的AOP&#xff08;面向切面编程&#xff09;。对于程序员来说&#xff0c;理解AOP对于掌握Spring框架来说是超级关键的。它像是魔法一样&#xff0c;能让咱们在不改变原有代码的…

XSS漏洞:prompt.mi靶场通关

xss系列往期文章&#xff1a; 初识XSS漏洞-CSDN博客 利用XSS漏洞打cookie-CSDN博客 XSS漏洞&#xff1a;xss-labs靶场通关-CSDN博客 目录 第0关 第1关 第2关 第3关 第4关 第5关 第6关 第7关 第8关 第9关 第A关 第B关 第C关 第D关 第E关 第F关 上一篇文章给…

c语言将csv文件中的XY轴数据转换为html波形图

目标&#xff1a; c语言实现一个最简化的csv转html波形图显示方案。 csv文件格式&#xff1a; 共两行数据&#xff0c;第一行是x轴数据&#xff0c;第二行是y轴数据。 csv文件名分为3段: 波形图名称&#xff0c;x轴名称&#xff0c;y轴名称。 c代码&#xff1a; int csv2html…

springboot集成shiro+前端vue,前后端分离项目遇到跨域以及sessionid拿不到等问题

近期在写前后端分离的项目&#xff0c;由于前后端分离导致原来使用的shiro配置无法满足现有系统要求。同时在前后端分离项目中存在的一些问题。例如&#xff0c;一些用户信息需要存储在后端方便进行安全性判断&#xff0c;但这些存储在后端的session前端却获取不到&#xff08;…

开发知识点-java基础

java基础知识整理 windows 多版本java jar包不能直接打开 需要java -jar问题解决 windows 多版本 控制面板 java15 download 多版本 https://www.cnblogs.com/chenmingjun/p/9941191.html https://gitee.com/shixinke/JC-jEnv/repository/archive/master.zip java jar包不…

2024年AMC8历年真题练一练和答案详解(10),以及全真模拟题

六分成长继续为您分享AMC8历年真题&#xff0c;最后两天通过高质量的真题来体会快速思考、做对题目的策略。 题目从575道在线题库&#xff08;来自于往年真题&#xff09;中抽取5道题&#xff0c;每道题目均会标记出自年份和当年度的序号&#xff0c;并附上详细解析。【使用六…

CUDA tips

命令行查看核函数消耗的寄存器和共享内存数量 nvcc --ptxas-options-v reduce_sum.cu nvprof 使用 由于 8.0 及以上计算能力的显卡用不了 nvprof&#xff0c;官方建议用 nsight system 和 ncu&#xff0c;但是如果只想命令行打印表格查看 kernel 概况感觉还是 nvprof 方便&am…

三个方法解决pycharm中 ,alt +enter自动导入包的快捷键失效的问题

目录 1. 检查IDE设置&#xff1a;查看IDE的设置&#xff0c;确保自动导入包的功能是启用的 2. file>settings>keymap 里没有找到 alt enter 的快捷键 3. 按照网上教程说的如下选项勾上&#xff0c;也没用 4. 在右侧的General设置界面中&#xff0c;找到并点击Auto I…

YOLOv5改进 | 2023主干篇 | 多种轻量化卷积优化PP-HGNetV2改进主干(全网独家创新)

一、本文介绍 Hello,大家好,上一篇博客我们讲了利用HGNetV2去替换YOLOv5的主干,经过结构的研究我们可以发现在HGNetV2的网络中有大量的卷积存在,所以我们可以用一种更加轻量化的卷积去优化HGNetV2从而达到更加轻量化的效果(亲测优化后的HGNetV2网络比正常HGNetV2精度更高…

Mac OS系统 SVN客户端 smartSVN 安装和基础使用

一、下载SVN客户端 官网地址&#xff0c;可以根据自己的系统下载 https://www.smartsvn.com/download/ 二、安装客户端和激活 第一步安装&#xff0c;很简单。 第二步&#xff0c;激活&#xff0c;选择激活文件 创建一个许可文件&#xff0c;例如 smartSvn.license。 内容如…

RabbitMQ交换机(1)

1.交换机Exchange RabbitMQ消息传递模型的核心思想是: 生产者生产的消息从不会直接发送到队列。实际上&#xff0c;通常生产者甚至都不知道这些消息传递传递到了哪些队列中。 相反&#xff0c;生产者只能将消息发送到交换机(exchange)&#xff0c;交换机工作的内容非常简单&am…

PDF有编辑密码怎么办

目录 注意&#xff1a; windows方法&#xff1a; 1 python 下载 2 打开命令行 3 安装 pikepdf 4 编写python脚本 5 使用py脚本 6解密完成 Linux方法&#xff1a; 注意&#xff1a; 此方法可以用于破解PDF的编辑密码&#xff0c;而不是PDF的打开密码 当遇到类似如下问…

Matlab交互式的局部放大图

在数据可视化中&#xff0c;很多时候需要对某一区间的数据进行局部放大&#xff0c;以获得对比度更高的可视化效果。下面利用 MATLAB 语言实现一个交互式的局部放大图绘制。 源码自行下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1yItVSinh6vU4ImlbZW6Deg?pwd9d…