HarmonyOS鸿蒙Next中如何给app添加智感握姿功能,添加后数据如何做到立即更新响应

HarmonyOS鸿蒙Next中如何给app添加智感握姿功能,添加后数据如何做到立即更新响应 如何给app添加智感握姿功能,添加后数据如何做到立即更新响应,开发小白需要详细教程,还请大佬指点

8 回复

【背景知识】 多模态融合感知:多模态融合感知是利用设备上的多种传感器数据,如加速度计和陀螺仪等,来识别活动、状态和姿态等信息,例如,判断设备是否处于静止状态。 获取用户动作:当应用需要获取用户动作时,可以调用motion模块,例如判断用户当前是用左手还是右手操作设备屏幕。

【解决方案】 从API15开始,支持获取操作手状态;从API20开始,支持获取握持手状态,智感握姿功能正是基于获取握持手状态能力实现,不过需要注意的是此功能当前支持部分机型,若设置菜单中存在“智感握姿”开关(可在“设置-系统”中查看),则表明该设备支持此功能,若无此开关,将返回801错误码,详细可查看约束与限制

使用两个能力之前需要导入相关Kit:

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

同时还需要在module.json5中申请ohos.permission.ACTIVITY_MOTION或ohos.permission.DETECT_GESTURE权限,本文以ohos.permission.DETECT_GESTURE举例。

场景一:获取用户操作手状态。 调用motion.on(‘operatingHandChanged’)接口订阅触控操作手感知事件,在回调函数中拿到触控操作手状态信息

try {
  motion.on('operatingHandChanged', (data: motion.OperatingHandStatus) => {
    switch (data) {
      case motion.OperatingHandStatus.UNKNOWN_STATUS:
        console.info('nothing has been detected.');
        break;
      case motion.OperatingHandStatus.LEFT_HAND_OPERATED:
        console.info('the operating hand is left hand.');
        this.message = '当前是左手操作';
        break;
      case motion.OperatingHandStatus.RIGHT_HAND_OPERATED:
        console.info('the operating hand is right hand.');
        this.message = '当前是右手操作';
        break;
      default:
        console.info('nothing has been detected.');
        return;
    }
  });
  console.info("operatingHandChanged on succeeded");
} catch (err) {
  let error: BusinessError = err as BusinessError;
  console.error("failed on operatingHandChanged and err code is " + error.code);
}

调用motion.off(‘operatingHandChanged’)接口取消订阅触控操作手感知事件:

try {
  motion.off('operatingHandChanged');
  console.info("off operatingHandChanged succeeded");
} catch (err) {
  let error: BusinessError = err as BusinessError;
  console.error("failed off operatingHandChanged and err code is " + error.code);
}

场景二:获取用户握持手状态。 调用motion.on(‘holdingHandChanged’)订阅握持手状态变化感知事件,在回调函数中拿到手机握持手状态信息

try {
  motion.on('holdingHandChanged', (data: motion.HoldingHandStatus) => {
    switch (data) {
      case motion.HoldingHandStatus.NOT_HELD:
        console.info('no holding has been detected.');
        this.message = '未检测到握持';
        break;
      case motion.HoldingHandStatus.LEFT_HAND_HELD:
        console.info('holding with the left hand.');
        this.textLocation = FlexAlign.Start;
        this.message = '当前是左手握持';
        break;
      case motion.HoldingHandStatus.RIGHT_HAND_HELD:
        console.info('holding with the right hand.');
        this.textLocation = FlexAlign.End;
        this.message = '当前是右手握持';
        break;
      case motion.HoldingHandStatus.BOTH_HANDS_HELD:
        console.info('holding with the both hand.');
        this.textLocation = FlexAlign.Center;
        this.message = '当前是双手握持';
        break;
      case motion.HoldingHandStatus.UNKNOWN_STATUS:
      default:
        console.info('nothing has been detected.');
        this.textLocation = FlexAlign.Center;
        break;
    }
  });
  console.info("holdingHandChanged on succeeded");
} catch (err) {
  let error: BusinessError = err as BusinessError;
  console.error("failed on holdingHandChanged and err code is " + error.code);
}

完整示例代码如下:

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

@Entry
@Component
struct Index {
  @State message: string = '获取用户动作开发示例';
  @State textLocation: FlexAlign = FlexAlign.Center;
  // 是否订阅操作手感知
  @State operatingHandChanged: boolean = false;
  // 是否订阅握持手感知
  @State holdingHandChanged: boolean = false;

