2. Android权限体系概览
Android 权限体系是应用安全模型的基石。它决定了应用能访问哪些系统资源、用户数据以及硬件能力。理解权限的分类、保护级别、权限组以及正常权限、危险权限和特殊权限之间的差异,是进行权限申请、运行时授权和系统服务集成的前提。本节将从整体结构出发,逐层拆解 Android 权限体系的核心概念。
一、权限的基本分类与保护级别
Android 中的每一个权限都由系统在框架层定义,并通过 AndroidManifest.xml 进行声明。权限本身并不是孤立存在的,它带有明确的保护级别(protectionLevel),用于描述该权限的授予方式和风险程度。常见的保护级别包括:
- normal(正常):风险较低,系统在安装时自动授予,无需用户交互。
- dangerous(危险):涉及用户隐私或敏感数据,必须在运行时向用户动态申请。
- signature(签名):只有与声明该权限的应用使用相同签名的应用才能获得。
- signatureOrSystem:签名匹配或位于系统镜像中的应用才能获得,通常用于系统级服务。
- privileged:系统特权应用可获得的权限,常用于预置系统应用。
保护级别决定了权限的“门槛”。普通应用开发者最常接触的是 normal 和 dangerous 两类,而 signature 和 privileged 更多出现在系统定制、ROM 开发或系统服务集成场景中。
二、权限组:用户视角的归类方式
为了简化用户理解,Android 将功能相近的权限归入同一个权限组(permission group)。例如,CAMERA 权限属于 android.permission-group.CAMERA,READ_CONTACTS 和 WRITE_CONTACTS 属于 android.permission-group.CONTACTS。权限组的主要作用是:
- 在运行时权限对话框中,系统以“组”为单位向用户展示授权请求,降低理解成本。
- 同一权限组内的权限在部分 Android 版本中可能被批量授予或拒绝。
- 权限组是面向用户的抽象,而权限本身才是系统实际校验的对象。
三、正常权限与危险权限
正常权限(Normal Permissions)是指那些不会直接威胁用户隐私或设备安全的权限。例如 INTERNET、ACCESS_NETWORK_STATE、SET_WALLPAPER 等。这类权限在应用安装时由系统自动授予,开发者只需在清单中声明即可使用,无需在代码中动态申请。
危险权限(Dangerous Permissions)则涉及用户的敏感数据或关键硬件能力,例如读取联系人、访问相机、获取位置、读写外部存储等。危险权限必须在运行时通过 requestPermissions() 或 Activity Result API 向用户发起申请,并且用户可以随时在系统设置中撤销授权。常见的危险权限包括:
android.permission.CAMERAandroid.permission.ACCESS_FINE_LOCATIONandroid.permission.READ_CONTACTSandroid.permission.READ_EXTERNAL_STORAGEandroid.permission.RECORD_AUDIO
下面是一个典型的运行时权限申请代码片段:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.CAMERA},
REQUEST_CODE_CAMERA
);
} else {
openCamera();
}
从 Android 6.0(API 23)开始,危险权限的运行时申请成为强制要求。开发者不能假设权限在安装时已经获得,必须在每次使用前检查并申请。
四、特殊权限:需要用户到设置页手动开启
除了正常权限和危险权限,Android 还存在一类特殊权限(Special Permissions)。这类权限通常涉及系统级能力或对用户体验影响较大的操作,不能通过普通的运行时权限对话框授予,而是需要引导用户跳转到系统设置页面手动开启。常见的特殊权限包括:
SYSTEM_ALERT_WINDOW:悬浮窗权限,用于在其他应用上层显示内容。WRITE_SETTINGS:修改系统设置权限。PACKAGE_USAGE_STATS:应用使用统计权限。REQUEST_INSTALL_PACKAGES:安装未知来源应用权限。MANAGE_EXTERNAL_STORAGE:管理所有文件权限(Android 11 及以上)。
特殊权限的申请流程与危险权限不同,通常需要先检查是否已授权,再通过 Intent 跳转到对应的设置页:
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(
Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName())
);
startActivityForResult(intent, REQUEST_CODE_OVERLAY);
}
五、权限体系整体关系图解
为了更直观地理解权限分类、保护级别、权限组以及正常权限、危险权限和特殊权限之间的关系,下面用一张结构关系图进行梳理:
六、常见误区与复盘
在实际开发中,围绕权限体系容易出现以下几类误区:
- 认为在清单中声明了就一定拥有权限。对于危险权限,清单声明只是“声明意图”,真正能否使用取决于运行时是否获得用户授权。
- 混淆权限组与具体权限。用户授予了某个权限组中的一项权限,并不代表该组内所有权限都被授予。系统校验时仍然以具体权限为准。
- 忽略特殊权限的跳转流程。特殊权限不能通过
requestPermissions()申请,必须使用对应的 Settings Intent,并处理用户返回后的状态检查。 - 未处理权限被撤销的情况。用户可以在系统设置中随时撤销危险权限,应用在每次使用前都应重新检查权限状态。
- 在低版本设备上直接调用高版本 API。不同 Android 版本对权限的要求不同,应做好版本判断和兼容处理。
七、权限分类速查清单
| 权限类型 | 保护级别 | 授予方式 | 典型示例 | 是否需要运行时申请 |
|---|---|---|---|---|
| 正常权限 | normal | 安装时自动授予 | INTERNET、ACCESS_NETWORK_STATE | 否 |
| 危险权限 | dangerous | 运行时用户授权 | CAMERA、ACCESS_FINE_LOCATION | 是 |
| 签名权限 | signature | 相同签名自动授予 | 系统内部自定义权限 | 否 |
| 特殊权限 | signature/privileged | 跳转设置页手动开启 | SYSTEM_ALERT_WINDOW、WRITE_SETTINGS | 是(设置页) |
掌握上述分类与保护级别,是后续学习运行时权限申请、权限回调处理以及系统服务集成的必要基础。在实际项目中,建议将权限检查封装为统一工具类,结合版本判断和用户引导,形成规范化的权限处理流程。