Normal Permission — Android中系统无需询问用户即可自动授予的权限类别。根据Android Developer Documentation, 2024,普通权限具有ProtectionLevel normal,与危险权限不同,不需要运行时对话框。它们涵盖对互联网、网络状态和振动的访问,不会对用户的机密数据造成风险。
要点
Normal Permission — 具有ProtectionLevel normal的Android系统权限类型,在安装时自动授予应用程序。开发者无需编写请求代码 — 只需在AndroidManifest.xml中指定权限即可。用户看不到对话框,也无法单独撤销normal permission,只能通过完全删除应用程序来实现。
Android系统将普通权限归类为低风险 — 它们不提供对个人数据、摄像头或麦克风的访问。典型示例:访问互联网、控制振动、读取Wi-Fi状态。根据Android Security Model (2024),所有系统权限中约40%属于normal类别。
重要属性 — 普通权限不能在运行时通过Settings撤销。如果用户想要禁止访问,唯一的方法是删除应用程序。开发者在架构中应考虑这一点,但对用户而言,这种方法简化了交互:首次启动时没有任何对话框。
普通权限和危险权限的划分出现在Android 6.0 Marshmallow(API 23)中。在此版本之前,所有权限都在安装时请求 — 用户看到一个统一的列表,并整体接受或拒绝。 Normal Permission 为低风险操作保留了这种模式,而Dangerous则转向了运行时请求。这一改变改善了用户体验,同时提高了安全性。
许多Android系统API需要显式指定普通权限,即使访问是自动的。例如,ConnectivityManager类需要ACCESS_NETWORK_STATE,VibratorService需要VIBRATE,WifiManager需要ACCESS_WIFI_STATE。如果没有声明相应的uses-permission,调用这些API将导致SecurityException。
ProtectionLevel normal — Android权限系统中的最低保护级别。具有此级别的权限在清单中声明,系统在安装时检查声明,无需用户干预即可授予访问权限。不显示任何UI元素,不调用任何回调。
检查机制在PackageManager级别工作。在安装APK时,系统扫描所有uses-permission标签,通过与permissions.xml文件中的系统定义进行比较来确定每个权限的保护级别,对于normal-level只需注册访问。该过程只需毫秒,不需要与用户界面交互。
授予算法如下:
用户无法通过界面撤销普通权限。在应用程序设置的权限部分,只显示危险权限。这与iOS形成对比,在iOS中,无论功能的敏感程度如何,每个权限都需要单独确认。
Normal和Dangerous Permission — Android中两种相反的保护类别。主要区别在于授予方式:普通权限在安装时自动授予,危险权限需要通过运行时对话框获得明确同意。这种差异从Android 6.0 Marshmallow版本开始就内置于安全架构中。
关键特性对比:
| 特性 | Normal Permission | Dangerous Permission |
|---|---|---|
| ProtectionLevel | normal | dangerous |
| 用户请求 | 不需要 | 运行时对话框必需 |
| 撤销可能性 | 否,只能删除应用程序 | 是,随时通过设置撤销 |
| 代码检查 | 始终为PERMISSION_GRANTED | checkSelfPermission必需 |
| 示例 | INTERNET, VIBRATE, ACCESS_NETWORK_STATE | CAMERA, RECORD_AUDIO, ACCESS_FINE_LOCATION |
用户在Normal Permission请求中看不到任何对话框。如果应用程序需要INTERNET — 它会静默获取。对于Dangerous Permission,系统会显示一个模态对话框,描述所请求的访问权限。用户按下Allow或Deny,之后可以随时通过Settings撤销权限。这是决定界面开发策略的关键UX差异。
在所有访问不涉及敏感数据的情况下,应使用Normal权限。ACCESS_NETWORK_STATE用于检查连接,VIBRATE用于触觉反馈,INTERNET用于HTTP请求 — 这些都是普通权限。在normal足够的情况下使用dangerous级别是糟糕的做法,会创建不必要的对话框并降低用户对应用程序的信任。
Android定义了数十个普通权限,每个对应一个特定的系统功能。所有权限都可以通过Manifest.permission类的常量访问。以下是应用程序开发中最常用的权限列表。
| 常量 | 访问 | 描述 |
|---|---|---|
| INTERNET | 网络 | 打开网络套接字进行HTTP请求 |
| ACCESS_NETWORK_STATE | 网络 | 获取有关网络状态的信息 |
| ACCESS_WIFI_STATE | Wi-Fi | 读取有关Wi-Fi连接的信息 |
| VIBRATE | 振动 | 控制设备振动马达 |
| BLUETOOTH | 蓝牙 | 连接到蓝牙设备 |
| WAKE_LOCK | 电源 | 阻止处理器进入休眠状态 |
| SET_ALARM | 闹钟 | 通过AlarmManager设置闹钟 |
| CHANGE_NETWORK_STATE | 网络 | 更改网络连接状态 |
普通权限不会为了在UI中显示而分组到Permission Group中。Android中的分组用于设置屏幕,其中只显示危险权限。但是,逻辑上可以将普通权限分为以下几类:网络(INTERNET, ACCESS_NETWORK_STATE)、硬件(VIBRATE, WAKE_LOCK)、系统(SET_ALARM)和蓝牙权限。
Manifest.permission中的一些常量可能在不同Android版本上改变保护级别。例如,BLUETOOTH_CONNECT在Android 12+上成为带有运行时请求的危险权限,尽管在更早的版本中是normal。建议开发者通过文档检查目标API的当前protectionLevel。
开发者可以通过PackageManager编程检查权限是否为普通权限。getPermissionInfo方法返回PermissionInfo,其protectionLevel字段包含PermissionInfo.PROTECTION_NORMAL标志。这对于动态处理和调试很有用。
fun isNormalPermission(permission: String): Boolean {
val pm = packageManager
val info = pm.getPermissionInfo(
permission,
PackageManager.GET_META_DATA
)
return info.protectionLevel ==
PermissionInfo.PROTECTION_NORMAL
}
在AndroidManifest.xml中声明Normal Permission是最简单的操作,只需一个uses-permission标签。不需要额外配置protectionLevel,因为保护级别由系统定义决定,而非应用程序清单。开发者只需指定常量的完整名称。
<!-- AndroidManifest.xml -->
<uses-permission
android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission
android:name="android.permission.VIBRATE" />
系统在安装时处理所有声明。如果至少有一个指定的权限具有不同于normal的protectionLevel,则需要运行时请求。INTERNET — 最流行的普通权限,存在于大多数Android应用程序中,尤其是那些执行HTTP请求或从网络加载内容的应用程序。
包含普通和危险权限的完整AndroidManifest.xml示例展示了区别:语法上uses-permission标签相同,但在执行阶段,INTERNET和VIBRATE将自动授予,而CAMERA需要对话框。
<manifest
xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Normal permissions -->
<uses-permission
android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.VIBRATE" />
<!-- Dangerous permission -->
<uses-permission
android:name="android.permission.CAMERA" />
</manifest>
在使用库(Google Play Services、Firebase、Glide)时,它们可以通过Manifest Merger将自己的uses-permission添加到最终清单中。其中一些是普通的(Firebase的INTERNET),其他是危险的(Google Maps的ACCESS_FINE_LOCATION)。开发者应在发布前检查build/outputs/logs/manifest-merger-report.txt中的最终合并清单。
Normal Permission有两个基本限制:无法由用户撤销和缺乏管理UI。如果用户不信任该应用程序,但普通权限已经自动授予 — 唯一的出路是删除应用程序。这会产生一定的风险,因为普通权限不会被Android的标准工具阻止。
额外的限制出现在具有多个配置文件(Work Profile、Multiple Users)的设备上。Normal Permission会立即为所有配置文件授予 — 应用程序无法将权限限制为仅一个。在企业场景中,这通过Managed Configurations解决。
无法检查应用程序当前是否正在使用Normal Permission。系统方法checkSelfPermission仅适用于危险权限。对于普通权限,它始终返回PERMISSION_GRANTED,这并不反映实际活动。在安全审计和应用程序行为分析中应考虑这一点。
还要记住,一些设备制造商(小米、华为、三星)会修改权限的默认行为。在他们的固件上,Normal Permission可能在MIUI或EMUI专有界面中需要额外的权限。建议开发者在不同厂商的真实设备上测试功能。
常见问题
Normal Permission在安装时自动授予,无需对话框。Dangerous需要运行时请求并获得用户的明确同意,并可通过设置撤销。Normal使用ProtectionLevel normal,Dangerous使用protectionLevel dangerous。
不需要,对于普通权限,只需在AndroidManifest.xml中声明uses-permission即可。不需要编写请求代码 — 系统会自动授予访问权限。这与需要ActivityCompat.requestPermissions的危险权限不同。
最常用的有:INTERNET(网络请求)、ACCESS_NETWORK_STATE(连接检查)、VIBRATE(触觉反馈)和WAKE_LOCK(保持处理器活动)。几乎每个Android应用程序至少使用INTERNET。
不可以,Normal Permission不能通过应用程序设置撤销。停止访问的唯一方法是删除应用程序。这是与用户可以随时关闭的危险权限的关键区别。
使用PackageManager.getPermissionInfo,传入权限的字符串名称。该方法返回带有protectionLevel字段的PermissionInfo。与PermissionInfo.PROTECTION_NORMAL或PROTECTION_DANGEROUS常量比较以确定类别。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。