1. 权限基础:Android权限模型演进、普通权限与危险权限、权限组概念
各位同学好,我是老张。今天咱们聊聊Android权限的基础知识。说实话,权限这块我踩过的坑真不少——早期项目里因为权限问题导致App在某个厂商手机上直接闪退,那叫一个尴尬。嗯,咱们从最基础的开始讲起。
1.1 Android权限模型的演进
Android的权限模型,说白了就是一套「App能干什么、不能干什么」的规则。我刚开始做Android开发那会儿,还是Android 4.4的时代,那时候权限管理相当粗放。
核心演进路线:
- Android 1.0 - 5.0(安装时授权):用户安装App时,系统会列出所有权限。你点「安装」,就等于一次性全同意了。之后App想干嘛就干嘛,没法撤销。
- Android 6.0(运行时权限诞生):这是里程碑式的变化。敏感权限必须在运行时弹窗询问用户,用户可以选择「允许」或「拒绝」。我记得当时适配这个改动,整个团队加班了两周。
- Android 10 - 13(精细化管控):新增「仅在使用中允许」「本次允许」「后台位置」等选项。权限越来越细,用户控制力越来越强。
为什么会这样演进?你想想看,早期那种「一刀切」的方式,用户根本不知道App在后台干了什么。有些流氓App装上就开始偷通讯录,用户毫无办法。所以Google不得不一步步收紧权限。
1.2 普通权限与危险权限
Android把权限分成了两大类:普通权限(Normal Permissions)和危险权限(Dangerous Permissions)。这个分类直接决定了你的App需不需要处理运行时弹窗。
| 类型 | 特点 | 举例 | 是否需要运行时申请 |
|---|---|---|---|
| 普通权限 | 不直接威胁用户隐私,系统自动授予 | INTERNET、ACCESS_NETWORK_STATE、VIBRATE | 否,只需在Manifest声明 |
| 危险权限 | 涉及用户隐私数据或敏感功能 | CAMERA、READ_CONTACTS、ACCESS_FINE_LOCATION | 是,必须运行时弹窗申请 |
我的经验:普通权限虽然不用运行时申请,但千万别在Manifest里乱写。我曾经见过一个项目,把几十个普通权限全列上了,结果用户一看权限列表直接卸载了App。只声明你真正需要的权限,这是基本原则。
危险权限的申请流程,我建议你这样理解:
- 检查权限是否已被授予(checkSelfPermission)
- 如果未授予,判断是否需要展示解释说明(shouldShowRequestPermissionRationale)
- 发起权限请求(requestPermissions)
- 在回调中处理用户的选择(onRequestPermissionsResult)
// 一个标准的危险权限申请代码片段
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
// 权限未授予,需要申请
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CAMERA)) {
// 这里可以展示一个解释说明,告诉用户为什么需要这个权限
showPermissionRationaleDialog();
} else {
// 直接申请权限
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA},
REQUEST_CODE_CAMERA);
}
} else {
// 权限已授予,直接执行相机操作
openCamera();
}
注意:千万不要在onRequestPermissionsResult里只处理「允许」的情况。用户拒绝后,你的App应该能优雅降级,而不是直接崩溃。我曾经见过一个App,用户拒绝位置权限后,整个地图页面白屏——这就是典型的没做好异常处理。
1.3 权限组概念
权限组(Permission Group)是Android用来管理同类权限的一种机制。说白了,就是把功能相似的权限归到一个组里。比如「通讯录」这个组,包含了READ_CONTACTS和WRITE_CONTACTS两个权限。
权限组的核心规则:
- 如果用户同意了某个权限组里的一个权限,系统会自动授予该组里的所有权限(仅限同组且已在Manifest中声明的)
- 如果用户拒绝了某个权限,再次申请同组其他权限时,系统会直接拒绝,不会弹窗
举个例子:你的App声明了READ_CONTACTS和WRITE_CONTACTS。用户同意了READ_CONTACTS,那么WRITE_CONTACTS也会自动被授予,不需要再次弹窗。反过来,如果用户拒绝了READ_CONTACTS,你再申请WRITE_CONTACTS,系统会直接回调拒绝,连弹窗都不显示。
重要提醒:这个规则在Android 11之后有所变化。Google开始弱化权限组的概念,建议开发者不要依赖「同组自动授权」的行为。我建议你每个权限都独立申请、独立检查,别偷懒。
1.4 知识体系总览
下面这张图是我自己整理的权限基础知识结构,你可以对照着理解:
这张图把权限基础的三块内容串起来了。从上往下看:先了解权限模型怎么演进的,再搞清楚普通和危险权限的区别,最后理解权限组的作用。我个人习惯把这张图贴在工位上,每次做权限适配时扫一眼,思路就很清晰。
避坑指南:我曾经在适配Android 12时,发现某个厂商的ROM把「存储权限」从危险权限改成了普通权限。结果我的App按照标准流程申请,反而出了问题。所以记住:不要假设所有设备的行为都完全一致,一定要做充分的兼容性测试。
好了,权限基础就讲到这里。记住三个关键词:演进、分类、分组。搞懂这些,后面学运行时权限申请流程就会轻松很多。
公众号:蓝海资料掘金营,微信deep3321