权限拒绝后只会反复弹窗:HarmonyOS 7 requestPermissionOnSetting 分项恢复实战
扫码入口的相机权限被用户拒绝后,按钮每次点击都重新触发同一授权流程;通知权限被关时又跟相机混在一起提示。最终用户既不知道要改哪一项,页面也无法判断从设置返回后的结果。
本文交付:一套 PermissionRecoveryPlan、错误码到 UI 的映射、相机和通知两种案例,以及返回设置后的复查步骤。。
官方依据与版本边界
官方变更页:https://developer.huawei.com/consumer/cn/doc/doccenter-release-notes/js-apidiff-abilitykit-7003
- AtManager.requestPermissionOnSetting 用于引导用户在设置中恢复权限。
- API 26 增加错误码 12100010。
- 恢复前必须按权限逐项读取授权结果。
- 返回应用后必须重新查询而非假设已授权。
本文依据 HarmonyOS 7.0.0 Release(API 26)官方变更说明梳理接口,并对状态模型、分支选择和异常映射做了宿主侧 TypeScript 测试。当前本机 SDK 为 API 24,且没有连接 HDC 设备,因此不把示例描述为 API 26 编译通过、真机性能数据或上架审核结论。接入前请在 API 26 工程中按文末清单完成编译、设备与回归验证。
复现与验证
- 分别关闭相机与通知权限,不要一次关闭全部。
- 从两个不同功能入口触发恢复流程。
- 记录 requestPermissionOnSetting 的权限数组与异常码。
- 返回应用后重新调用权限查询,更新单项状态。
- 确认通知拒绝不阻断菜谱浏览,相机拒绝只阻断扫码。
| 输入/场景 | 预期分支 | 验收信号 |
|---|---|---|
| 相机已授权 | 不打开设置 | 直接扫码 |
| 相机 blocked | 只传 CAMERA | 返回后复查 |
| 通知 blocked | 只传通知权限 | 浏览不受影响 |
| 错误 12100010 | 显示手动路径 | 不循环弹窗 |
| 用户未改设置 | 维持 blocked | 按钮仍可解释 |
| 两项都关闭 | 按触发场景分批处理 | 不打包索权 |
图中的每条箭头都应对应一条可查询日志:输入、平台调用、状态映射、UI 或降级结果。只有 UI 变化而没有中间证据,后续仍然难以区分接口失败和页面逻辑错误。
两种行为不同的案例
案例一:扫码识菜
相机是即时动作所必需。拒绝后应说明影响并只请求相机设置,不要顺便索取通知权限。
案例二:烹饪计时提醒
通知被关闭不应阻断浏览菜谱;页面保留功能入口,在用户启用提醒时再给出可恢复路径。
可复用的 ArkTS 集成片段
typePermissionState='granted'|'denied'|'blocked'+typeRecovery={permission:string;reason:string;requiredNow:boolean}++exportfunctionbuildRecovery(states:Record<string,PermissionState>):Recovery[]{+constplans:Recovery[]=[]+if(states['ohos.permission.CAMERA']==='blocked'){+plans.push({permission:'ohos.permission.CAMERA',reason:'扫码识菜需要取景',requiredNow:true})+}+if(states['ohos.permission.NOTIFICATION_CONTROLLER']==='blocked'){+plans.push({permission:'ohos.permission.NOTIFICATION_CONTROLLER',reason:'计时结束提醒',requiredNow:false})+}+returnplans+}++asyncfunctionrecoverOne(atManager:abilityAccessCtrl.AtManager,item:Recovery){+try{+awaitatManager.requestPermissionOnSetting(getContext(),[item.permission])+return{permission:item.permission,next:'recheck'asconst}+}catch(error){+constcode=(errorasBusinessError).code+return{permission:item.permission,next:code===12100010?'show-guidance':'log-and-stop'}+}+}代码刻意把平台调用和业务状态分开:平台返回什么就记录什么,页面只消费稳定状态。接入时还应补齐项目的日志域、错误码类型和生命周期释放。
取舍与落地清单
一次把所有权限送进设置页看似省步骤,却会降低可解释性,也让返回结果难以对应功能。按场景分项恢复会多一层状态代码,但更容易测试,也不会把可选权限变成强制门槛。
- 已用 API 26 工程编译,并记录 SDK 与设备版本
- 已覆盖“扫码识菜”和“烹饪计时提醒”两类行为
- 已记录成功、失败、降级三条路径的输入与结果
- 已核对监听、对象或任务的释放与幂等行为
- 已把本文宿主测试替换为项目自己的真机证据
小结
一套 PermissionRecoveryPlan、错误码到 UI 的映射、相机和通知两种案例,以及返回设置后的复查步骤。。建议先在最小页面复现,再接入完整“中式美食”流程;先证明状态链正确,再谈动画、缓存或埋点优化。