HarmonyOS 6.1 全场景实战|《灵犀厨房》实战(三十三):权限管理——用一套“安检系统”告别散装代码

HarmonyOS 6.1 全场景实战|《灵犀厨房》实战(三十三):权限管理——用一套“安检系统”告别散装代码

摘要:从第1篇到第30篇,《灵犀厨房》已经集成了相机(拍照识别食材)、麦克风(声控指令)、通知(烹饪提醒)等系统能力。每一处都需要运行时权限——但之前的写法就像是每家每户自己挖井RecipeDetailPage 里写一段权限检查,IngredientCamera 里又写一段几乎一模一样的代码……重复、散乱、改一处漏三处。今天,我们新建一个 PermissionHelper 工具类,把权限检查、请求、引导设置三项操作封装成三个静态方法,用一套“统一安检系统”管住所有敏感权限。从此,你的代码行数减少75%,维护成本趋近于零。


一、HarmonyOS 权限模型:门禁卡的三个等级

想象你走进一栋智能大厦:

  • normal 权限:就像大厦的旋转门——任何人都可以自由通过(例如访问网络INTERNET),安装 App 时自动授权,你甚至感觉不到它的存在。

  • system_basic 权限:像进入办公区的门禁——你需要刷一下工牌,系统会弹出一个对话框问“是否允许进入”。CAMERA(相机)和 MICROPHONE(麦克风)就属于这一类。用户第一次使用时,系统弹出授权提示。

  • system_core 权限:像进入数据中心机房——不仅需要刷工牌,还要输入动态验证码,甚至需要管理员后台审批。这类权限(如读取通讯录、精准定位)用户需要手动到系统设置页开启。

CAMERAMICROPHONE 属于 system_basic 级——首次使用时系统弹框询问“允许/拒绝”。如果用户勾选了“拒绝且不再询问”,后续调用直接失败,这时我们必须引导用户跳转到系统设置页手动开启。

金句:所有权限必须在 module.json5 中提前“声明”。声明就像在施工图纸上画好“这里要装一扇门”,而运行时请求才是真正“刷卡开门”。两者缺一不可。


二、PermissionHelper 设计:把“散装安检”升级为“统一闸机”

在重构之前,每一处需要权限的页面都重复着这样 12 行“散装代码”:

const atManager = abilityAccessCtrl.createAtManager();
const ctx = this.getUIContext().getHostContext() as common.UIAbilityContext;
const tokenId = ctx.applicationInfo.accessTokenId;
const granted = atManager.checkAccessTokenSync(tokenId, 'ohos.permission.MICROPHONE')
  === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
if (!granted) {
  const result = await atManager.requestPermissionsFromUser(ctx, ['ohos.permission.MICROPHONE']);
  if (result.authResults[0] !== 0) { /* 用户拒绝,提示跳转设置 */ }
}

每个人都在重复造轮子,而且容易出错:tokenId 取错、回调处理不统一、跳转设置的逻辑五花八门……

现在,我们把这三个核心能力封装成一个静态工具类——就像大厦统一安装的“人脸识别闸机”,所有楼层共用同一套系统。

2.1 类图:一图看懂三个方法

«static»

PermissionHelper

+isGranted(context, permission) : boolean

+checkAndRequest(context, permission) : Promise<boolean>

+goToSettings(context) : void

三个静态方法,无需实例化

同步检查权限状态,即插即用

检查→请求→返回结果,适合按钮点击场景

跳转系统设置页,供用户手动开启

2.2 isGranted —— 同步“查门禁”

static isGranted(context: common.UIAbilityContext, permission: string): boolean {
  const atManager = abilityAccessCtrl.createAtManager();
  return atManager.checkAccessTokenSync(
    context.applicationInfo.accessTokenId,
    permission
  ) === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
}

为什么用同步 API?
权限状态本质是系统 token 中的一个标记,读取它就像看一眼门禁灯——绿灯/红灯,瞬间就知道。用同步方法可以避免不必要的异步等待,尤其适合在页面初始化时快速判断(例如决定是否显示“请授权相机”提示条)。

