【鸿蒙心迹】权限申请实战:从“弹个框就完了”到分层申请与拒绝后引导
【鸿蒙心迹】权限申请实战:从"弹个框就完了"到分层申请与拒绝后引导
前言
长列表优化收尾之后,码上清单的性能账清了,功能侧开始加码:给待办配图(相机)、语音速记(麦克风)。功能没写几行,先撞上的是权限体系——这也是系列第二阶段的第一个话题。以前总觉得权限就是"弹个框让用户点同意",真做下来发现它拆开是三件事:分清哪些权限要弹、什么时机弹、用户拒绝之后怎么办。弹框只是这套流程里最薄的一层。这篇按这三件事展开。
一、先把权限"分级"搞清楚
动手之前先把分类表过一遍,HarmonyOS 的权限分两大类:
- system_grant(系统授权):在 module.json5 里声明即生效,不弹框。最常见的就是
ohos.permission.INTERNET——第一次做网络请求时以为要弹框申请,搜了半天"怎么触发权限弹窗",其实只要配置里声明了,安装那一刻就已经有了; - user_grant(用户授权):相机、麦克风、位置这类涉及用户敏感数据的,声明只是第一步,必须运行时调用接口弹框,用户点了同意才算数。
第一个常见的坑就在这里:把 system_grant 当成 user_grant 去申请,代码里塞了一段申请逻辑却永远等不到弹窗,排查半天发现根本不需要申请。反过来,以为声明了就能用 user_grant 权限,运行时调相机直接报错,是另一半。两类权限的清单在官方《权限列表》文档里查得到,动手前先对号入座。
二、申请的正确姿势:时机、声明、话术
user_grant 权限的完整链路是三步:module.json5 声明 → 运行时申请 → 处理结果。
声明要带 reason 和 usedScene:
// module.json5
"requestPermissions": [
{
"name": "ohos.permission.CAMERA",
"reason": "$string:camera_permission_reason",
"usedScene": { "abilities": ["EntryAbility"], "when": "inuse" }
}
]
时机是这套流程里最值得斟酌的一件事。实测下来一个原则:跟着用户动作走,不跟应用启动走。点"拍照记待办"按钮的时候申请相机,用户对"为什么要这个权限"有天然的心理预期,通过率高;应用一启动就连环弹三个框,用户大概率全部拒绝,而且第一次体验就被消耗掉了。
话术(reason)别小看它。这个字符串会展示在权限弹窗和应用市场审核里,写成"需要使用您的相机"这种万能模板,审核会被打回——要求是具体功能场景,比如"拍摄照片以添加待办配图"。用 $string 资源引用而不是硬编码,还能顺带支持多语言。
代码本身不复杂:
import { abilityAccessCtrl, Permissions } from '@kit.AbilityKit';
const atManager = abilityAccessCtrl.createAtManager();
const result = await atManager.requestPermissionsFromUser(
this.context, ['ohos.permission.CAMERA'] as Array<Permissions>);
// result.authResults 里 0 是授权,-1 是拒绝
if (result.authResults[0] === 0) {
this.openCamera();
}
三、拒绝之后:真正的工作量在这里
弹框只是开始,用户拒绝之后的路径才是工程量所在。拒绝分两种情况,处理完全不同:
- 普通拒绝(第一次点"拒绝"):下次再调 requestPermissionsFromUser 还能正常弹框。这时不要灰心,在用户再次触发功能时再问一次,话术场景给足,很多用户第二次会点同意;
- 拒绝并勾选"不再询问"(或多次拒绝后):再调申请接口不会弹框,直接静默返回拒绝。这条路要靠引导用户去设置页手动打开——可以用 requestPermissionOnSetting 拉起该权限的设置弹窗,或 startAbility 到应用的设置详情页,跳转前先用自己的页面说清楚"为什么需要",别让用户裸脸面对设置页。
所以功能入口要做成三岔路:已授权 → 直接用;可再问 → 走申请;死锁 → 走引导。判断当前状态用 checkAccessToken(tokenID 从 bundleManager 查自己包信息拿)。另外留一条降级路:没相机权限,文字输入照样能用,语音速记退化成键盘输入。权限被拒不该等于功能不可用,这是产品侧最重要的兜底。
四、踩坑三条
- 声明与申请两头都要有:只在代码里申请、module.json5 没声明,接口直接报错;只声明没申请,user_grant 权限拿不到。排查权限问题先数这两头是否配平;
- reason 写模板话术被审核驳回:要求中文、具体到功能场景。一次性把$string 资源写好,比打回重传省一个工作日;
- 别碰 ACL 门槛权限:后台定位这类 restricted 权限走 ACL(权限访问控制名单)申请,普通应用声明了也拿不到授权。选型阶段就要核对权限的授权方式,别把功能设计在拿不到的权限上,浪费的是整个排期。
小结
权限这块补完,码上清单的"拍照配图 + 语音速记"落地了,沉淀下来的是一张三岔路决策图:分级 → 场景申请 → 拒绝分流(再问 / 引导 / 降级)。下一篇写网络请求封装:RCP 客户端选型、拦截器里塞 token 与重试、弱网下的超时预算,把"能联网"做成"联网可靠"。
*本文环境:DevEco Studio 5.x / HarmonyOS NEXT(API 14+)。权限清单与授权方式以官方《应用权限列表》文档为准。系列上一篇:《【鸿蒙心迹】长列表性能优化实录》。*
更多推荐




所有评论(0)