  build() {
    Column() {
      Row() {
        Text(this.message)
          .margin({
            bottom: 40
          });
      }
      .width('100%')
      .justifyContent(this.textLocation);

      // 订阅操作手
      Button(this.operatingHandChanged ? '点击【关闭】获取操作手状态' : '点击【开启】获取操作手状态')
        .backgroundColor(this.operatingHandChanged ? Color.Blue : Color.Gray)
        .onClick(() => {
          this.textLocation = FlexAlign.Center;
          // 如果是false,提示点击开启,然后监听
          if (!this.operatingHandChanged) {
            try {
              motion.on('operatingHandChanged', (data: motion.OperatingHandStatus) => {
                switch (data) {
                  case motion.OperatingHandStatus.UNKNOWN_STATUS:
                    console.info('nothing has been detected.');
                    break;
                  case motion.OperatingHandStatus.LEFT_HAND_OPERATED:
                    console.info('the operating hand is left hand.');
                    this.message = '当前是左手操作';
                    break;
                  case motion.OperatingHandStatus.RIGHT_HAND_OPERATED:
                    console.info('the operating hand is right hand.');
                    this.message = '当前是右手操作';
                    break;
                  default:
                    console.info('nothing has been detected.');
                    return;
                }
              });
              console.info("operatingHandChanged on succeeded");
            } catch (err) {
              let error: BusinessError = err as BusinessError;
              console.error("failed on operatingHandChanged and err code is " + error.code);
            }
          } else {
            this.message = '获取用户动作开发示例';
            try {
              motion.off('operatingHandChanged');
              console.info("off operatingHandChanged succeeded");
            } catch (err) {
              let error: BusinessError = err as BusinessError;
              console.error("failed off operatingHandChanged and err code is " + error.code);
            }
          }
          // 修改状态和按键名称
          this.operatingHandChanged = !this.operatingHandChanged;
          // 两个手势监听互斥
          if (this.operatingHandChanged) {
            this.holdingHandChanged = false;
            try {
              motion.off('holdingHandChanged');
              console.info("off holdingHandChanged succeeded");
            } catch (err) {
              let error: BusinessError = err as BusinessError;
              console.error("failed off holdingHandChanged and err code is " + error.code);
            }
          }
        })
        .margin({
          bottom: 15
        });

      // 订阅握持手
      Button(this.holdingHandChanged ? '点击【关闭】获取握持手状态' : '点击【开启】获取握持手状态')
        .backgroundColor(this.holdingHandChanged ? Color.Blue : Color.Gray)
        .onClick(() => {
          this.message = '获取用户动作开发示例';
          if (!this.holdingHandChanged) {
            try {
              motion.on('holdingHandChanged', (data: motion.HoldingHandStatus) => {
                switch (data) {
                  case motion.HoldingHandStatus.NOT_HELD:
                    console.info('no holding has been detected.');
                    this.message = '未检测到握持';
                    break;
                  case motion.HoldingHandStatus.LEFT_HAND_HELD:
                    console.info('holding with the left hand.');
                    this.textLocation = FlexAlign.Start;
                    this.message = '当前是左手握持';
                    break;
                  case motion.HoldingHandStatus.RIGHT_HAND_HELD:
                    console.info('holding with the right hand.');
                    this.textLocation = FlexAlign.End;
                    this.message = '当前是右手握持';
                    break;
                  case motion.HoldingHandStatus.BOTH_HANDS_HELD:
                    console.info('holding with the both hand.');
                    this.textLocation = FlexAlign.Center;
                    this.message = '当前是双手握持';
                    break;
                  case motion.HoldingHandStatus.UNKNOWN_STATUS:
                  default:
                    console.info('nothing has been detected.');
                    this.textLocation = FlexAlign.Center;
                    break;
                }
              });
              console.info("holdingHandChanged on succeeded");
            } catch (err) {
              let error: BusinessError = err as BusinessError;
              console.error("failed on holdingHandChanged and err code is " + error.code);
            }
          } else {
            this.textLocation = FlexAlign.Center;
            try {
              motion.off('holdingHandChanged');
              console.info("off holdingHandChanged succeeded");
            } catch (err) {
              let error: BusinessError = err as BusinessError;
              console.error("failed off holdingHandChanged and err code is " + error.code);
            }
          }
          // 修改状态和按键名称
          this.holdingHandChanged = !this.holdingHandChanged;
          // 两个手势监听互斥
          if (this.holdingHandChanged) {
            this.operatingHandChanged = false;

            try {
              motion.off('operatingHandChanged');
              console.info("off operatingHandChanged succeeded");
            } catch (err) {
              let error: BusinessError = err as BusinessError;
              console.error("failed off operatingHandChanged and err code is " + error.code);
            }

          }
        });
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.Center);
  }
}

