【HarmonyOS】应用振动效果实现

一、问题背景:

应用在强提醒场景下,一般会有马达振动的效果,提示用户注意力的关注。

比如消息提醒,扫码提示,删除键确认提示等。

针对高定制化或者固定的振动方式,我们需要有不同的方案实现,马达振动效果。

二、解决方案:

鸿蒙针对振动效果的实现,有多种方案,目前分为振动和音振协同两种方式。

单纯的只是振动,又分为三种方式:

  1. 系统定制的振动方式,例如闹钟
  2. 非系统定制,自定义振动配置json文件的方式
  3. 线性马达振动,只需要设置时间和强度(最简单的调用方式)

音振协同一般用于,音效播放和振动同时的场景,例如扫码。

1.首先需要配置振动权限,该权限是系统权限,只需要配置后,默认就会被授权。

ohos.permission.VIBRATE

2.之后根据需要实现不同的马达振动效果,方案调用详情参见下方代码示例的注释。

三、DEMO示例:

dart 复制代码
import vibrator from '@ohos.vibrator';
import { BusinessError } from '@ohos.base';
import { resourceManager } from '@kit.LocalizationKit';

/**
 * 振动管理类
 * 需要权限: ohos.permission.VIBRATE
 */
export class HapticMgr {
  private TAG: string = 'HapticMgr';

  private static mHapticMgr: HapticMgr | undefined = undefined;

  public static Ins(): HapticMgr{
    if(!HapticMgr.mHapticMgr){
      HapticMgr.mHapticMgr = new HapticMgr();
    }
    return HapticMgr.mHapticMgr;
  }

  /**
   * 按照指定持续时间触发马达振动
   */
  public timeVibration(){
    try {
      // 触发马达振动
      vibrator.startVibration({
        type: 'time',
        duration: 1000,
      }, {
        id: 0,
        usage: 'alarm'
      }, (error: BusinessError) => {
        if (error) {
          console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`);
          return;
        }
        console.info('Succeed in starting vibration');
      });
    } catch (err) {
      let e: BusinessError = err as BusinessError;
      console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
    }
  }

  /**
   * 按照预置振动效果触发马达振动,可先查询振动效果是否被支持,再调用振动接口
   */
  public typeVibration(){

    try {
      // 查询是否支持'haptic.clock.timer'
      vibrator.isSupportEffect('haptic.clock.timer', (err: BusinessError, state: boolean) => {
        if (err) {
          console.error(`Failed to query effect. Code: ${err.code}, message: ${err.message}`);
          return;
        }
        console.info('Succeed in querying effect');
        if (state) {
          try {
            // 触发马达振动
            vibrator.startVibration({
              type: 'preset',
              effectId: 'haptic.clock.timer',
              count: 1,
            }, {
              usage: 'unknown'
            }, (error: BusinessError) => {
              if (error) {
                console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`);
              } else {
                console.info('Succeed in starting vibration');
              }
            });
          } catch (error) {
            let e: BusinessError = error as BusinessError;
            console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
          }
        }
      })
    } catch (error) {
      let e: BusinessError = error as BusinessError;
      console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
    }
  }

  public fileVibration(){
    const fileName: string = 'vibration.json';

    // 获取文件资源描述符
    let rawFd: resourceManager.RawFileDescriptor = getContext().resourceManager.getRawFdSync(fileName);

    // 触发马达振动
    try {
      vibrator.startVibration({
        type: "file",
        hapticFd: { fd: rawFd.fd, offset: rawFd.offset, length: rawFd.length }
      }, {
        id: 0,
        usage: 'alarm'
      }, (error: BusinessError) => {
        if (error) {
          console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`);
          return;
        }
        console.info('Succeed in starting vibration');
      });
    } catch (err) {
      let e: BusinessError = err as BusinessError;
      console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
    }

    // 关闭文件资源描述符
    getContext().resourceManager.closeRawFdSync(fileName);
  }

  /**
   * 按照指定模式停止对应的马达振动,自定义振动不支持此类停止方式
   */
  public stopVibrationByType(){
    //  停止固定时长振动
    try {
      // 按照VIBRATOR_STOP_MODE_TIME模式停止振动
      vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_TIME, (error: BusinessError) => {
        if (error) {
          console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`);
          return;
        }
        console.info('Succeed in stopping vibration');
      })
    } catch (err) {
      let e: BusinessError = err as BusinessError;
      console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
    }

    // 停止预置振动:
    try {
      // 按照VIBRATOR_STOP_MODE_PRESET模式停止振动
      vibrator.stopVibration(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_PRESET, (error: BusinessError) => {
        if (error) {
          console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`);
          return;
        }
        console.info('Succeed in stopping vibration');
      })
    } catch (err) {
      let e: BusinessError = err as BusinessError;
      console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
    }

  }

  /**
   * 停止所有模式的马达振动,包括自定义振动:
   */
  public stopVibration(){
    try {
      // 停止所有模式的马达振动
      vibrator.stopVibration((error: BusinessError) => {
        if (error) {
          console.error(`Failed to stop vibration. Code: ${error.code}, message: ${error.message}`);
          return;
        }
        console.info('Succeed in stopping vibration');
      })
    } catch (error) {
      let e: BusinessError = error as BusinessError;
      console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`);
    }
  }


}

振动配置文件:

dart 复制代码
{
  "MetaData": {
    "Create": "2023-01-09",
    "Description": "a haptic case",
    "Version": 1.0,
    "ChannelNumber": 1
  },
  "Channels": [
    {
      "Parameters": {
        "Index": 0
      },
      "Pattern": [
        {
          "Event": {
            "Type": "transient",
            "StartTime": 0,
            "Parameters": {
              "Frequency": 31,
              "Intensity": 100
            }
          }
        },
        {
          "Event": {
            "Type": "continuous",
            "StartTime": 40,
            "Duration": 54,
            "Parameters": {
              "Frequency": 30,
              "Intensity": 38,
              "Curve": [
                {
                  "Time": 0,
                  "Frequency": 0,
                  "Intensity": 0
                },
                {
                  "Time": 1,
                  "Frequency": 15,
                  "Intensity": 0.5
                },
                {
                  "Time": 40,
                  "Frequency": -8,
                  "Intensity": 1.0
                },
                {
                  "Time": 54,
                  "Frequency": 0,
                  "Intensity": 0
                }
              ]
            }
          }
        }
      ]
    }
  ]
}
相关推荐
AORO_BEIDOU2 小时前
单北斗+鸿蒙系统+国产芯片,遨游防爆手机自主可控“三保险”
华为·智能手机·harmonyos
博览鸿蒙4 小时前
鸿蒙操作系统(HarmonyOS)的应用开发入门
华为·harmonyos
Damon小智11 小时前
HarmonyOS NEXT 技术实践-基于基础视觉服务的多目标识别
华为·harmonyos
匹马夕阳13 小时前
华为笔记本之糟糕的体验
华为·笔记本电脑
egekm_sefg13 小时前
华为、华三交换机纯Web下如何创关键VLANIF、操作STP参数
网络·华为
岳不谢1 天前
华为DHCP高级配置学习笔记
网络·笔记·网络协议·学习·华为
爱笑的眼睛111 天前
uniapp 极速上手鸿蒙开发
华为·uni-app·harmonyos
K.P1 天前
鸿蒙元服务从0到上架【第三篇】(第二招有捷径)
华为·harmonyos·鸿蒙系统
K.P1 天前
鸿蒙元服务从0到上架【第二篇】
华为·harmonyos·鸿蒙系统
敲代码的小强1 天前
Flutter项目兼容鸿蒙Next系统
flutter·华为·harmonyos