Android 权限模型概览

Android 权限模型是应用访问受限资源(如相机、位置、联系人)的门禁系统。自 Android 6.0(API 23)起,权限模型从“安装时授予”演变为“运行时授予”,大幅提升了用户对隐私的控制力。本章从原理层面拆解权限分类、保护级别,并对比运行时权限与安装时权限的本质区别。

1.1 权限分类

Android 将权限划分为三类,按声明方式和授予时机区分:

  • 普通权限 (Normal Permission):风险较低,系统自动授予,无需用户交互。例如 INTERNET、ACCESS_NETWORK_STATE。
  • 危险权限 (Dangerous Permission):涉及用户隐私或设备安全,必须运行时明确申请。例如 CAMERA、ACCESS_FINE_LOCATION。
  • 签名权限 (Signature Permission):只有使用相同证书签名的应用才能获取,用于系统级或同厂商应用通信。例如 BIND_ACCESSIBILITY_SERVICE。

1.2 保护级别 (Protection Level)

每个权限在 AndroidManifest.xml 中声明时都包含一个 protectionLevel 属性,它决定了权限的授予策略。常用保护级别如下:

保护级别 含义 授予时机
normal 低风险,系统自动授予 安装时
dangerous 高风险,需用户确认 运行时
signature 仅同签名应用可申请 安装时
signatureOrSystem 系统应用或同签名应用 安装时

在代码中,保护级别常通过 PermissionInfo 的 protectionLevel 字段获取:

// 获取权限信息
PackageManager pm = getPackageManager();
PermissionInfo info = pm.getPermissionInfo("android.permission.CAMERA", 0);
int level = info.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
if (level == PermissionInfo.PROTECTION_DANGEROUS) {
    // 危险权限,需要运行时申请
}

1.3 运行时权限 vs 安装时权限

两者核心差异在于授予时机、用户交互及撤销机制:

对比维度 安装时权限(Android < 6.0) 运行时权限(Android 6.0+)
授予时机 应用安装时一次性授予 应用运行时弹窗请求
用户交互 安装前列表展示,用户确认安装即同意 每次使用前弹窗,用户可拒绝
撤销方式 只能通过卸载或设置中的“清除数据” 用户在设置中随时可关闭
适用于 普通权限 + 签名权限 危险权限
代码影响 调用敏感 API 时无需检查 每次调用前需检查并申请
常见错误:在 Android 6.0+ 设备上,若 targetSdkVersion < 23,即使声明了危险权限,系统也会在安装时自动授予,导致运行时不弹窗。这是许多旧应用在 Android 10+ 上崩溃的根源之一。

1.4 权限声明与清单配置

所有权限(无论哪种类型)都必须在 AndroidManifest.xml 中声明:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" 
        android:maxSdkVersion="32" />
    
    <application ...>
        ...
    </application>
</manifest>

系统在安装时扫描 <uses-permission> 标签,并依据保护级别决定后续策略。注意 maxSdkVersion 可限制该权限在高于某 API 版本后不再生效,适用于位置权限等逐渐被细化的场景。

性能与优化提示:运行时权限请求涉及 Activity 生命周期、Dialog 弹窗、用户等待。若一个页面同时请求多个危险权限,建议使用 requestPermissions 批量申请,并合理处理 onRequestPermissionsResult 回调,避免频繁弹窗导致用户体验下降。
Android 权限分类与保护级别映射 Android 权限 普通权限 (Normal) 危险权限 (Dangerous) 签名权限 (Signature) normal dangerous signature / signatureOrSystem 安装时授予 运行时授予 安装时授予 关键结论 危险权限对应 dangerous 保护级别,必须运行时申请;普通/签名权限对应 normal/signature 保护级别,安装时自动授予。 注:signatureOrSystem 级别仅适用于系统预置应用,第三方应用无法声明。

1.5 常见错误与调试

  • 权限未声明:运行时报 SecurityException,Logcat 中可见 Permission Denial。始终检查清单文件。
  • targetSdkVersion 过低:即使运行时申请也会被系统忽略(自动授予),导致在 Android 11+ 出现兼容性问题。
  • 权限组误解:危险权限按组管理,申请组内任一权限,用户同意后该组其他权限自动授予。例如申请 CAMERA 时,如果同一个组内有 RECORD_AUDIO(实际上它们不在同一组),需注意分组查看。
调试命令:使用 ADB 列出应用已授予的权限:
adb shell dumpsys package com.example.myapp | grep -A 100 "grantedPermissions"
使用 pm revoke 模拟撤销权限:
adb shell pm revoke com.example.myapp android.permission.CAMERA