【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
                }
              ]
            }
          }
        }
      ]
    }
  ]
}
相关推荐
Random_index4 小时前
#Uniapp篇:支持纯血鸿蒙&发布&适配&UIUI
uni-app·harmonyos
鸿蒙自习室8 小时前
鸿蒙多线程开发——线程间数据通信对象02
ui·harmonyos·鸿蒙
SuperHeroWu710 小时前
【HarmonyOS】鸿蒙应用接入微博分享
华为·harmonyos·鸿蒙·微博·微博分享·微博sdk集成·sdk集成
期待未来的男孩10 小时前
华为FusionCube 500-8.2.0SPC100 实施部署文档
华为
岳不谢12 小时前
VPN技术-VPN简介学习笔记
网络·笔记·学习·华为
zhangjr057512 小时前
【HarmonyOS Next】鸿蒙实用装饰器一览(一)
前端·harmonyos·arkts
Industio_触觉智能14 小时前
如何在开源鸿蒙OpenHarmony开启SELinux模式?RK3566鸿蒙开发板演示
openharmony·selinux·开源鸿蒙·鸿蒙开发板·rk3566开发板
诗歌难吟46419 小时前
初识ArkUI
harmonyos
SameX19 小时前
HarmonyOS Next 设备安全特性深度剖析学习
harmonyos
郭梧悠21 小时前
HarmonyOS(57) UI性能优化
ui·性能优化·harmonyos