【HarmonyOS】应用振动效果实现

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

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

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

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

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

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

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

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

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

三、DEMO示例:

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}`);
    }
  }


}

振动配置文件:
在这里插入图片描述

{
  "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
                }
              ]
            }
          }
        }
      ]
    }
  ]
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/678737.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【已解决】c++ QT继承基类界面页面丢失问题

本博文源于自己在工位上遇到的一个问题,这个问题不只犯了一次了。首先我继承CBaseDialog里的一个标题栏,结果发现,界面本来想这样结果变成这样: 结果变成这个样子: 问题原因 在于ui.setupUi这个层面,错…

C语言王国——字符函数和字符串函数(2)

目录 5 strtok函数 5.1 函数的表达式 5.2 函数模拟 6 strstr函数 6.1 函数表达式 7 strerror函数 7.1 函数表达式 7.2 例子 7.3 perror 8 strncpy、strncat、strncmp函数 四 结论 5 strtok函数 strtok函数我的理解是他是一个分割字符串的函数 5.1 函数的表达式 cha…

光伏无人机踏勘需要使用哪些设备?用到哪些原理?

随着全球能源结构的转型和绿色能源的大力推广,光伏电站的建设和运维正成为能源领域的热点。然而,光伏电站的选址、建设和后期运维过程中,往往面临着地形复杂、设备分散、巡检难度大等挑战。在这一背景下,无人机踏勘技术以其独特的…

最新 Navicat Data Modeler 4 | 产品介绍

在过去的几周里,我们已经介绍了 Navicat 版本 17,现在我们来把注意力转移到另外两个值得关注的产品上,即 Navicat Data Modeler 和 Navicat BI(之前称为 Navicat Chart Creator)。今天的博客将介绍 Navicat Data Model…

draw.io 如何设置图形圆角?

draw.io 如何设置图形圆角呢? draw.io 是一款强大的,免费的开源工具,我经常用它来画流程图,但是我发现 draw.io 对于图形圆角的设置,只提供了一个设置选项,如下图: 当你选中某个图形&#xff0…

go语言进阶 init() 函数

go 语言包 在一个项目中通常我们需要引入第三方包,我们来看下 当我们导入一个包的时候 发生了什么: 首先我们先详细介绍下两个函数: init(), main() 是 go 语言中的保留函数。我们可以在源码中 定义 init()函数, 此函数会在包导入…

谷粒商城实战(031 业务-秒杀功能2)

Java项目《谷粒商城》架构师级Java项目实战,对标阿里P6-P7,全网最强 总时长 104:45:00 共408P 此文章包含第315p-第p318的内容 秒杀上架 定时上架功能 EnableAsync 异步 EnableScheduling 定时调度 Configuration 配置类 创建上架定时任务类和方法 …

抖店商家疑惑,自然流量突然下滑,为什么呢?

大家好,我是喷火龙。 很多的抖店商家会遇到一种情况,那就是自己店铺的流量好好的,不知道怎么的就突然没流量了,各方面的数据都断崖式的下降。 为什么会这样呢?原因有以下几点,大家可以检查一下&#xff0…

Typora配置自动上传图片到图床

Typora配置自动上传图片到图床 在多平台发布文章时,如果遇到图片不能导入的问题,推荐使用图床!推荐使用阿里云或腾讯云,免费的不用考虑了! PicGo下载 链接:夸克网盘分享 使用手册: PicGo is…

《python开发》cannot allocate memory in static TLS block-报错问题解决

阿丹: 今天在配置跑rasa训练的时候出现问题,找了国内论坛有解决的人,但是说的不明白。查阅了很多论坛之后发现了解决的方案。 https://github.com/keras-team/keras-tuner/issues/317 问题描述以及错误: 关键错误 :c…

升级最新版openssh-9.7p1及openssl-1.1.1h详细步骤及常见问题总结

近期因为openssh相继被漏洞扫描工具扫出存在漏洞,所以考虑升级操作系统中的openssh和openssl为最新版本,来避免漏洞风险。期间的升级过程及遇到的疑难问题,特此记录下来,供有需要的人参考。 本次目标是升级 openssh 为 9.7p1 版本…

ios v品会 api-sign算法

vip品会 api-sign算法还原 ios入门案例 视频系列 IOS逆向合集-前言哔哩哔哩bilibili 一、ios难度与安卓对比 这里直接复制 杨如画大佬的文章的内容: ios难度与安卓对比 很多人说ios逆向比安卓简单,有以下几个原因 1 首先就是闭源,安卓开源…

UIScrollView代理

场景: 想要监控某组件,可以通过addTarget,但是复杂一点的,如UIScrollView的滚动监听就需要通过代理来实现了。代理本质是官方定义好的协议(接口),你只要用官方给出的API接口,就能实…

osg库的下载和安装

下载 下载地址:https://github.com/openscenegraph/OpenSceneGraph 安装 打开Cmake.exe,将上述下载的osg文件下的CMakeLists.txt文件拖入Cmake界面中。 在其路径下新建一个build文件 并配置cmake,点击Configure 修改如下几个选项 ACTUAL_3RDPARTY_DIR BUILD_OSG_EXAM…

Open vSwitch 数据包转发

一、数据包转发流程 Open vSwitch 数据包转发流程如下图所示,其中红色数字序号表示数据包转发的步骤顺序。 以下步骤为一个数据包通过 OVS 时的首次处理流程:(步骤序号和图中序号一一对应) OVS 从设备接口中获取数据包并交…

GitHub狂揽6700 Star,Python进阶必备的案例、技巧与工程实践

当下是 Python 急剧发展的时代,越来越多的人开始学习和使用Pyhon,而大家也遇到了各种问题。这份手册清晰、细致地介绍了 Python 代码应该遵循的编程风格,并解释了背后的原理和机制。 入门 Python 语言相对简单,但写出优雅的代码并…

营造科技展厅主题氛围,多媒体应用有哪些新策略?

长久以来,展厅作为线下向公众传递信息的窗口,其设计风格与内容主题紧密相连,展现出千姿百态的面貌。然而,随着数字多媒体技术的日新月异,展厅不再仅仅是传统的信息展示平台,而是成为了引领内容展示潮流的风…

技术积累1:Java容错机制

如何优雅地重试 原创 赵九文 字节跳动技术团队 2021-01-05 10:01 背景 在微服务架构中,一个大系统被拆分成多个小服务,小服务之间大量 RPC 调用,经常可能因为网络抖动等原因导致 RPC 调用失败,这时候使用重试机制可以提高请求的…

git获取的项目无法运行

一、Unsupported engine 问题:在使用命令npm install下载依赖项的时候就遇到了这个问题,有帖子说多试几次,其实这是提示node版本问题,版本的更新出现兼容性问题,多试几次也没用。 解决方案: 更新node.js的…

HiWoo Cloud数据采集监控系统

在数字化、智能化的浪潮中,企业如何高效地管理其设备、优化生产流程、提升运营效率?答案或许就隐藏在HiWoo Cloud——这款数据采集监控系统中。今天,就让我们一起走进HiWoo Cloud的世界,探索它如何助力企业实现数字化转型&#xf…