Android M(6.0)运行时权限申请及遇到的坑

2023-05-16

一、概述

        在对动态权限申请进行详细说明时,还是先大致介绍下6.0后,google对权限的一个归类和划分。在Android M之前,再开发应用的时候,程序员只需要在AndroidManifest.xml文件中进行权限配置即可,这种操作确实比较方便,但是也容让有些程序员为了图方便,一股脑儿的申请很多权限,也不管APP是否能用上。另一方面,对用户而言,一般在安装应用的时候,也不会注意申请了哪些权限,很容易造成用户的数据泄露。所以谷歌从Android M之后,将权限进行了分类,分为普通权限,危险权限和特殊权限。普通权限和以前一样,在AndroidManifest.xml文件配置即可,危险权限就需要程序员更加需要进行动态申请(两个特殊权限再次暂不做讨论)。
       危险权限共分为9组,每一组只要其中一个权限授权了,那同一组的其他权限也自动取得授权,具体如下:
group:android.permission-group.CONTACTS
    permission:android.permission.WRITE_CONTACTS
    permission:android.permission.GET_ACCOUNTS    
    permission:android.permission.READ_CONTACTS

  group:android.permission-group.PHONE
    permission:android.permission.READ_CALL_LOG
    permission:android.permission.READ_PHONE_STATE 
    permission:android.permission.CALL_PHONE
    permission:android.permission.WRITE_CALL_LOG
    permission:android.permission.USE_SIP
    permission:android.permission.PROCESS_OUTGOING_CALLS
    permission:com.android.voicemail.permission.ADD_VOICEMAIL

  group:android.permission-group.CALENDAR
    permission:android.permission.READ_CALENDAR
    permission:android.permission.WRITE_CALENDAR

  group:android.permission-group.CAMERA
    permission:android.permission.CAMERA

  group:android.permission-group.SENSORS
    permission:android.permission.BODY_SENSORS
  group:android.permission-group.LOCATION
    permission:android.permission.ACCESS_FINE_LOCATION
    permission:android.permission.ACCESS_COARSE_LOCATION
  group:android.permission-group.STORAGE
    permission:android.permission.READ_EXTERNAL_STORAGE
    permission:android.permission.WRITE_EXTERNAL_STORAGE
  group:android.permission-group.MICROPHONE
    permission:android.permission.RECORD_AUDIO

  group:android.permission-group.SMS
    permission:android.permission.READ_SMS
    permission:android.permission.RECEIVE_WAP_PUSH
    permission:android.permission.RECEIVE_MMS
    permission:android.permission.RECEIVE_SMS
    permission:android.permission.SEND_SMS
    permission:android.permission.READ_CELL_BROADCASTS

、动态申请权限的方法步骤

总的来说,动态申请权限分为三大步
第一、检测权限是否已经获取
第二、申请获取权限
第三、根据申请反馈的结果(用户是否同意)进行不同的处理
检测是否已经获取到权限,调用checkSelfPermission(String permission)方法即可
final String[] permissions = {Manifest.permission.CAMERA};
// 第一步 检测权限:返回结果如下
//PackageManager.PERMISSION_GRANTED(有权限)
//PackageManager.PERMISSION_DENIED(无权限)
int result = checkSelfPermission(permissions[0]);
根据返回检测结果,做不同处理,如果没有获取到权限,调用requestPermissions(@NonNull String[] permissions, int requestCode)方法获取权限。
这里多啰嗦几句,一般在调用该方法之前,需要先调用shouldShowRequestPermissionRationale(@NonNull String permission)这个方法,判断用户是否已经拒绝过该权限。如果用户在第一次申请的时候,拒绝了该权限,再次申请该权限的时候,该方法就会返回true(默认返回false),这个时候为了增加用户友好体验,可以在此处给用户做一些说明,为什么需要这个权限,希望用户同意等等……,不过此处有坑,后面会详细介绍。
if (result == PackageManager.PERMISSION_GRANTED) {
    // 已经具有权限,直接打开相机
    startCamera();
} else {
    // 第二步 申请权限
    // 判断是否需要向用户弹出权限需求说明
    if (shouldShowRequestPermissionRationale(permissions[0])) {
        new AlertDialog.Builder(MainActivity.this)
                .setTitle("提示")
                .setMessage("应用需要相机权限才能正常使用, 是否授权")
                .setNegativeButton("取消", null)
                .setPositiveButton("授权", new DialogInterface.OnClickListener() {
                    @TargetApi(Build.VERSION_CODES.M)
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        requestPermissions(permissions, REQUEST_CODE);
                    }
                })
                .show();
        return;// 结束执行,防止重复请求权限
    }
    requestPermissions(permissions, REQUEST_CODE);
}
如果是第一次申请权限,则直接弹出申请对话框:
如果 是第二次申请权限,则会弹出提示对话框
对申请结果(用户同意与否)进行监听并处理,重写onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults)这个方法
if (requestCode == REQUEST_CODE && grantResults.length > 0) { // 判断是否有返回结果
    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        Toast.makeText(this, "获取到相机权限, 打开相机", Toast.LENGTH_SHORT).show();
        startCamera();
    } else {
        Toast.makeText(this, "获取相机权限失败", Toast.LENGTH_SHORT).show();
    }
}


