鸿蒙权限管理:受限权限申请(六)
搞鸿蒙开发有一段时间的朋友,应该都有这种体会:权限申请本身并不难,难的是搞清楚“哪些权限能直接申请,哪些权限得走特殊流程”。尤其是受限权限,英文文档里叫 restricted permissions,中文社区里讨论得不算多,但凡是做应用市场审核、做系统应用、做企业分发的,迟早都会撞上它。
这篇是《鸿蒙权限管理》系列里比较“硬核”的一篇,专门聊受限权限申请这件事。我会把它的基本逻辑、为什么存在这层限制、申请时和普通权限有什么不一样、实战里最常踩的坑,尽量一次讲透。适合已经写过 requestPermissionsFromUser 但被拒得不明不白,或者马上要面对应用市场审核的开发者。
- 为什么会有“受限权限”这种东西
1.1 权限也分三六九等
鸿蒙的权限体系,按官方文档的划分,大致分成了 normal(普通权限)、system_basic(系统基础权限)、system_core(系统核心权限)这几类。普通权限好理解,比如访问网络、获取网络状态,只要在 module.json5 里声明,然后在运行时向用户申请,用户点了同意就能用。
但有一类权限比较特殊,它在官方权限列表里存在,声明方式也和普通权限一样,但当你运行时去申请,系统会直接拒绝,甚至不会弹窗。这类权限内部被称为 restricted permissions,中文官方翻译是“受限权限”,有的地方也叫“受限申请权限”。
我第一次遇到这个坑,是在做一个文件管理类应用的时候。需要在系统公共目录里创建自己的文件夹,当时按惯性给应用声明了媒体位置的权限,结果运行时申请直接被拒了,错误码返回 201,提示信息模模糊糊,一看就是权限等级不够,但等级哪里不够,API 文档写得并不直白。
后来才搞清楚,受限权限是普通应用能申请的“上限”之外的一类权限。它的特点是:权限声明存在、权限用途明确、系统能力也确实提供,但是出于用户数据安全、设备控制安全等原因,不允许一般应用在未经验证的情况下直接获取。
1.2 谁在限制你,限制的是什么
鸿蒙的权限校验,背后是一套能力开放策略。系统不可能把所有能力都无差别开放给所有应用,否则一个随便下载的 App 就能读取设备上的敏感信息,整个安全模型就崩了。
受限权限限制的核心有三个:
- 权限声明里的级别(level)不够。有些权限在 ACL(访问控制列表)里只允许 system_core 或 system_basic 级别的应用声明,普通应用声明了也白搭。
- 需要额外申请受限权限的授权。这个授权不是运行时的用户弹窗就能解决的,而是需要开发者在应用市场或特定渠道完成受限权限申请,审核通过后,你的应用签名指纹才会被加入白名单。
- 即便代码里调用了申请接口,用户也未收到任何提示。因为受限权限的申请根本不会走用户授权弹窗,它是去“权限管理”界面或系统层面做静态控制的。
这么一解释,你就能理解为什么很多开发者在本地调试时一切正常,一上真机或者一提交审核就出问题。本地调试环境可能默认给了你调试签名对应的权限白名单;真机上,如果你的应用没有通过受限权限申请流程,权限自然拿不到。
- 受限权限和普通权限到底差在哪里
很多教程里会把“敏感权限”和“受限权限”混着讲,实际这俩不是一回事。普通权限里也有敏感的,比如定位、相机、麦克风,它们在运行时会触发用户授权弹窗,用户拒绝的话你再申请一次也还能再弹;但受限权限的敏感程度通常更高,涉及的不只是单个用户的一次授权,而是会影响整个系统设备状态或者跨应用的数据访问边界。
为了不让大家绕晕,我把我在项目里常用的对比表直接放出来。
| 对比项 | 普通权限 | 受限权限 |
|---|---|---|
| 声明方式 | module.json5 里声明 | module.json5 里声明(同) |
| 运行时弹窗 | 有,用户点同意即可 | 一般没有,需要预授权 |
| 授权主体 | 用户 | 用户 + 系统/应用市场侧审核 |
| 权限级别 | normal / system_basic 可覆盖 | 通常 system_basic 起步,core 常见 |
| 调试阶段 | 直接可用 | 往往需要白名单或额外签名配置 |
| 典型例子 | 获取设备网络状态 | 读取 |
