权限拒绝后只会反复弹窗:HarmonyOS 7 requestPermissionOnSetting 分项恢复实战

扫码入口的相机权限被用户拒绝后,按钮每次点击都重新触发同一授权流程;通知权限被关时又跟相机混在一起提示。最终用户既不知道要改哪一项,页面也无法判断从设置返回后的结果。

本文交付:一套 PermissionRecoveryPlan、错误码到 UI 的映射、相机和通知两种案例,以及返回设置后的复查步骤。。

官方依据与版本边界

官方变更页:https://developer.huawei.com/consumer/cn/doc/doccenter-release-notes/js-apidiff-abilitykit-7003

  1. AtManager.requestPermissionOnSetting 用于引导用户在设置中恢复权限。
  2. API 26 增加错误码 12100010。
  3. 恢复前必须按权限逐项读取授权结果。
  4. 返回应用后必须重新查询而非假设已授权。

本文依据 HarmonyOS 7.0.0 Release(API 26)官方变更说明梳理接口,并对状态模型、分支选择和异常映射做了宿主侧 TypeScript 测试。当前本机 SDK 为 API 24,且没有连接 HDC 设备,因此不把示例描述为 API 26 编译通过、真机性能数据或上架审核结论。接入前请在 API 26 工程中按文末清单完成编译、设备与回归验证。

复现与验证

  1. 分别关闭相机与通知权限,不要一次关闭全部。
  2. 从两个不同功能入口触发恢复流程。
  3. 记录 requestPermissionOnSetting 的权限数组与异常码。
  4. 返回应用后重新调用权限查询,更新单项状态。
  5. 确认通知拒绝不阻断菜谱浏览,相机拒绝只阻断扫码。
输入/场景预期分支验收信号
相机已授权不打开设置直接扫码
相机 blocked只传 CAMERA返回后复查
通知 blocked只传通知权限浏览不受影响
错误 12100010显示手动路径不循环弹窗
用户未改设置维持 blocked按钮仍可解释
两项都关闭按触发场景分批处理不打包索权

权限拒绝后只会反复弹窗:HarmonyOS 7 requestPermissionOnSetting 分项恢复实战 的状态与证据路径

图中的每条箭头都应对应一条可查询日志:输入、平台调用、状态映射、UI 或降级结果。只有 UI 变化而没有中间证据,后续仍然难以区分接口失败和页面逻辑错误。

两种行为不同的案例

案例一:扫码识菜

相机是即时动作所必需。拒绝后应说明影响并只请求相机设置,不要顺便索取通知权限。

案例二:烹饪计时提醒

通知被关闭不应阻断浏览菜谱;页面保留功能入口,在用户启用提醒时再给出可恢复路径。

可复用的 ArkTS 集成片段

type PermissionState = 'granted' | 'denied' | 'blocked'
+type Recovery = { permission: string; reason: string; requiredNow: boolean }
+
+export function buildRecovery(states: Record<string, PermissionState>): Recovery[] {
+  const plans: 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 })
+  }
+  return plans
+}
+
+async function recoverOne(atManager: abilityAccessCtrl.AtManager, item: Recovery) {
+  try {
+    await atManager.requestPermissionOnSetting(getContext(), [item.permission])
+    return { permission: item.permission, next: 'recheck' as const }
+  } catch (error) {
+    const code = (error as BusinessError).code
+    return { permission: item.permission, next: code === 12100010 ? 'show-guidance' : 'log-and-stop' }
+  }
+}

代码刻意把平台调用和业务状态分开:平台返回什么就记录什么,页面只消费稳定状态。接入时还应补齐项目的日志域、错误码类型和生命周期释放。

取舍与落地清单

一次把所有权限送进设置页看似省步骤,却会降低可解释性,也让返回结果难以对应功能。按场景分项恢复会多一层状态代码,但更容易测试,也不会把可选权限变成强制门槛。

  • 已用 API 26 工程编译,并记录 SDK 与设备版本
  • 已覆盖“扫码识菜”和“烹饪计时提醒”两类行为
  • 已记录成功、失败、降级三条路径的输入与结果
  • 已核对监听、对象或任务的释放与幂等行为
  • 已把本文宿主测试替换为项目自己的真机证据

小结

一套 PermissionRecoveryPlan、错误码到 UI 的映射、相机和通知两种案例,以及返回设置后的复查步骤。。建议先在最小页面复现,再接入完整“中式美食”流程;先证明状态链正确,再谈动画、缓存或埋点优化。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