Android动态权限适配

在 Android 6.0 也就是 API 版本 23 之前,App 需要的权限都会在安装阶段向用户展示。而在 App 运行期间则不需要动态判断权限是否已申请。从 6.0 之后的版本开始,App 需要在代码中动态申请相应的权限。

权限分类

Android 权限分 2 种:普通权限和危险权限,这 2 种权限都需要在 AndroidManifest 清单文件中声明。

  • 普通权限(Normal Permission)

在程序运行时期自动获取,只需要在清单文件中声明即可。最常用的就是 INTERNET 网络权限。

  • 危险权限(Dangerous Permission)

App 中可能存在一些操作会查看与用户隐私相关的信息,比如查看用户的通讯录或者图库等。对于这一类操作,Android 系统要求 App 主动向用户展示操作所需要的权限,只有用户授权之后才可以进行下一步操作,这样就保证了用户的隐私信息不会被轻易窃取。

接下来,我们对权限申请流程做一个简要说明:

  1. 判断 API 版本是否小于 23。
  2. 如果版本低于 23,则不需要动态申请权限,否则调用 checkSelfPermission() 方法检查权限是否已申请。
  3. 如果 checkSelfPermission 返回
    false,说明权限并没有申请,此时需要调用requestPermission方法主动发送申请权限的操作。

上述描述的流程中,在调用 requestPermission 方法申请权限之前,还有一步比较重要的操作:判断是否需要展示 shouldShowRequestPermissionRationale

shouldShowRequestPermissionRationale

shouldShowRequestPermissionRationale 这个方法会返回以下两种情况

  • 返回 true:用户之前在申请权限操作时,点击了“拒绝”按钮,但是没有选中“Never ask again”选项。
  • 返回 false:有 2 种情况会返回 false,其一是用户从来没有申请过此权限;二是用户之前选中拒绝,并且勾选了“Never ask
    again”选项。

针对返回 true 的情况很容易处理,这种情况表示用户已经拒绝过申请操作,但是并没有选中“Never ask again”选项,因此我们只需要再次调用 requestPermission 方法申请权限即可,系统会自动弹出申请权限的对话框。

但是对于返回 false 的情况稍微麻烦一点,因为有 2 种情况会返回 false,而针对这 2 种情况所对应的相应反馈操作也不一样。比如如果用户从来没有申请过此权限,那就同上述返回 true 的操作一样,直接调用 requestPermission 方法申请权限即可;但是如果是因为用户之前拒绝申请操作,并且勾选“Never ask again”选项,此时我们不应该再执行 requestPermission 方法,而是应该弹出自定义的对话框,提示用户此操作必须通过权限申请之后才可继续进行,并给用户提供进入权限设置界面的入口。

需要注意的一点是 shouldShowRequestPermissionRationale 返回 true
的情况在很多国内厂商的手机中设置了自动屏蔽,也就是没有返回 true 的情况,比如华为、小米等手机。

代码示例

接下来我们以申请通讯录权限为例来演示如何进行动态权限适配,首先需要判断系统版本是否高于 23,代码如下:
在这里插入图片描述只有在高于 23 版本的系统中才需要动态申请权限,在申请之前还需要检查当前 App 是否已经获取到相应的权限,避免重复申请,如下所示:
在这里插入图片描述上图中的 PackageManager.PERMISSION_GRANTED 表示权限已获取。

接下来就是申请权限的流程,上文中已经介绍在申请权限之前,需要调用 shouldShowRequestPermissionRationale 方法判断用户之前的操作,因此代码修改如下:
在这里插入图片描述图中 1 处 shouldShowRequestPermissionRationale 返回 true,直接调用 requestPermission 再次申请权限即可。但是对于返回 false 的情况需要特殊处理,因为有 2 种情况返回 false。我们可以借助于 SharedPreference 来判断是否为用户第一次申请权限的操作,代码如下所示:
在这里插入图片描述上图中使用 SharedPreference 来保存用户是否是第一次申请权限的状态值,默认情况为 true,当执行一次申请权限操作之后需要将其设置为 false。

权限申请操作封装

App 中会存在很多调用危险权限的代码,如果每一次执行这些代码都复制粘贴上图中的权限申请代码,会显得代码很冗余。因此我们可以将动态权限申请的操作封装到工程中的某个 Util 类中,并提供给调用者相应的回调接口。部分核心代码如下:
在这里插入图片描述最后只需要在 BaseActivity或者BaseFragment 中,调用此方法时传入具体实现的 PermissionRequestListener 即可,如下所示:
在这里插入图片描述

三方库使用

同之前的 LogUtils 课时内容一样,对于 Permission 的动态申请也可以借助于开源的三方库来加快开发速度。目前对 Permission 动态申请支持比较好的开源库有以下几个:

Dexter

easypermissions

PermissionsDispatcher

但是三方库的使用也具有一定的隐患,因为不同版本中 Android 系统对 Permission 的处理政策并不完全一致,以后在新版本的系统中很有可能会添加对权限申请更严格的请求策略。比如在 Android 10 中,Android 系统就增加了对外置存储访问的限制,正常情况下我们可以通过以下代码获取外置存储的根路径:
复制

Environment.getExternalStorageDirectory().getAbsolutePath

然后在此目录下创建 App 相应的文件夹缓存数据,但是从 Android10(API 29)开始,App 层已经没有访问此路径的权限,无论你在 AndroidManifest.xml 文件中加上对应的权限还是使用 ActivityCompat.requestPermissions 动态申请到权限都无法实现访问。目前官方提供的临时解决方案就是在 AndroidManifest 清单文件中添加如下设置:
在这里插入图片描述但是如果我们使用的三方库处理动态权限申请操作的话,如果三方库并没有做版本适配,或者做了相应的适配修改,但是我们并没有升级三方库的版本,都会造成在 Android 10 中的设备上处理文件发生异常。

总结

这节课介绍了 Android 系统中申请权限相关的知识点,主要是针对 Android 版本 23 之后的动态申请做了详细介绍,其中有以下几个方法需要掌握:

checkSelfPermission 检查某权限是否已申请。

requestPermissions 主动发送申请权限的请求。

shouldShowRequestPermissionRationale 判断用户之前对申请权限做出的相应动作。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值