这个示例里最容易被忽略的地方,不在页面,也不在动画,而是在 module.json5。很多人复制 motion.on() 之后发现没反应,最后才发现权限没配。

项目源码:https://gitcode.com/HarmonyOS_Samples/SmartReach/tree/master

智感握姿为什么需要权限

智感握姿依赖系统的动作感知能力。应用想知道用户当前是左手握持还是右手握持,就必须先声明 ohos.permission.DETECT_GESTURE

这类能力不是普通 UI 事件。按钮点击、滑动列表属于应用内部事件;握姿识别来自系统多模态感知能力,所以它需要单独授权。

项目里的权限配置

源码位置是 entry/src/main/module.json5,关键片段如下:

"requestPermissions": [
  {
    "name": "ohos.permission.DETECT_GESTURE",
    "reason": "$string:gesture_reason",
    "usedScene": {
      "abilities": [
        "SmartreachAbility"
      ],
      "when": "inuse"
    }
  }
]

小白可以先记住三个字段:

  • name:申请哪个权限,这里就是动作感知;
  • reason:告诉用户为什么需要这个权限;
  • usedScene:说明哪个 Ability、什么时机使用。

reason 不要随便写

reason 指向字符串资源:

Ink notes style infographic breaking down the thre

"reason": "$string:gesture_reason"

这意味着真正展示给用户看的文案在资源文件里,而不是直接写死在 module.json5。这样做的好处是后面做中英文、多语言适配时比较轻松。

如果你做自己的项目,我建议把原因写得直白一点,比如“用于识别左右手握持状态,调整底部导航位置”。不要写成“提升用户体验”这种空话,用户看了也不知道你到底要干嘛。

权限和代码怎么连起来

有了权限声明,页面里才会去监听握姿变化:

import { motion } from '@kit.MultimodalAwarenessKit';

aboutToAppear(): void {
  try {
    if (canIUse('SystemCapability.MultimodalAwareness.Motion')) {
      motion.on('holdingHandChanged', this.handleHoldingHandChange);
      Logger.info(TAG, `Succeed handle on holdingHandChanged`);
    } else {
      Logger.error(TAG, `Can not handle on holdingHandChanged`);
    }
  } catch (error) {
    Logger.error(TAG, `Failed on holdingHandChanged. cause${error.message}`);
  }
}

这里有个很好的习惯:监听前先用 canIUse() 判断系统能力。不是所有设备、系统版本都一定支持这个能力,直接调 API 会让排查变麻烦。

Ink notes style flowchart explaining robust API us

常见坑:只写代码,不看设备能力

我见过不少小白会这样写:

motion.on('holdingHandChanged', this.handleHoldingHandChange);

这段看着很简洁,但不够稳。真实项目里最好像示例这样包三层保护:

  • try/catch 防止异常打断页面;
  • canIUse() 判断系统能力;
  • 日志记录成功和失败路径。

等你开始调真机时,这些日志能省不少时间。

截图对照一下

权限配置正确后,应用才能在运行中根据握持状态改变悬浮控件的位置。下面是折叠屏示例图:

折叠屏智感握姿效果

写在最后

权限配置这一步没什么炫技,但它是智感握姿的地基。我的建议是:以后只要用到系统感知、定位、相机、麦克风这类能力,先去 module.json5 看权限,再写业务代码。这个顺序能少踩很多坑。

Logo

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

更多推荐