2.3 checkAndRequest —— 异步“请求放行”

static async checkAndRequest(
  context: common.UIAbilityContext,
  permission: string
): Promise<boolean> {
  // 先检查:已有权限直接放行
  if (PermissionHelper.isGranted(context, permission)) return true;

  // 未授权:弹出系统对话框请求
  const atManager = abilityAccessCtrl.createAtManager();
  try {
    const result = await atManager.requestPermissionsFromUser(context, [permission]);
    // authResults[0] === 0 表示用户点击“允许”
    return result.authResults.length > 0 && result.authResults[0] === 0;
  } catch (err) {
    console.error('[PermissionHelper] 请求权限失败:', JSON.stringify(err));
    return false;
  }
}

这个方法像一个智能接待员:先看你是不是已经有门禁卡(isGranted),有就直接放行;没有就弹出系统对话框请你刷脸(requestPermissionsFromUser),然后告诉你“放行”还是“拒绝”。

下面的流程图直观展示了整个过程:

✅ 已授权

❌ 未授权

允许

拒绝

拒绝且不再询问

调用 checkAndRequest(ctx, 'ohos.permission.CAMERA')

isGranted?

return true

requestPermissionsFromUser()
弹出系统对话框

用户选择

return true

return false

下次 isGranted 仍为 false

调用者判断:引导用户 goToSettings()

2.4 goToSettings —— 跳转“后勤部”

如果用户曾经拒绝且勾选了“不再询问”,后续 checkAndRequest 将直接返回 false,系统不会再弹框。此时我们需要引导用户去系统设置页手动开启权限——就像门禁坏了,你得去物业办公室补办一张卡。

static goToSettings(context: common.UIAbilityContext): void {
  try {
    const want: Want = {
      bundleName: 'com.huawei.hmos.settings',        // 系统设置包名
      abilityName: 'com.huawei.hmos.settings.MainAbility',
      uri: 'application_info_entry',                 // 跳转到应用详情页
      parameters: { pushParams: context.applicationInfo.name }
    };
    context.startAbility(want);
  } catch (err) {
    console.error('[PermissionHelper] 跳转设置失败:', JSON.stringify(err));
  }
}

设计细节goToSettings 不抛异常——跳转失败(比如用户正在使用低版本系统)不会导致 App 崩溃,最多是无法打开设置页。静默吞掉错误,让主流程继续。


三、使用示例:从“散装12行”到“精致3行”

3.1 拍照前检查相机权限(第6篇食材识别场景)

改造前 —— 重复、冗余、容易遗漏引导逻辑:

const atManager = abilityAccessCtrl.createAtManager();
const ctx = this.getUIContext().getHostContext() as common.UIAbilityContext;
const tokenId = ctx.applicationInfo.accessTokenId;
const granted = atManager.checkAccessTokenSync(tokenId, 'ohos.permission.CAMERA')
  === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
if (!granted) {
  const result = await atManager.requestPermissionsFromUser(ctx, ['ohos.permission.CAMERA']);
  if (result.authResults[0] !== 0) {
    promptAction.showToast({ message: '需要相机权限才能拍照' });
    return;  // 往往忘了引导去设置页
  }
}
// 12 行,而且丢失了引导逻辑

改造后 —— 3 行搞定,语义清晰:

const ctx = this.getUIContext().getHostContext() as common.UIAbilityContext;
const granted = await PermissionHelper.checkAndRequest(ctx, 'ohos.permission.CAMERA');
if (!granted) {
  promptAction.showToast({ message: '请到设置页开启相机权限' });
  PermissionHelper.goToSettings(ctx);
  return;
}
// 继续拍照逻辑

3.2 三种典型使用模式

场景代码模板说明
页面初始化判断(决定是否显示引导条)if (!PermissionHelper.isGranted(ctx, perm)) this.showHint = true;同步、无弹框
按钮点击请求权限(如“开始录音”)const ok = await PermissionHelper.checkAndRequest(ctx, perm); if (ok) this.startRecord();自动弹框,异步等待
请求失败后引导if (!ok) { PermissionHelper.goToSettings(ctx); }跳转系统设置