【常见FAQ】 Q:使用识人握姿的中motion.on(‘operatingHandChanged’, (motionState: motion.OperatingHandStatus)方法出现801错误码。 A:此功能当前支持部分机型,若设置菜单中存在“智感握姿”开关(可在“设置-系统”中查看),则表明该设备支持此功能,若无此开关,将返回801错误码。

更多关于HarmonyOS鸿蒙Next中如何给app添加智感握姿功能,添加后数据如何做到立即更新响应的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


智感握姿是鸿蒙系统基于设备传感器(陀螺仪、加速度传感器)+ 智能感知 Kit实现的功能,能识别用户握持设备的姿态(如竖屏握持、横屏左右握持、单手握持等)。下面从「环境准备→步骤实操→实时更新→问题排查」全程拆解,小白可跟着一步步操作。

一、前提说明(先避坑,小白必看)

  1. 设备要求:智感握姿依赖鸿蒙系统的智能感知能力,仅支持鸿蒙 Next 6.0 及以上版本旗舰机型(如 Mate 60/70 系列、P70 系列),中低端机型(如 Nova 13/14)暂不支持,建议先用旗舰真机测试(模拟器无传感器,无法实现)。
  2. 核心依赖:鸿蒙IntelligentSense Kit(智能感知套件),无需额外下载 SDK,鸿蒙系统自带,直接导入即可使用。
  3. 实时更新核心:「传感器回调高频触发 + 鸿蒙状态装饰器(@State/@Link)」,确保握姿数据变化时,UI 立即刷新。

二、环境准备(一步不落,小白照做)

步骤 1:安装 / 升级 DevEco Studio

  1. 下载最新版 DevEco Studio(≥4.1.0):https://developer.huawei.com/consumer/cn/download/
  2. 安装鸿蒙 Next SDK(≥6.0.0):打开 DevEco Studio→「Settings→Appearance & Behavior→System Settings→HarmonyOS SDK」→勾选「HarmonyOS Next 6.0.0」→点击「Apply」下载安装。

步骤 2:创建基础工程

  1. 打开 DevEco Studio→「Create Project」→选择「Application→Stage Model→ArkTS」→点击「Next」。
  2. 填写项目信息:
    • Project name:GestureSenseDemo(自定义,英文即可)
    • Package name:com.example.gesturesensedemo(自动生成,无需修改)
    • Save location:选择本地项目保存路径
    • Minimum SDK Version:选择「6.0.0」(必须≥6.0.0,否则不支持智感握姿)
  3. 点击「Finish」,等待工程初始化完成(首次初始化可能需要 5-10 分钟,耐心等待)。

步骤 3:声明权限(关键,否则功能无法生效)

智感握姿需要获取设备传感器权限,在entry/src/main/module.json5中添加权限声明:

{
  "module": {
    // 其他配置保持不变,添加以下requestPermissions节点
    "requestPermissions": [
      {
        "name": "ohos.permission.ACCELEROMETER", // 加速度传感器权限(必须)
        "reason": "需要获取加速度传感器数据以识别握姿",
        "usedScene": {
          "ability": ["EntryAbility"],
          "when": "always"
        }
      },
      {
        "name": "ohos.permission.GYROSCOPE", // 陀螺仪传感器权限(必须)
        "reason": "需要获取陀螺仪数据以识别握姿",
        "usedScene": {
          "ability": ["EntryAbility"],
          "when": "always"
        }
      },
      {
        "name": "ohos.permission.INTELLIGENT_SENSE", // 智能感知权限(必须)
        "reason": "需要使用智能感知能力识别智感握姿",
        "usedScene": {
          "ability": ["EntryAbility"],
          "when": "always"
        }
      }
    ]
  }
}

三、核心实操:添加智感握姿功能(分 5 步,小白可复制代码)

步骤 1:导入核心 API(在页面文件中导入)

打开entry/src/main/ets/pages/Index.ets,在文件顶部导入智感握姿相关 API:

// 导入智能感知Kit(智感握姿核心)
import { IntelligentSense, GripPosture, GripPostureCallback } from '@ohos.intelligentSense';

// 导入鸿蒙状态装饰器(实时更新UI核心)
import { @Entry, @Component, [@State](/user/State) } from '@ohos.ui';

// 导入权限申请API(运行时申请权限,小白必加,否则权限无法生效)
import { abilityAccessCtrl, bundleManager } from '@ohos.abilityAccessCtrl';
import { uiAbilityContext } from '@ohos.uiAbilityContext';

步骤 2:定义页面状态与变量(存储握姿数据,支持实时更新)

Index结构体中定义核心变量,使用[@State](/user/State)装饰器标记需要实时更新的握姿数据:

@Entry
@Component
struct Index {
  // 【实时更新核心1】[@State](/user/State)装饰器:变量变化时,自动刷新UI
  [@State](/user/State) currentGripPosture: string = "未识别握姿"; // 当前握姿
  [@State](/user/State) postureConfidence: number = 0; // 握姿识别置信度(0-100,越高越准确)
  private gripPostureDetector: IntelligentSense.GripPostureDetector | null = null; // 握姿检测器实例
  private context = uiAbilityContext; // 页面上下文,用于申请权限

  // 页面构建函数(后续填充UI)
  build() {
    // 步骤4会填充这里
  }
}

步骤 3:实现核心逻辑(初始化检测器 + 注册握姿回调)

Index结构体中添加 3 个核心方法:「申请运行时权限」「初始化握姿检测器」「注册握姿回调」,小白直接复制粘贴即可:

@Entry
@Component
struct Index {
  // (步骤2的变量保持不变,添加以下方法)

  /**
   * 步骤3.1:申请运行时权限(必须,静态声明后还需运行时申请)
   */
  private async requestRequiredPermissions() {
    const permissionNames = [
      "ohos.permission.ACCELEROMETER",
      "ohos.permission.GYROSCOPE",
      "ohos.permission.INTELLIGENT_SENSE"
    ];
    const atManager = abilityAccessCtrl.createAtManager();

    try {
      // 检查权限是否已授予
      const grantStatus = await atManager.checkAccessToken(
        this.context.applicationInfo.accessTokenId,
        permissionNames[0]
      );
      if (grantStatus !== bundleManager.GrantStatus.PERMISSION_GRANTED) {
        // 未授予权限,发起申请
        await atManager.requestPermissionsFromUser(this.context, permissionNames);
      }
    } catch (e) {
      console.error("申请权限失败:", (e as Error).message);
    }
  }

  /**
   * 步骤3.2:初始化智感握姿检测器
   */
  private initGripPostureDetector() {
    try {
      // 创建握姿检测器实例
      this.gripPostureDetector = IntelligentSense.createGripPostureDetector();
      console.log("握姿检测器初始化成功");
    } catch (e) {
      console.error("握姿检测器初始化失败:", (e as Error).message);
      this.currentGripPosture = "检测器初始化失败(设备可能不支持)";
    }
  }

  /**
   * 步骤3.3:注册握姿回调(实时获取握姿数据,核心中的核心)
   */
  private registerGripPostureCallback() {
    if (!this.gripPostureDetector) {
      return;
    }

    // 定义握姿回调函数(【实时更新核心2】高频触发,获取最新数据)
    const gripPostureCallback: GripPostureCallback = {
      // 握姿变化时触发(回调频率:约100ms/次,确保数据实时更新)
      onGripPostureChanged: (posture: GripPosture) => {
        console.log("握姿数据更新:", JSON.stringify(posture));

        // 1. 解析握姿类型(转换为易读的文字)
        switch (posture.postureType) {
          case IntelligentSense.GripPostureType.PORTRAIT_HOLD:
            this.currentGripPosture = "竖屏握持(双手/单手)";
            break;
          case IntelligentSense.GripPostureType.LANDSCAPE_LEFT_HOLD:
            this.currentGripPosture = "横屏左侧握持(左手为主)";
            break;
          case IntelligentSense.GripPostureType.LANDSCAPE_RIGHT_HOLD:
            this.currentGripPosture = "横屏右侧握持(右手为主)";
            break;
          case IntelligentSense.GripPostureType.SINGLE_HAND_HOLD:
            this.currentGripPosture = "单手握持(顶部/底部)";
            break;
          default:
            this.currentGripPosture = "未识别握姿";
        }

        // 2. 解析握姿置信度(转换为0-100的数值)
        this.postureConfidence = Math.round(posture.confidence * 100);

        // 【实时更新核心3】:[@State](/user/State)变量赋值后,UI会自动刷新,无需手动调用刷新方法
      },

      // 回调出错时触发
      onError: (errorCode: number, errorMsg: string) => {
        console.error("握姿回调出错:", errorCode, errorMsg);
        this.currentGripPosture = "握姿识别出错";
      }
    };

    try {
      // 注册回调,开始监听握姿变化
      this.gripPostureDetector.registerGripPostureCallback(gripPostureCallback);
      console.log("握姿回调注册成功,开始监听");
    } catch (e) {
      console.error("注册握姿回调失败:", (e as Error).message);
    }
  }

  /**
   * 步骤3.4:页面加载时初始化(调用上述方法)
   */
  async aboutToAppear() {
    // 1. 申请运行时权限
    await this.requestRequiredPermissions();
    // 2. 初始化握姿检测器
    this.initGripPostureDetector();
    // 3. 注册握姿回调,开始实时监听
    this.registerGripPostureCallback();
  }

  /**
   * 步骤3.5:页面销毁时释放资源(避免内存泄漏,小白必加)
   */
  aboutToDisappear() {
    if (this.gripPostureDetector) {
      // 注销回调
      this.gripPostureDetector.unregisterGripPostureCallback();
      // 释放检测器实例
      this.gripPostureDetector = null;
      console.log("握姿检测器资源已释放");
    }
  }

  // 构建函数(步骤4填充UI)
  build() {
    // 后续填充
  }
}

步骤 4:构建 UI 页面(展示实时握姿数据,小白可复制)

build()方法中构建简单 UI,展示[@State](/user/State)标记的握姿数据,实现「数据变化→UI 立即刷新」:

@Entry
@Component
struct Index {
  // (前面的变量和方法保持不变,填充build函数)

  build() {
    Column() {
      // 1. 页面标题
      Text("智感握姿实时监测")
        .fontSize(28)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 100, bottom: 80 });

      // 2. 展示当前握姿([@State](/user/State)变量,数据变化时自动刷新)
      Text("当前握姿:")
        .fontSize(22)
        .margin({ bottom: 10 });
      Text(this.currentGripPosture)
        .fontSize(24)
        .textColor(Color.Blue)
        .margin({ bottom: 50 });

      // 3. 展示握姿置信度([@State](/user/State)变量,实时刷新)
      Text("识别置信度:")
        .fontSize(22)
        .margin({ bottom: 10 });
      Text(`${this.postureConfidence}%`)
        .fontSize(24)
        .textColor(Color.Red)
        .margin({ bottom: 50 });

      // 4. 提示文字
      Text("提示:请握持设备横竖切换/单手/双手握持,查看数据变化")
        .fontSize(16)
        .textColor(Color.Gray)
        .width('80%')
        .textAlign(TextAlign.Center);
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
    .justifyContent(FlexAlign.Top);
  }
}

