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)运行时权限申请及遇到的坑 的相关文章

  • 新的 Material Design 底部导航应使用哪个视图? [复制]

    这个问题在这里已经有答案了 我相信你们都听说过添加底部导航 https www google com design spec components bottom navigation html材料设计指南 我计划将其添加到我的应用程序中 但
  • 设置 CollapsingToolbarLayout 的起始高度

    我希望能够在 CollapsingToolbarLayout 内的 ImageView 上滚动 那么这怎么可能 以及如何设置该图像视图的起始高度 我的 ImageView 高度是 280p 在活动开始时我想显示 200p 然后我可以向下滚动
  • 尝试在 Android 上使用 FFMPEG。编译但是还是不行

    首先 我尝试使用 ffmpeg 将图像数组编译成 Android 上的视频 我已经遵循了各种在线教程 并且已经能够编译 Android 的库 但仍然需要项目运行 我现在使用的存储库可以在这里找到 https github com Batte
  • Android ImageButton 在 Activity 中运行良好。它在片段中不起作用

    我正在尝试转换布局 使其包含片段 其中一个视图是具有侦听器的 ImageButton 该代码作为 Activity 运行良好 但作为 Fragment 会出现麻烦 第一个问题是我无法使用 findViewById 但我能够在这里找到答案并使
  • OneSignal 推送通知 单击以打开活动

    我集成了一个用于推送通知的信号库 我想在应用程序未运行时通过单击推送通知来打开特定活动 我收到推送通知 但当我单击通知时 应用程序崩溃了 这是我的通知接收器代码 public class ExampleNotificationOpenedH
  • __stack_chk_fail_local 和 -fno-stack-protector - 如何让它工作?

    Update 我刚刚发现问题出在我的项目 libxml2 中包含的预构建库上 它是在启用堆栈保护的情况下构建的 因此依赖于 stack chk fail local方法 我现在已经重建了该库 fno stack protector也是 一切
  • Firebase 云消息传递 - 目标到 Firebase 控制台中不可见的单个设备

    我正在尝试向 android 中的单个设备发送通知 但是当我从 Firebase 控制台执行此操作时 它在 Firebase 新视图中不可见 谁能帮助我从哪里向单个设备发送通知 仔细尝试以下步骤 Tap 新通知 Fill up 通知标题 可
  • overridePendingTransition 显示第二个活动的速度太快

    我有 2 个活动 我想在两个活动之间创建一个动画过渡 以便两个活动的视图向上滑动 就好像第二个活动正在向上推动第一个活动一样 在我的第一个活动中我使用 Intent iSecondActivity new Intent FirstActiv
  • Android Studio,工具提示消失得这么快

    我有以下问题 我想从这个工具提示中复制错误文本 但是一旦我将鼠标悬停在它上面 它就消失得如此之快 这让我发疯 我有以下 android studio 版本 我有以下设置 谢谢您的帮助 如果有人遇到这个问题 这与logcat刷新的方式有关 每
  • 尝试使用 Facebook ID 获取 Facebook 图像时获取空位图

    这是我正在使用的代码 String imageURL Bitmap bitmap null imageURL http graph facebook com fbID picture type try bitmap BitmapFactor
  • JaCoCo 显示 0% 覆盖率,即使所有测试均已通过

    我在下面写了一些测试用例androidTest目录 我正在使用 androidx testInstrumentationRunner androidx test runner AndroidJUnitRunner 添加的依赖项 androi
  • 防止滚动时自定义 ListView 刷新。我想停止刷新

    我在我的 Android 应用程序中使用自定义 ListView 问题是当我滚动 ListView 时 它会自动清除从 EditText Edittext 作为 list item 输入的数据 并且 ListView 刷新 我想阻止它停止清
  • 在 Android 模拟器中获取互联网连接

    我有一台带有wifi连接的台式电脑 我的IP地址是192 168 12 95 网关是192 168 10 10 但是我在android模拟器中没有获得互联网连接 也就是说我无法访问internate 我也尝试过 emulator avd w
  • Android jUnit 测试 java.lang.NoClassDefFoundError: android/database/sqlite/SQLiteOpenHelper

    我正在尝试运行一个模拟子类的单元测试SQLiteOpenHelper但我收到以下错误 java lang NoClassDefFoundError android database sqlite SQLiteOpenHelper at ja
  • Android - 带动画的可扩展 TextView

    我有一个TextView首先显示长文本的一小部分 用户可以按 查看更多 按钮来展开TextView并查看该文本的其余部分 进行测试 我可以通过简单地交换以下值来实现这一点TextView setMaxLines介于 4 之间 用于折叠 和
  • 从前台服务的活动中释放内存

    我有一个带有前台服务和一项活动的应用程序 该服务可以在启动时自行启动 也可以从 Activity 中启动 我注意到当服务在启动时自行启动时 内存使用量约为 3MB 一旦我打开该 Activity 内存使用量就会跃升至约 9mB 一旦 Act
  • 如何运行传递给模拟方法的 lambda 函数?

    我想知道是否可以运行作为参数传递给模拟函数的 lambda 函数 并在调用模拟方法时运行它 我正在使用 Mockk 我想象代码是这样的 class DataManager fun submit lambda Int gt Unit val
  • 屏幕方向更改后应用程序崩溃

    我有以下问题 启动后 应用程序工作正常 即使在更改屏幕方向后也是如此 应用程序尚未准备好处理方向更改 例如替代布局等 因此仅显示旋转的默认布局就可以了 但是 当我通过按后退键离开应用程序 更改方向并在再次启动应用程序后立即崩溃 崩溃后 如果
  • 找不到R类

    当我打开 Eclipse 时 R class在我的项目中消失了 为什么 我有 eclipse juno 和最新版本的 android SDK The R class不会重新生成 因为代码中有错误 我怎么解决这个问题 Try Project
  • 如何找出每个包含的库的最低 api 级别

    我的项目中包含了很多库 Android Studio 2 0 Preview 4 我想找出它们每个的最低 Android SDK 级别 是否可以不用谷歌搜索每个图书馆的信息 如果您有源形式的库 例如 作为项目中的库模块 请查看其清单 如果您

随机推荐

  • 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