Android 动态权限详解
什么是动态权限
首先,从一张图开始此文。
IOS 12 定位权限
Android 权限管理简史
第一阶段:没遮拦
第二阶段:第三方安全 App
例:HTC T328 Android 4.0.2 系统。浏览器扫码功能触发相机调用时,360 手机卫士会弹出权限提示窗,用户可以允许或拒绝授权。注意,此窗由第三方安全软件弹出,非系统级弹窗,跟后面要说的两种弹窗有所区别。
360 手机卫士 弹窗
第三阶段:手机厂商介入
第四阶段:谷歌升级权限管理
例:Pixel2,原生 Android 10;华为 mate8,基于 Android 8.0 的 EMUI8。浏览器扫码功能触发相机调用时,会弹出权限提示窗。此窗,由 App 通知系统弹出,为系统级权限弹窗。
编辑
添加图片注释,不超过 140 字(可选)
第三阶段与第四阶段,同为系统弹出授权弹窗。二者有什么区别吗?
首先,从 UI 上很难判断所弹授权窗为第三阶段或第四阶段。第三阶段弹的系统授权窗大都带有一个倒计时自动拒绝逻辑;第四阶段弹的系统授权窗基本不带自动拒绝逻辑。此点可以粗略判断系统使用的哪种机制。
其次,从原理上。第三阶段的弹窗,为系统监测到 App 在使用危险权限行为自动弹出弹窗。第四阶段的弹窗,为 App 发觉自己没有权限,让系统弹出的弹窗。粗俗的理解,第三阶段,你去朋友家串门,到门口看到大门敞开就直接往里走,触发了红外线报警器,报警器通知了你朋友;第四阶段,你去朋友家串门,到门口发觉门关着,就按下门铃呼叫朋友给你开门。
目前,国内主要处于第三阶段(涵盖 Android4.0~7.1)和第四阶段(涵盖 Android6.0~10),此点将在后文用到。
3
如何应对动态权限特性
方案一:逃避
因为动态权限特性,仅从 Android 6.0 开始拥有,所以,可以简单粗暴的通过不提升 targetSDK(targetSDK<23)的方式,便可不触发此特性。
方案二:实现动态权限****
1. 在使用权限前,检测权限。
首先,我们需要判断自己是否拥有权限。判断时间点为执行需要权限的对应操作前。如我们在获取 IMEI 前,需要判断是否拥有 PHONE_STATE 权限。
我们可以调用 ContextCompat.checkSelfPermission()方法检测授权状态,返回的结果为 PackageManager 中的两个常量:PERMISSION_GRANTED(已授权)和 PERMISSION_DENIED(未授权)。
2. 已授权的情况下,执行你的原有操作。
当已授权时,就可以执行你原有的操作了。代码如下:
那么如果未授权怎么办?
3. 未授权的情况下,申请权限。
如果 App 未获得授权,我们就需要向用户申请授权。可以调用 requestPermissions()方法来请求授权。代码如下:
调用申请授权方法后,ROM 会调起一个系统级弹窗(如下图),这个 dialog 你无法定制。当用户点击同意后,系统会记录,下次再判断权限时就会返回已授权状态;当 App 卸载时,记录会被清除。
以上,就完成了最朴素版的授权逻辑。整体代码如下:
那么弹出申请弹窗之后呢?上面说道,弹出的 dialog 为系统的,我们无法在 dialog 中加代码,但当弹窗被用户点击后,会触发回调,我们在指定函数中处理回调即可。
4. 重写函数,处理授权弹窗的点击结果。
直接在 Activity 或 Fragment 中重写 onRequestPermissionsResult()函数,来处理权限申请结果。requestPermissions()的第三个参数,将在这里被用到。代码如下:
5. 优化授权流程,提高授权几率。
首先,系统授权窗我们无法定制,但是我们可以在这之前做个引导。在触发系统弹窗之前,弹出一个引导 UI,来告知用户将要申请权限,并说明所需权限可带来哪些更好体验。尤其当你申请的权限看似与主要功能并无关系时,比如一个相机 App 如果需要申请定位权限的时候。
综上,动态权限主要实现步骤
在 AndroidManifest 明确我们需要哪些权限。(非动态权限也需要此步)1. 在执行操作前检是否获得对应授权 -> checkSelfPermission()。1. 如果已授权可以继续操作;如果未授权,判断之前是否授权被拒 -> shouldShowRequestPermissionRationale() (非必须操作)a)判断如果没有被拒过,弹出首次授权引导。b)判断如果被据过,弹出非首次授权引导。1. 引导后,申请权限-> requestPermissions()。1. 处理申请的结果信息-> 回调函数 onRequestPermissionsResult()。
系统一共提供如下 4 个函数完成动态权限相关操作。
写到这里,动态授权实现 demo 部分均已完成,实际业务场景肯定比以上流程复杂的多
4.系统版本兼容
以下为目前主流国内厂商对动态权限支持情况。(测试方法:在全新安装未进行过授权操作的情况下,使用 checkSelfPermission()检查 PHONE_STATE、定位、相机权限,返回如果是 PERMISSION_GRANTED,则认为不支持动态权限)
基于 Android6.0 的 ROM 基于 Android7.0 的 ROM|------
5.关于权限弹窗
权限组 icon1. App 名称 1. 申请的权限 1. 允许、拒绝 操作 1. 不再询问选项 1. 多弹窗索引
2.是否存在不再询问选项
关于权限弹窗,针对同一个 App 的同一个权限,有时弹窗不带“拒绝 &不再询问”选项,有时带此选项。如下图是谷歌原生系统、小米 MIUI 系统的两种弹窗对比。这是什么原因呢?Android 原生实现:App 全新安装后首次申请权限,弹窗不带此选项,即图左效果。当用户拒绝授权后,App 下次再申请该权限时,则带此选项,即图右效果。但是,国内部分手机厂商并未遵循此标准,比如华为的 Android 10 之前的系统、OPPO/VIVO 的部分权限,授权弹窗不管是否首次,都带此选项。此为系统行为,App 无法决定。
3.弹窗选项与 App 设置中权限选项对应关系
以原生 Android 10 系统为例:
以基于 Android 9.0 的 MIUI10.4.8 为例:
4.弹窗选项对四个函数的影响。
弹窗弹出,用户操作指定选项后,下次再调用四个函数会有如下现象:
6 权限分类
But,部分 ROM 修改了此逻辑。比如,华为 9.0 以下系统,遵循的是原生系统 Android 8.0 之前的逻辑。但是,华为 9.0 以后系统和小米 6.0 以后系统,都用的比原生系统 Android 8.0 更严格的逻辑。每个权限都需要单独申请权限,而且会单独弹窗要求用户确认。
例如:步骤一:Manifest 中加入了 READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE 步骤二:在程序中只申请了 READ_EXTERNAL_STORAGE 权限,用户同意后步骤三:在程序中申请 WRITE_EXTERNAL_STORAGE 权限结果:会弹出授权弹窗,需要用户再次授权带来问题:相同权限组不同权限的授权弹窗是一毛一样的。这就导致用户很懵逼,明明刚刚授权过了,为什么又要问我一次。
所以,部分手机上,你会发觉有些 App,先后弹出两个访问文件存储的权限弹窗。那是因为写 App 的时候,先后申请了 READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE 权限导致。如何解决?
查看 requestPermissions()方法的第二个参数,为一个数组。也就是说,可以传入一个权限列表。
经测试,如果直接调该方法同时传入 READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE 只会弹出一个授权窗,而且用户同意后可以同时获得两个权限。如果传入不同组权限,则按先后每组弹出一个弹窗。而且,这种单次传入多组权限的情况,弹窗中大都会出现一个 m/n 的编号,以标识弹到第几个,还剩几个。如下图分别是 MIUI10(基于 android9)和 EMUI10(基于 android10)的弹窗样式:
7.写在最后
后期的一些权限策略变化,仅列部分户感知较大的。
IOS 8(2014 年),定位权限选项分为“使用期间”(新增项)、“始终允许”、“不允许”。(减少 App 后台定位)
IOS 10(2016 年),App 访问网络需要授权。
Android 8.0(2017 年),
安装未知来源应用需要申请权限。(App 自升级、三方应用市场、广告 App 安装其他 App 需申请权限)
权限组授权问题修复,上文有提及。
定位权限选项分为“使用期间”(新增项)、“始终允许”、“拒绝”。(减少 App 后台定位)
部分电话、蓝牙、WLAN 的 API,需要申请精确位置权限。
无法再获取手机 IMEI
分区存储强制执行。Download 目录、SD 卡目录访问受限。
对位置、麦克风、相机增加一次性权限许可,见 IOS 13 定位权限(即,如果用户选了一次性许可,重启 App 后需要重新申请权限)。
自动阻止 App 重复的权限请求。也就是说如果用户点击 2 次拒绝授权,那么系统会自动停止询问授权,当然了,用户也可以前往设置中手动调整。 两大平台,都在多个版本中对用户隐私进行了优化,仅定位权限的优化就多次提及。可见,在手机逐渐转化为人体器官之一的今天,IOS 和 Android 两大移动平台对于权限、隐私的管理越发严苛,而且趋同的速度越来越快。估计以后 Android App 想访问网络也需申请授权。但手机厂商自行定制修改 ROM,仍是开发者最头疼的问题。
更多学习资料戳!!!
评论