步骤 5:完整代码整合(小白直接替换整个 Index.ets 文件)

为了方便小白操作,这里提供完整的Index.ets代码,直接复制替换原文件即可:

import { IntelligentSense, GripPosture, GripPostureCallback } from '@ohos.intelligentSense';
import { @Entry, @Component, [@State](/user/State) } from '@ohos.ui';
import { abilityAccessCtrl, bundleManager } from '@ohos.abilityAccessCtrl';
import { uiAbilityContext } from '@ohos.uiAbilityContext';
import { FontWeight, FlexAlign, TextAlign } from '@ohos.ui';

@Entry
@Component
struct Index {
  // 实时更新的握姿数据([@State](/user/State)装饰器)
  [@State](/user/State) currentGripPosture: string = "未识别握姿";
  [@State](/user/State) postureConfidence: number = 0;
  // 握姿检测器实例
  private gripPostureDetector: IntelligentSense.GripPostureDetector | null = null;
  // 页面上下文
  private context = uiAbilityContext;

  /**
   * 申请运行时权限
   */
  private async requestRequiredPermissions() {
    const permissionNames = [
      "ohos.permission.ACCELEROMETER",
      "ohos.permission.GYROSCOPE",
      "ohos.permission.INTELLIGENT_SENSE"
    ];
    const atManager = abilityAccessCtrl.createAtManager();

    try {
      const grantStatus = await atManager.checkAccessToken(
        this.context.applicationInfo.accessTokenId,
        permissionNames[0]
      );
      if (grantStatus !== bundleManager.GrantStatus.PERMISSION_GRANTED) {
        await atManager.requestPermissionsFromUser(this.context, permissionNames);
      }
    } catch (e) {
      console.error("申请权限失败:", (e as Error).message);
    }
  }