三、使用过程中遇到的一些坑

在此先将个人已经遇到的一些坑分享给大家
1、动态权限同样需要在 AndroidManifest.xml文件中进行配置。不知道是我某些地方出错还是确实是这样,至少我在使用过程中发现,如果没有在AndroidManifest.xml文件中进行权限配置,同样不能够正常申请权限。所以无论是普通权限还是危险权限,全部都需要在清单文件里面进行配置。
2、shouldShowRequestPermissionRationale(@NonNull String permission)的返回值问题。由于国内android手机厂家的系统几乎都是经过自己定制处理过的,有些手机厂家直接将该方法的返回值确定为false。及无论用户第几次拒绝,都不会返回true。解决办法和问题3解决方法相同如下
3、用户选择不再提示后拒绝权限。如果用户在拒绝权限的时候,选择了不再提示,那以后应用都不会在弹出对框去申请权限,最终造成APP无法正常使用。如果用户不知道是因为自己拒绝了权限造成的,就会以为你的APP很烂,造成用户体验差。一般解决问题2和3的方式就是,在用户选择了拒绝权限的时候,就对用户进行提示,如果需要,同时引导用户去重新授权,我的处理方式,如果用户确定拒绝,则退出应用,如果用户选择重新授权,直接跳转到应该管理的界面,让用户重新授权,代码如下(该Demo里面不含此部分处理)
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("权限提醒")
        .setMessage("是否要拒绝权限,如果拒绝,应用将无法正常运行")
        .setPositiveButton("拒绝", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                MyApplication.getInstance().exit();
            }
        })
        .setNegativeButton("重设", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    if (!Settings.System.canWrite(LoginActivity.this)) {
                        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                        intent.setData(Uri.parse("package:" + getPackageName()));
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        startActivity(intent);
                    }
                }
            }
        })
        .show();
4、兼容问题:checkSelfPermission和requestPermissions从API 23才加入,低于23版本,需要在运行时判断 或者使用Support Library v4中提供的方法
ContextCompat.checkSelfPermission
ActivityCompat.requestPermissions
ActivityCompat.shouldShowRequestPermissionRationale

四、比较好用的动态权限处理第三方库推荐

个人目前感觉比较好用的有两个库
PermissionsDispatcher  gitHub地址
PermissionGen gitHub地址
本文Demo的下载地址 https://github.com/victorcatfish/PermissionsM.git
我也是一个初学和摸索者,如果有不对的地方还望大家多多指正。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android M(6.0)运行时权限申请及遇到的坑 的相关文章

