11# 权限请求框架
22
3- > 码云地址:[ Gitee] ( https://gitee.com/getActivity/XXPermissions )
3+ * 码云地址:[ Gitee] ( https://gitee.com/getActivity/XXPermissions )
44
5- > [ 点击此处下载Demo] ( XXPermissions.apk ) ,[ 博文地址:一句代码搞定权限请求,从未如此简单] ( https://www.jianshu.com/p/c69ff8a445ed )
5+ * [ 点击此处下载Demo] ( XXPermissions.apk ) ,[ 博文地址:一句代码搞定权限请求,从未如此简单] ( https://www.jianshu.com/p/c69ff8a445ed )
66
7- > 另外想对 Android 6.0 权限需要深入了解的,可以看这篇文章[ Android 6.0 运行权限解析] ( https://www.jianshu.com/p/6a4dff744031 )
7+ * 另外想对 Android 6.0 权限需要深入了解的,可以看这篇文章[ Android 6.0 运行权限解析] ( https://www.jianshu.com/p/6a4dff744031 )
88
99![ ] ( picture/1.jpg ) ![ ] ( picture/2.jpg ) ![ ] ( picture/3.jpg )
1010![ ] ( picture/4.jpg ) ![ ] ( picture/5.jpg ) ![ ] ( picture/6.jpg )
1414``` groovy
1515dependencies {
1616 // 权限请求框架:https://github.com/getActivity/XXPermissions
17- implementation 'com.hjq:xxpermissions:9.0 '
17+ implementation 'com.hjq:xxpermissions:9.2 '
1818}
1919```
2020
@@ -69,6 +69,8 @@ public class XxxActivity extends AppCompatActivity {
6969 if (XXPermissions . hasPermission(this , Permission . RECORD_AUDIO ) &&
7070 XXPermissions . hasPermission(this , Permission . Group . CALENDAR )) {
7171 toast(" 用户已经在权限设置页授予了录音和日历权限" );
72+ } else {
73+ toast(" 用户没有在权限设置页授予权限" );
7274 }
7375 }
7476 }
@@ -77,43 +79,22 @@ public class XxxActivity extends AppCompatActivity {
7779
7880#### 关于权限监听回调参数说明
7981
80- * 我们都知道,如果用户全部授予只会调用 hasPermission 方法,如果用户全部拒绝只会调用 noPermission 方法。
82+ * 我们都知道,如果用户全部授予只会调用 ` hasPermission ` 方法,如果用户全部拒绝只会调用 ` noPermission ` 方法。
8183
8284* 但是还有一种情况,如果在请求多组权限的情况下,这些权限不是被全部授予或者全部拒绝了,而是部分授权部分拒绝这种情况,框架会如何处理回调呢?
8385
84- * 框架会先调用 noPermission 方法,再调用 hasPermission 方法。其中我们可以通过 hasPermission 方法中的 all 参数来判断权限是否全部授予了。
86+ * 框架会先调用 ` noPermission ` 方法,再调用 ` hasPermission ` 方法。其中我们可以通过 ` hasPermission ` 方法中的 ` all ` 参数来判断权限是否全部授予了。
8587
86- * 如果想知道回调中的某个权限是否被授权或者拒绝,可以调用 List 类中的 contains(Permission.XXX) 方法来判断这个集合中是否包含了这个权限。
88+ * 如果想知道回调中的某个权限是否被授权或者拒绝,可以调用 ` List ` 类中的 ` contains(Permission.XXX) ` 方法来判断这个集合中是否包含了这个权限。
8789
88- #### 框架亮点
89-
90- * 第一款适配 Android 11 的权限请求框架,适配过程几乎零成本
91-
92- * 简洁易用,采用链式调用的方式,使用只需一句代码
93-
94- * 支持单个权限、多个权限、单个权限组、多个权限组请求
95-
96- * 支持大部分国产手机直接跳转到具体的权限设置页面
97-
98- * 支持申请安装包、悬浮窗、通知栏、系统设置权限
99-
100- * 支持所有危险权限的申请,包含 6.0 之后出现的新权限
101-
102- * 向下兼容属性,新权限在旧系统可以正常申请,无需调用者适配
10390
104- * 本框架不依赖任何第三方库,整个框架大小不到 20 kb(在同类框架中排名第一)
105-
106- * 如果申请的权限没有在清单文件中注册会抛出异常(仅在 Debug 模式下判断)
91+ #### Android 11 定位权限适配
10792
108- * 如果申请的权限和项目 targetSdkVersion 不符合要求会抛出异常(仅在 Debug 模式下判断)
93+ * 在 Android 10 上面,定位被划分为前台权限(精确和模糊)和后台权限,而到了 Android 11 上面,需要分别申请这两种权限,如果同时申请这两种权限会惨遭系统无情拒绝,连权限申请对话框都不会弹,直接被系统拒绝,导致定位权限申请失败。
10994
110- #### Android 11 定位适配
95+ * 如果你使用的是 XXPermissions 最新版本,那么恭喜你,直接将前台定位权限和后台定位权限全部传给框架即可,框架已经自动帮你把这两种权限分开申请了,整个适配过程零成本。
11196
112- * 在 Android 10 上面,定位被划分为前台权限(精确和模糊)和后台权限,而到了 Android 11 上面,需要分别申请这两种权限,如果同时申请这两种权限会惨遭系统无情拒绝,也就是连权限申请对话框都不会弹的那种拒绝。
113-
114- * 如果你使用的是 XXPermissions 最新版本,那么恭喜你,直接将前台和后台传给框架即可,框架已经自动帮你把这两种权限分开申请了,整个适配过程零成本。
115-
116- #### Android 11 存储适配
97+ #### Android 11 存储权限适配
11798
11899* 如果你的项目需要适配 Android 11 存储权限,那么需要先将 targetSdkVersion 进行升级
119100
@@ -182,11 +163,10 @@ XXPermissions.with(MainActivity.this)
182163| 功能及细节对比 | [ XXPermissions] ( https://github.com/getActivity/XXPermissions ) | [ AndPermission] ( https://github.com/yanzhenjie/AndPermission ) | [ RxPermissions] ( https://github.com/tbruyelle/RxPermissions ) | [ PermissionsDispatcher] ( https://github.com/permissions-dispatcher/PermissionsDispatcher ) | [ EasyPermissions] ( https://github.com/googlesamples/easypermissions ) | [ PermissionX] ( https://github.com/guolindev/PermissionX )
183164| :--------: | :------------: | :------------: | :------------: | :------------: | :------------: | :------------: |
184165| 对应版本 | 9.0 | 2.0.3 | 0.12 | 4.8.0 | 3.0.0 | 1.4.0 |
185- | aar 包大小 | [ 20 KB] ( https://bintray.com/getactivity/maven/xxpermissions#files/com/hjq/xxpermissions ) | [ 127 KB] ( https://mvnrepository.com/artifact/com.yanzhenjie/permission ) | [ 28 KB] ( https://jitpack.io/#com.github.tbruyelle/rxpermissions ) | [ 22 KB] ( https://bintray.com/hotchemi/org.permissionsdispatcher/permissionsdispatcher#files/org/permissionsdispatcher/permissionsdispatcher ) | [ 48 KB] ( https://bintray.com/easygoogle/EasyPermissions/easypermissions#files/pub/devrel/easypermissions ) | [ 32 KB] ( https://bintray.com/guolindev/maven/permissionx#files/com/permissionx/guolindev/permissionx ) |
186166| minSdk 要求 | API 11+ | API 14+ | API 14+ | API 14+ | API 14+ | API 15+ |
187- | targetSdk 要求 | API 23+ | API 29+ | API 29+ | API 29+ | API 30+ | API 30+ |
188- | class 文件数量 | 8 个 | 110 个 | 3 个 | 37 个 | 15 个 | 16 个 |
189- | 是否有依赖 | 无任何依赖 | 依赖 Support | 依赖 AndroidX | 依赖 AndroidX | 依赖 AndroidX | 依赖 AndroidX |
167+ | class 文件数量 | 7 个 | 110 个 | 3 个 | 37 个 | 15 个 | 16 个 |
168+ | aar 包大小 | [ 19 KB ] ( https://bintray.com/getactivity/maven/xxpermissions#files/com/hjq/xxpermissions ) | [ 127 KB ] ( https://mvnrepository.com/artifact/com.yanzhenjie/permission ) | [ 28 KB ] ( https://jitpack.io/#com.github.tbruyelle/rxpermissions ) | [ 22 KB ] ( https://bintray.com/hotchemi/org.permissionsdispatcher/permissionsdispatcher#files/org/permissionsdispatcher/permissionsdispatcher ) | [ 48 KB ] ( https://bintray.com/easygoogle/EasyPermissions/easypermissions#files/pub/devrel/easypermissions ) | [ 32 KB ] ( https://bintray.com/guolindev/maven/permissionx#files/com/permissionx/guolindev/permissionx ) |
169+ | 是否有依赖 | 无任何依赖 | 依赖 Support | 依赖 AndroidX 和 RxJava | 依赖 AndroidX | 依赖 AndroidX | 依赖 AndroidX |
190170| 安装包权限 | 支持 | 支持 | 不支持 | 不支持 | 不支持 | 不支持 |
191171| 悬浮窗权限 | 支持 | 支持 | 不支持 | 不支持 | 不支持 | 不支持 |
192172| 通知栏权限 | 支持 | 出现崩溃 | 不支持 | 不支持 | 不支持 | 不支持 |
@@ -195,7 +175,58 @@ XXPermissions.with(MainActivity.this)
195175| Android 10.0 三个新危险权限 | 已适配 | 部分适配 | 未适配 | 已适配 | 未适配 | 已适配 |
196176| Android 11 新版存储权限 | 已适配 | 未适配 | 未适配 | 未适配 | 未适配 | 未适配 |
197177| Android 11 新版定位策略 | 已适配 | 未适配 | 未适配 | 未适配 | 未适配 | 未适配 |
198- | 国产手机权限设置界面 | 已适配 | 已适配 | 未适配 | 未适配 | 未适配 | 未适配 |
178+
179+ #### 框架亮点
180+
181+ * 第一款适配 Android 11 的权限请求框架,适配过程几乎零成本
182+
183+ * 简洁易用,采用链式调用的方式,使用只需一句代码
184+
185+ * 支持单个权限、多个权限、单个权限组、多个权限组请求
186+
187+ * 支持申请安装包、悬浮窗、通知栏、系统设置权限
188+
189+ * 支持所有危险权限的申请,包含 6.0 之后出现的新权限
190+
191+ * 向下兼容属性,新权限在旧系统可以正常申请,无需调用者适配
192+
193+ * 本框架不依赖任何第三方库,整个框架大小不到 20 kb(在同类框架中排名第一)
194+
195+ * 如果申请的权限没有在清单文件中注册会抛出异常(仅在 Debug 模式下判断)
196+
197+ * 如果申请的权限和项目 targetSdkVersion 不符合要求会抛出异常(仅在 Debug 模式下判断)
198+
199+ #### 为什么不兼容 Android 6.0 以下的权限申请?
200+
201+ * 因为 Android 6.0 以下的权限管理是手机厂商做的,那个时候谷歌还没有统一权限管理的方案,所以就算我们的应用没有适配也不会有任何问题,因为手机厂商对这块有自己的处理,但是有一点是肯定的,就算用户拒绝了授权,也不会导致应用崩溃,只会返回空白的通行证。
202+
203+ * 如果 XXPermissions 做这块的适配也可以做到,通过反射系统服务 AppOpsManager 类中的字段即可,但是并不能保证权限判断的准确性,可能会存在一定的误差,其次是适配的成本太高,因为国内手机厂商太多,对这块的改动参差不齐。
204+
205+ * 考虑到 Android 6.0 以下的设备占比很低,后续也会越来越少,会逐步退出历史的舞台,所以我的决定是不对这块做适配。
206+
207+ #### 新版 XXPermissions 为什么移除了国产手机权限设置页功能?
208+
209+ * XXPermissions 9.0 及之前是有存在这一功能的,但是我在后续的版本上面将这个功能移除了,原因是有很多人跟我反馈这个功能其实存在很大的缺陷,例如在一些华为新机型上面可能跳转的页面不是应用的权限设置页,而是所有应用的权限管理列表界面。
210+
211+ * 其实不止华为有问题,小米同样有问题,有很多人跟我反馈过同一个问题,XXPermissions 跳转到国产手机权限设置页,用户正常授予了权限之后返回仍然检测到权限仍然是拒绝的状态,这个问题反馈的次数很多,但是迟迟不能排查到原因,终于在最后一次得到答案了,[ 有人] ( https://github.com/getActivity/XXPermissions/issues/38 ) 帮我排查到是 miui 优化开关的问题(小米手机 ---> 开发者选项 ---> 启用 miui 优化),那么问题来了,这个开关有什么作用?是如何影响到 XXPermissions 的?
212+
213+ * 首先这个问题要从 XXPermissions 跳转到国产手机设置页的原理讲起,从谷歌提供的原生 API 我们最多只能跳转到应用详情页,并不能直接跳转到权限设置页,而需要用户在应用详情页再次点击才能进入权限设置页。如果从用户体验的角度上看待这个问题,肯定是直接跳转到权限设置页是最好的,但是这种方式是不受谷歌支持的,当然也有方法实现,网上都有一个通用的答案,就是直接捕获某个品牌手机的权限设置页 `Activity` 包名然后进行跳转。这种想法的起点是好的,但是存在许多问题,并不能保证每个品牌的所有机型都能适配到位,手机产商更改这个 `Activity` 的包名的次数和频率比较高,在最近发布的一些新的华为机型上面几乎已经全部失效,也就是 `startActivity` 的时候会报 `ActivityNotFoundException` 或 `SecurityException ` 异常,当然这些异常是可以被捕捉到的,但是仅仅只能捕获到崩溃,一些非崩溃的行为我们并不能从中得知和处理,例如我刚刚讲过的华为和小米的问题,这些问题并不能导致崩溃,但是会导致功能出现异常。
214+
215+ * 而 miui 优化开关是小米工程师预留的切换 miui 和原生的功能开关,例如在这个开关开启的时候,在应用详情页点击权限管理会跳转到小米的权限设置页,如果这个开关是关闭状态(默认是开启状态),在应用详情页点击权限管理会跳转到谷歌原生的权限设置页,具体效果如图:
216+
217+ ![ ] ( picture/miui_1.jpg )
218+
219+ ![ ] ( picture/miui_2.jpg )
220+
221+ * 最大的问题在于:这两个界面是不同的 Activity,一个是小米定制的权限设置页,第二个是谷歌原生的权限设置页,当 miui 优化开启的时候,在小米定制的权限设置页授予权限才能有效果,当这个 miui 优化关闭的时候,在谷歌原生的权限设置页授予权限才能有效果。而跳转到国产手机页永远只会跳转到小米定制的那个权限设置页,所以就会导致当 miui 优化关闭的时候,使用代码跳转到小米权限设置页授予了权限之后返回仍然显示失败的问题。
222+
223+ * 有人可能会说,解决这个问题的方式很简单,判断 miui 优化开关,如果是开启状态就跳转到小米定制的权限设置页,如果是关闭状态就跳转到谷歌原生的权限设置页,这样不就可以了?其实这个解决方案我也有尝试过,我曾委托联系到在小米工作的 miui 工程师,也有人帮我反馈这个问题给小米那边,最后得到答复都是一致的。
224+
225+ ![ ] ( picture/miui_3.jpg )
226+
227+ ![ ] ( picture/miui_4.jpg )
228+
229+ * 这个功能的出发点是好的,但是我们没办法做好它,经过慎重考虑,决定将这个功能在 XXPermissions 9.2 版本上面移除。
199230
200231#### 作者的其他开源项目
201232
0 commit comments