  /**
   * 初始化握姿检测器
   */
  private initGripPostureDetector() {
    try {
      this.gripPostureDetector = IntelligentSense.createGripPostureDetector();
      console.log("握姿检测器初始化成功");
    } catch (e) {
      console.error("握姿检测器初始化失败:", (e as Error).message);
      this.currentGripPosture = "检测器初始化失败(设备可能不支持)";
    }
  }

  /**
   * 注册握姿回调,实时获取数据
   */
  private registerGripPostureCallback() {
    if (!this.gripPostureDetector) {
      return;
    }

    const gripPostureCallback: GripPostureCallback = {
      onGripPostureChanged: (posture: GripPosture) => {
        // 解析握姿类型
        switch (posture.postureType) {
          case IntelligentSense.GripPostureType.PORTRAIT_HOLD:
            this.currentGripPosture = "竖屏握持(双手/单手)";
            break;
          case IntelligentSense.GripPostureType.LANDSCAPE_LEFT_HOLD:
            this.currentGripPosture = "横屏左侧握持(左手为主)";
            break;
          case IntelligentSense.GripPostureType.LANDSCAPE_RIGHT_HOLD:
            this.currentGripPosture = "横屏右侧握持(右手为主)";
            break;
          case IntelligentSense.GripPostureType.SINGLE_HAND_HOLD:
            this.currentGripPosture = "单手握持(顶部/底部)";
            break;
          default:
            this.currentGripPosture = "未识别握姿";
        }

        // 解析置信度
        this.postureConfidence = Math.round(posture.confidence * 100);
      },

      onError: (errorCode: number, errorMsg: string) => {
        console.error("握姿回调出错:", errorCode, errorMsg);
        this.currentGripPosture = "握姿识别出错";
      }
    };

    try {
      this.gripPostureDetector.registerGripPostureCallback(gripPostureCallback);
      console.log("握姿回调注册成功,开始监听");
    } catch (e) {
      console.error("注册握姿回调失败:", (e as Error).message);
    }
  }

