在开发过程中,我们时常会声明很多权限。都是熟悉的。
我们哪个module需要这个权限,就在哪个modue的AndroidManifest中声明。
权限可以到处声明,最终的AndroidManifest会合并这个重复声明的权限,所以,相同的权限只会被声明一次。
简述权限声明
Android权限定义的位置:frameworks/base/core/res/AndroidManifest.xml
附上一个git地址AOSP7.1 frameworks
你会发现有这样的结构
<permission android:name="android.permission.READ_CONTACTS"
android:permissionGroup="android.permission-group.CONTACTS"
android:label="@string/permlab_readContacts"
android:description="@string/permdesc_readContacts"
android:protectionLevel="dangerous" />
android:name
权限名称。
这就是App的AndroidManifest.xml中声明的部分。
<uses-permission android:name="android.permission.READ_CONTACTS" />
android:permissionGroup
权限分类。
会把差不多的权限 分到一起。权限所属权限组的名称,并且需要在这个或其他应用中使用标签提前声明该名称,如果没有声明,该权限就不属于该组。
权限分组 | 权限 |
---|---|
android.permission-group.CONTACTS | android.permission.READ_CONTACTS android.permission.WRITE_CONTACTS android.permission.GET_ACCOUNTS |
android.permission-group.CALENDAR | android.permission.READ_CALENDAR android.permission.WRITE_CALENDAR |
我们看一下AndroidManifest.xml源码
<!-- Allows an application to read the user's calendar data.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_CALENDAR"
android:permissionGroup="android.permission-group.CALENDAR"
android:label="@string/permlab_readCalendar"
android:description="@string/permdesc_readCalendar"
android:protectionLevel="dangerous" />
<!-- Allows an application to write the user's calendar data.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.WRITE_CALENDAR"
android:permissionGroup="android.permission-group.CALENDAR"
android:label="@string/permlab_writeCalendar"
android:description="@string/permdesc_writeCalendar"
android:protectionLevel="dangerous" />
android:label
提示给用户的权限名。就是一个简介的描述
以android.permission.READ_CALENDAR为例
<string name="permlab_readCalendar">read calendar events plus confidential information</string>
android:description
提示给用户的权限描述。详细版本。
android:protectionLevel
分4个级别:normal、dangerous、signature、signatureOrSystem;官网上的解释。
-
normal
普通风险。也是最低风险,安装应用不会提示,默认授权,系统直接默认该应用有此权限; -
dangerous
风险较高。但任何App都可以申请。安装时需要确认才能使用。一般不会默认授权。注:拥有此权限可能会访问用户私人数据或者控制设备,给用户带来负面影响;
-
signature
这种权限级别,只有当发请求的应用和接收此请求的应用使用同一签名文件,并且声明了该权限才会授权,并且是默认授权,不会提示用户授权 -
signatureOrSystem
仅当申请权限的应用程序位于相同的Android系统镜像中,或申请权限的应用程序和声明该权限的程序拥有相同签名时,才会赋权。
这种权限应该尽量避免使用,偏向系统级。
注意:
- Android系统中声明的权限有普通权限(normal)和危险权限(dangerous)。
- normal权限不涉及用户隐私,系统会自动赋予权限;
- dangeerous权限涉及用户隐私,需要获取用户的授权。
附录权限列表
需要注意的:与权限相关的Api差异
- 如果App在targetSDKVersion 小于 23(从sdk 1到sdk 22)的版本中,则系统安装时就会赋予所有需要的权限。
- 从 SDK 23开始,用户可以控制 应用的权限。
注意
在targetSDKVersion = Android O(8.0)之前,如果App在运行时请求权限并被授予该权限,系统会将 属于 同一权限组 且 AndroidManifest中注册 的其他权限也一起授予。
在targetSDKVersion = Android O(8.0)中,系统就只授予应用明确请求的权限。
用户一旦授予过某个权限之后,以后就不需要再提示用户了。
除非用户去系统 - 设置 - 应用 中找到该App 再次关掉某些权限。
权限管理的组件化思维
软件架构最重要的基础思维:聚合、解耦。
当然这也是组件化思维的重点。
操作方法
- 将normal级别的权限都放到Base Module中
- 将dangerous级别的权限放到各自module中独立申请。
考量:
- 当添加 \ 删除 单一模块时,隐私权限申请也会 随之 移除,就能做到最大程度的权限解耦。
- 权限解耦后,可以有效减少 权限合并检测的耗时。(所以,不能把权限随意放,或者 所有的权限 全部 转交到 功能module)
权限申请三方框架
这里主要是AndPermission和RxPermission。
后续我们来分析下这两者的优劣。
配合路由拦截打造更好的 体验
场景:
我们的某个场景,可能要申请一些权限。我们可能会通过Router打开。
将权限申请放在 Activity中执行,容易发生帧数降低,产生黑屏时间延长,用户体验变差等问题。
处理方法:
我使用的是alibaba的ARouter。
- 路由会在跳转前,遍历intercept。
- 通过ARouter的拦截,可以提前处理 权限申请。就可以有效避免切换到新页面之后,同时弹出权限申请框,带来的负面影响。
需要注意
- 权限申请需要一个activity,这里是强引用,你需要注意泄漏问题。我们会在下个回合将Application部分