4. 权限声明与配置:module.json5权限声明、权限组概念、权限冲突解决策略
好,咱们进入第四个章节。权限声明这块,说实话,是很多鸿蒙开发者容易踩坑的地方。我自己刚接触那会儿,也闹过笑话——明明功能都写好了,一运行就崩,结果发现是权限没配。嗯,今天咱们就把这事儿彻底聊透。
4.1 module.json5 里的权限声明
在鸿蒙应用里,权限声明主要写在 module.json5 这个文件里。你想想看,它就像是你进小区时给保安看的通行证——哪些门能进,哪些房间不能进,都得写清楚。
具体怎么写呢?看这个例子:
{
"module": {
"name": "entry",
"type": "entry",
"requestPermissions": [
{
"name": "ohos.permission.CAMERA",
"reason": "用于扫码识别功能",
"usedScene": {
"abilities": ["MainAbility"],
"when": "inuse"
}
},
{
"name": "ohos.permission.READ_CONTACTS",
"reason": "用于读取联系人信息",
"usedScene": {
"abilities": ["MainAbility", "SecondAbility"],
"when": "always"
}
}
]
}
}
这里有几个关键字段,我跟你掰扯一下:
- name:权限名称,必须跟系统定义的一致,大小写敏感。我见过有人把
CAMERA写成Camera,结果折腾了半天。 - reason:申请权限的原因。这个在应用商店审核时会看,别瞎写。我曾经见过有人写「为了好玩」,结果直接被拒。
- usedScene:使用场景。包括哪些 Ability 在用,以及使用时机(
inuse表示前台使用,always表示后台也能用)。
注意:敏感权限(比如位置、相机、麦克风)必须填写 reason 字段,否则编译会报错。这是鸿蒙的硬性要求,没得商量。
4.2 权限组的概念
权限组,说白了就是把相关的权限打包在一起。为什么要这么设计?你想想看,如果一个应用要拍照、录像、扫码,难道要用户点三次同意吗?那体验也太差了。
鸿蒙把权限分成了几个组,我列个表给你看:
| 权限组名称 | 包含的权限 | 典型场景 |
|---|---|---|
| CAMERA | ohos.permission.CAMERA | 拍照、扫码、视频通话 |
| LOCATION | ohos.permission.LOCATION ohos.permission.LOCATION_IN_BACKGROUND |
地图导航、位置分享 |
| MICROPHONE | ohos.permission.MICROPHONE | 语音输入、录音 |
| STORAGE | ohos.permission.READ_MEDIA ohos.permission.WRITE_MEDIA |
读取相册、保存文件 |
这里有个细节要注意:用户授权是按组授权的。比如用户同意了 CAMERA 组,那组里的所有权限就都开了。但反过来,如果你只申请了组里的一个权限,用户同意了,那其他权限并不会自动获得——嗯,这个逻辑有点绕,但很重要。
我的建议:尽量按组申请权限,别零散地申请。这样用户体验好,审核也容易过。我在项目里就吃过亏,一开始只申请了 READ_MEDIA,后来要写文件时又弹窗,用户直接给了差评。
4.3 权限冲突解决策略
权限冲突,说白了就是两个模块或者两个库都要用同一个权限,但申请方式不一样。这种情况在大型项目里特别常见。
我遇到过这么个事儿:项目里用了第三方图片库,它自己申请了 CAMERA 权限,但我们的主模块也申请了。结果运行时弹了两次授权框,用户直接懵了。
怎么解决?我总结了几个策略:
- 统一声明:所有权限都在主模块的
module.json5里声明,第三方库的权限声明全部去掉。这是最干净的做法。 - 权限合并:如果第三方库的权限声明去不掉(比如是闭源的),那就用
overlay机制覆盖掉。具体做法是在自己的配置里加上相同的权限,系统会自动合并。 - 运行时检查:在调用第三方库之前,先检查权限是否已经授予。如果没授予,先申请再调用。代码大概长这样:
// 检查权限
let result = await abilityAccessCtrl.createAtManager()
.checkAccessTokenSync(
bundleName,
ohos.permission.CAMERA
);
if (result !== 0) {
// 申请权限
await abilityAccessCtrl.createAtManager()
.requestPermissionsFromUser(
context,
["ohos.permission.CAMERA"]
);
}
// 再调用第三方库
thirdPartyLib.startCamera();
核心原则:权限申请要「一次申请,多处复用」。别每个模块都去弹窗,用户会疯的。
4.4 避坑指南
最后,我把自己踩过的坑总结一下,你直接拿去用:
- 别重复申请:同一个权限在多个 Ability 里申请,系统会合并,但弹窗次数不会减少。我建议只在入口 Ability 里统一申请。
- 注意权限等级:鸿蒙的权限分 normal、system_basic、system_core 三级。普通应用只能申请 normal 级别的权限,别想着越级。
- 动态权限要处理拒绝:用户点了「拒绝」后,别一直弹窗。我见过有的应用死循环弹窗,直接被系统拉黑了。
- 测试时用真实设备:模拟器上权限申请可能不弹窗,真机上才会触发。我曾经在模拟器上测得好好的,一上真机就崩,尴尬死了。
嗯,权限这块内容其实挺多的,但核心就是这几点。你只要把 module.json5 写对,权限组概念搞清楚,冲突策略用上,基本就不会出大问题。下一章咱们聊聊权限的动态申请和用户交互,那个更有意思。