随机推荐

  • CAN的报文格式

    CAN的报文格式 在总线中传送的报文 xff0c 每帧由7部分组成 CAN协议支持两种报文格式 xff0c 其唯一的不同是标识符 xff08 ID xff09 长度不同 xff0c 标准格式为11位 xff0c 扩展格式为29位 在标准格式
  • uabntu系统安装软件:E: 无法定位软件包问题

    血泪教训 耽误了贼长时间 一开始参考了如下链接 xff0c 然而我的问题一个没解决 xff0c 哭了 Ubuntu sudo apt get install 出现 E 无法定位软件包问题 解决方法汇总 遥想在想peach的博客 CSDN博客
  • 右手定则

    http www 7wenta com zhuanti 9648 html 问他 首页问答中心竞技场 学习快报 达人榜商城 问他手机版 注册 登录 问他网 gt 学习专题 gt 高中物理 gt 右手定则 物理题库练习题我要提问
  • 【机器人规划】Bug解析

    文章目录 参考文献简介Bug1算法Bug2算法Tangent Bug算法关于O i的选择激光雷达半径对算法的影响 总结 参考文献 自动驾驶决策规划算法 Bug Algorithms Bug算法 Robotic Motion Planning
  • ubantu虚拟机无法联网

    在VMware中安装Ubuntu虚拟机 xff0c 总会发生无法上网的情况 xff0c 主要情况有以下几点 xff1a 宿主机可以上网 xff1b 虚拟机却无法访问网页虚拟机ping不通任何网站 xff0c 用浏览器显示error 一般情况
  • 半监督语义分割论文学习记录

    Semi Supervised Semantic Segmentation with Cross Consistency Training 1 1 motivation 一致性训练的目的是在应用于输入的小扰动上增强模型预测的不变性 因此 x
  • 使用Qt二次开发周立功CAN(一)

    使用Qt二次开发周立功CAN xff08 一 xff09 使用Qt二次开发周立功的CAN通信 xff0c 第一步需要完成动态链接库的加载 xff0c 成功加载之后才能调用其提供的接口函数 加载库需要注意的问题有两个 xff1a 一是Qt版本
  • 字节序基础知识

    在各种计算机体系结构中 xff0c 对于字节 字等的存储机制有所不同 xff0c 因而引发了计算机通信领 域中一个很重要的问题 xff0c 即通信双方交流的信息单元 xff08 比特 字节 字 双字等等 xff09 应该以什么样的顺序进行传
  • vlc命令行: 转码 流化 推流

    写在命令行之前的话 xff1a VLC不仅仅可以通过界面进行播放 xff0c 转码 xff0c 流化 xff0c 也可以通过命令行进行播放 xff0c 转码和流化 还可以利用里面的SDK进行二次开发 vlc命令行使用方法 xff1a 1 x
  • C++ 简单实现HTTP GET/POST 请求

    HTTP 超文本传输协议 是一种客户端与服务端的传输协议 xff0c 最早用于浏览器和服务器之间的通信 xff0c 后来因为其使用灵活 方便等特点 xff0c 广泛用于客户端与服务端的通信 文章将简单介绍HTTP协议 xff0c 同时以C
  • STM32单片机HAL库下串口接收不定长数据

    xff33 xff34 xff2d xff13 xff12 单片机 xff28 xff21 xff2c 库下串口接收不定长数据 xff28 xff21 xff2c 库下的串口接收不定长数据代码配置代码实现代码演示总结 xff28 xff21
  • C++将一个数据格式化为固定长度的字符串

    经常会遇到将数据解析为文本文件的现象 xff0c 通常因为数据长度的不同导致 xff0c 可视化效果不好 写一个输入数据获取固定长度字符串的函数 xff0c 来得到一个固定长度的数据 xff0c 让格式化看起来好看一些 include lt
  • Socket原理与编程基础

    一 Socket简介 Socket是进程通讯的一种方式 xff0c 即调用这个网络库的一些API函数实现分布在不同主机的相关进程之间的数据交换 几个定义 xff1a xff08 1 xff09 IP地址 xff1a 即依照TCP IP协议分
  • mac 安装brew

    起因是这样的 xff0c 我想在mac上安装htop 然后我了解到可以用brew安装htop 然后再执行命令 brew install htop 所以我就开始吭哧吭哧安装brew 过程xue wei 曲折了一些 先是看到一个文章 xff0c
  • 【项目学习】C++实现高并发服务器——代码学习(三)用户注册登录功能

    项目来源 xff1a WebServer 上一篇 xff1a 存储解析HTTP请求报文 xff0c 创建响应报文 本文介绍以下功能的代码实现 利用RAII机制实现了数据库连接池 xff0c 减少数据库连接建立与关闭的开销 xff0c 同时实
  • 用CSS3实现动画进度条

    CSS3的新特性为我们实现漂亮的进度条扫清了障碍 xff0c 我们可以完全不需要任何图片和简单的Javascript代码就可以构建 一 第一个例子 效果图 xff1a Demo地址 xff1a http namepk sinaapp com
  • tcpdump命令使用详解

    tcpdump命令使用详解 疯狂的小企鹅的博客 CSDN博客 tcpdump命令详解全网最详细的 tcpdump 使用指南 王一白 博客园Tcpdump抓包工具实战教程 xff0c 让你知道一个抓包走天下 xff01 哔哩哔哩 bilibi
  • Chrome浏览器Postman插件安装包及安装教程

    最近电脑装了新环境 xff0c 以前本地的postman安装包竟然找不到了 xff0c 网上费尽心力找了很多资源 xff0c 终于找到纯净的安装包 xff0c 绕开套路 xff0c 现将Postman安装包及安装教程分享给各位 xff0c
  • LayoutInflater的错误用法(Avoid passing null as the view root )

    今天在练习使用Fragment的时候 xff0c 注意到在使用LayoutInflater的时候有黄色报警 xff08 Avoid passing null as the view root needed to resolve layout
  • Android M(6.0)运行时权限申请及遇到的坑

    一 概述 在对动态权限申请进行详细说明时 xff0c 还是先大致介绍下6 0后 xff0c google对权限的一个归类和划分 在Android M之前 xff0c 再开发应用的时候 xff0c 程序员只需要在AndroidManifest