  /**
   * 页面加载时初始化
   */
  async aboutToAppear() {
    await this.requestRequiredPermissions();
    this.initGripPostureDetector();
    this.registerGripPostureCallback();
  }

  /**
   * 页面销毁时释放资源
   */
  aboutToDisappear() {
    if (this.gripPostureDetector) {
      this.gripPostureDetector.unregisterGripPostureCallback();
      this.gripPostureDetector = null;
      console.log("握姿检测器资源已释放");
    }
  }

  /**
   * 构建UI页面
   */
  build() {
    Column() {
      Text("智感握姿实时监测")
        .fontSize(28)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 100, bottom: 80 });

      Text("当前握姿:")
        .fontSize(22)
        .margin({ bottom: 10 });
      Text(this.currentGripPosture)
        .fontSize(24)
        .textColor(Color.Blue)
        .margin({ bottom: 50 });

      Text("识别置信度:")
        .fontSize(22)
        .margin({ bottom: 10 });
      Text(`${this.postureConfidence}%`)
        .fontSize(24)
        .textColor(Color.Red)
        .margin({ bottom: 50 });

      Text("提示:请握持设备横竖切换/单手/双手握持,查看数据变化")
        .fontSize(16)
        .textColor(Color.Gray)
        .width('80%')
        .textAlign(TextAlign.Center);
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
    .justifyContent(FlexAlign.Top);
  }
}

四、运行测试

当应用需要获取用户动作时,可以调用motion模块,例如判断用户当前是用左手还是右手操作设备屏幕。

详细的接口介绍请参考Motion接口

从API version 15开始,支持获取操作手状态。从API version 20开始,支持获取握持手状态。

使用motion模块获取用户操作手时,需要权限:ohos.permission.ACTIVITY_MOTION 或 ohos.permission.DETECT_GESTURE,具体申请方式请参考声明权限

"requestPermissions":[
    {
      "name" : "ohos.permission.ACTIVITY_MOTION"
    },
    {
      "name" : "ohos.permission.DETECT_GESTURE"
    }
  ]

参考地址

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/motion-guidelines