四、代码交付清单

文件操作行数变化说明
common/PermissionHelper.ets新增+50三个静态方法,纯工具类
module.json5无需修改0权限声明(相机/麦克风/通知)已在之前篇章添加
IngredientCamera.ets重构-9移除散装权限代码,调用 Helper
RecipeDetailPage.ets重构-12麦克风权限检查统一调用 Helper

净减少代码约 20 行,但更重要的是——未来新增任何需要权限的功能,只需一行 await PermissionHelper.checkAndRequest(),维护成本降为 0。


五、设计决策:为什么这么写?

决策理由
全静态方法权限工具无状态,无需 new。就像 Math.max(),直接调用即可
isGranted 用同步 API权限检查本质是读系统 token,同步返回结果,避免不必要的异步开销
goToSettings 不抛异常跳转设置失败是“锦上添花”的功能,不应打断主流程。静默失败,仅打日志
权限声明与请求分离module.json5 是编译时“备料”,运行时 checkAndRequest 是“下锅”。各司其职
不封装多权限同时请求简化设计:一次只处理一个权限。调用方自行循环调用,更清晰,避免“部分成功”的混乱

六、总结与下篇预告

今天,我们给《灵犀厨房》装上了一套统一权限管理“安检系统”

  • isGranted 快速查门禁(同步)
  • checkAndRequest 智能请求放行(异步 + 自动弹框)
  • goToSettings 跳转后勤部(手动开启)

从此,任何需要相机、麦克风、通知的地方,都只需 3 行代码完成权限检查。代码更干净、逻辑更统一、用户体验更一致。

但这只是性能优化的前奏。下一站,我们将打开 DevEco Studio 的 Profiler 工具,像一个“性能侦探”一样分析《灵犀厨房》的 CPU、内存、帧率瓶颈——找出那些让页面卡顿的“真凶”,然后一个个优化掉。敬请期待第 32 篇!


📚 专栏持续更新中下一期,我们化身“性能侦探”,用 Profiler 给 App 做一次深度体检。不见不散!

🔗 专栏入口:[《HarmonyOS6.1全场景实战》合集]
📦 获取基线版本源码包包括第1-15篇所有代码 + 架构文档 + Flask 后端
**如果你发现本文还有任何不严谨之处,欢迎随时指出,我们一起共建最优质的 HarmonyOS 6.1 学习内容!如果觉得有帮助,请不要吝啬你的点赞 👍、收藏 ⭐ 和评论 💬!
纯血鸿蒙,用心造厨。我们下一篇见!

内容概要:本文围绕可变桨叶四旋翼无人机的规范控制与点对点运动模拟展开,重点研究优化推力分配策略在翻转动作中的应用与性能比较。通过Matlab代码实现,构建了四旋翼动力学模型,并设计了多种控制算法以实现精确的姿态调整与轨迹跟踪。研究对比了不同推力分配方案在执行高机动性翻转动作时的稳定性、能耗效率与响应速度,旨在提升无人机在复杂飞行任务中的动态性能与控制精度。该仿真研究为无人机飞控系统的设计与优化提供了理论依据和技术支持。; 适合人群:具备一定自动控制理论基础和Matlab编程能力,从事无人机控制、飞行器动力学或机器人系统研究的科研人员及研究生。; 使用场景及目标:① 实现四旋翼无人机在三维空间中的精确点对点运动控制;② 对比分析不同推力分配策略在执行翻转等高难度动作时的控制效果与能耗表现,优化飞行性能;③ 为无人机自主飞行、特技飞行及复杂环境下的机动控制提供算法验证平台。; 阅读建议:此资源以Matlab仿真为核心,建议读者结合相关控制理论知识,深入理解代码实现细节,重点关注动力学建模、控制律设计与推力分配模块。在学习过程中,应动手调试参数,复现文中翻转动作的仿真结果,并尝试拓展至其他复杂飞行任务,以加深对无人机控制机理的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安楠的数智笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值