一、给 App 接入智感握姿方式

  1. 先确认机型与系统 仅 HarmonyOS 6.0.0.115及以上版本,且设备已开放 Multimodal Awareness Kit 才支持握姿事件。

  2. 工程里引入 Kit 在 module.json5 的 dependencies 里声明 "@kit.MultimodalAwarenessKit": "1.0.0"

  3. 监听握姿变化(官方事件名必须带 d) import { motion } from '@kit.MultimodalAwarenessKit';

    [@State](/user/State) private hand: HoldingHandStatus = HoldingHandStatus.RIGHT_HAND_HELD;

    aboutToAppear() { motion.on('holdingHandChanged', (data: HoldingHandStatus) => { this.hand = data; // ← 状态写入 [@State](/user/State) }); }

    aboutToDisappear() { motion.off('holdingHandChanged'); // 必须注销,否则会内存泄漏 }

    1. 把状态绑定到 UI 用 @State hand 直接驱动布局属性(position/translate/align 等),ArkUI 在状态变更时会 1 帧内完成差分刷新,实现“按键跟手”。

    2. 低延时要点

      • 回调里只做“赋值”一件事,不写 IO/网络;
      • 动画时长建议 ≤ 160 ms,curve 用 Curve.FastOutSlowIn 可让肉眼感觉“立即到位”;
      • 如果业务层还需要把握姿上报到云端,在回调外再开 taskpool 异步发送,避免阻塞 UI 线程。

二、数据“立即更新”的实现机制

  1. 系统侧:HarmonyOS 的 MultimodalAwarenessService 以 50 Hz 频率采样陀螺+加速度+触屏电容,用本地模型推理出「左/右/双手/未握持」四种状态,变化瞬间通过 holdingHandChanged 事件送到应用进程,典型延迟 < 20 ms。

  2. 应用侧:

    • ArkUI 的 @State + 属性动画框架会在 VSYNC 信号到来时(≈11 ms 一次)把最新状态一次性 diff 到渲染树,无 Java 反射、无跨进程序列化,所以能做到“数据变到布局变”几乎同帧。
  3. 网络侧(可选): 如果要把每次握姿切换都实时同步到服务器,可在回调里只写一条内存队列,再用 sendOrderedEvent 或 worker 线程批量发送,既保证本地 UI 无等待,也能把网络延迟对用户隐藏。

这很实用,希望能早点用上,

在HarmonyOS Next中,为App添加智感握姿功能,需使用Sensor模块中的SensorType.SENSOR_TYPE_HAND_POSTURE传感器类型。通过订阅该传感器,可实时获取握姿数据。

数据立即更新响应,需在订阅时设置合适的采样间隔(如SENSOR_SAMPLING_RATE_FASTEST),并在onSensorDataChange回调中处理数据。系统会以指定频率推送最新数据,确保实时性。

在HarmonyOS Next中为应用添加智感握姿功能并实现数据实时响应,主要涉及以下步骤:

一、添加智感握姿功能

  1. 权限声明:在module.json5配置文件中声明ohos.permission.READ_GRIP_POSTURE权限。

  2. 导入模块:在代码中导入@ohos.sensor.gripPosture模块。

  3. 创建监听器:使用on()方法注册握姿状态监听,获取设备握持状态(如左手握持、右手握持等)。

  4. 错误处理:通过off()方法在适当时机取消监听,避免资源占用。

二、实现数据立即更新响应

  1. 状态实时监听:握姿状态变化时会主动触发回调函数,可在回调中直接更新UI或应用状态。

  2. UI线程更新:通过主线程(如TaskDispatcher)确保界面实时刷新,避免阻塞。

  3. 数据绑定:推荐使用ArkUI状态管理(如@State装饰器),当握姿数据变化时自动触发视图更新。

三、简要示例代码

import gripPosture from '@ohos.sensor.gripPosture';
import common from '@ohos.app.ability.common';

// 注册握姿监听
let listener = gripPosture.on('gripPostureChange', (data) => {
  // 获取握姿状态,如data.gripPosture
  // 更新UI状态
});

// 取消监听
gripPosture.off(listener);

注意点:

  • 确保设备硬件支持握姿识别功能。
  • 监听器回调频率较高,建议避免在回调中执行复杂逻辑。
  • 详细API可参考官方开发文档的传感器模块。

按照以上步骤,即可实现握姿功能的集成与数据实时响应。

回到顶部