【HarmonyOS】鸿蒙应用实现音效播放

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

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

在鸿蒙应用如何实现音效播放呢?

二、解决方案:

使用AVPlayer实现本地音效资源的播放。

该播放器功能很丰富,目前只针对于音效播放进行展开。

播放的全流程包含:创建AVPlayer,设置播放资源,设置播放参数(音量/倍速/焦点模式),播放控制(播放/暂停/跳转/停止),重置,销毁资源。

状态切换处理流程图
开发详细步骤说明:

  1. 首先创建实例createAVPlayer(),AVPlayer初始化idle状态。

  2. 注册状态变化回调和错误回调

  3. 加载本地音效文件资源

  4. 设置变化状态,提供播放接口

  5. 音效文件比较短,默认播放完不做任何处理。若播放长时间音乐文件,可在状态回调里处理

需要注意的是,当音效文件设置完成后,只有调用play才会正常播放。


ps: 其实关于音效和振动同时处理,官方有音振协同的API进行实现,但是该API目前调用资源,例如音效文件和自定义振动配置文件的方式不太友好,不能从应用沙箱raw下读取,所以推荐分开实现的方式。


三、DEMO示例:

DEMO讲解通过注释的方式表明。若有不清楚的点,可关注私信我沟通。

音效播放管理类

import { media } from '@kit.MediaKit';
import { BusinessError } from '@kit.BasicServicesKit';

/**
 * 音效播放管理类
 */
export class AudioMgr {
  private TAG: string = 'AudioMgr';

  // 单例对象
  private static mAudioMgr: AudioMgr | null = null;

  // 播放器实例
  private mAVPlayer: media.AVPlayer | undefined = undefined;

  // 是否初始化
  private isInit: boolean = false;

  // 创建单例
  public static Ins(): AudioMgr{
    if(!AudioMgr.mAudioMgr){
      AudioMgr.mAudioMgr = new AudioMgr();
    }
    return AudioMgr.mAudioMgr;
  }

  /**
   * 初始化接口(可以提前初始化,也可以直接调用play接口,使用时初始化)
   */
  private async init(){
    // 创建avPlayer实例对象
    this.mAVPlayer = await media.createAVPlayer();
    // 创建状态机变化回调函数
    this.registerStateChange(this.mAVPlayer);
    // error回调监听函数,当avPlayer在操作过程中出现错误时调用 reset接口触发重置流程
    this.registerErrorCall(this.mAVPlayer);
    // 获取raw音效资源 设置属性url,AVPlayer进入initialized状态。
    let fileDescriptor = await getContext(this).resourceManager.getRawFd("test.mp3");
    this.mAVPlayer.fdSrc = {
        fd: fileDescriptor.fd,
        offset: fileDescriptor.offset,
        length: fileDescriptor.length
    };
    this.isInit = true;
  }

  /**
   * 注册异常回调
   * @param avPlayer
   */
  private registerErrorCall(avPlayer: media.AVPlayer){
    avPlayer.on('error', (err: BusinessError) => {
      console.log(this.TAG, " err:" + JSON.stringify(err));
      // 调用reset重置资源,触发idle状态
      avPlayer.reset();
    })
  }

  /**
   * 注册状态变化回调
   * @param avPlayer
   */
  private registerStateChange(avPlayer: media.AVPlayer){
    avPlayer.on('stateChange', async (state: string, reason: media.StateChangeReason) => {

      switch (state) {
        // 成功调用reset接口后触发该状态机上报
        case 'idle':
          console.info(this.TAG, 'stateChange idle-release');
          avPlayer.release(); // 调用release接口销毁实例对象
          break;

        // avplayer 设置播放源后触发该状态上报
        case 'initialized':
          console.info(this.TAG, 'stateChange initialized-prepare');
          avPlayer.prepare();
          break;

        // prepare调用成功后上报该状态机
        case 'prepared':
          console.info(this.TAG, 'stateChange prepared-setVolume');
          avPlayer.setVolume(1); // The value ranges from 0.00 to 1.00.
          avPlayer.play(); // 调用播放接口开始播放
          break;

        // play成功调用后触发该状态机上报
        case 'playing':
          console.info(this.TAG, 'stateChange playing');
          break;

        // pause成功调用后触发该状态机上报
        case 'paused':
          console.info(this.TAG, 'stateChange paused');
          break;

        // 播放结束后触发该状态机上报
        case 'completed':
          console.info(this.TAG, 'stateChange completed');
          break;

        // stop接口成功调用后触发该状态机上报
        case 'stopped':
          console.info(this.TAG, 'stateChange stopped');
          // avPlayer.reset(); // 调用reset接口初始化avplayer状态
          break;

        case 'released':
          console.info(this.TAG, 'stateChange released');
          break;

        default:
          console.info(this.TAG, 'stateChange default');
          break;
      }
    });
  }

  /**
   * 播放音效
   */
  public async play(){
    if(this.isInit){
      await this.init();
      this.mAVPlayer?.play();
    }else{
      this.mAVPlayer?.play();
    }
  }

  /**
   * 销毁音效管理工具
   */
  public destroy(){
    this.mAVPlayer?.release();
    AudioMgr.mAudioMgr = null;
  }

}

音效播放测试页

import { promptAction } from '@kit.ArkUI'
import { BusinessError } from '@kit.BasicServicesKit';
import { AudioMgr } from '../../mgr/AudioMgr';

/**
 * 音效播放
 */


struct AudioPage {

  private TAG: string = "AudioPage";

  onClickDestroy= ()=>{
    AudioMgr.Ins().destroy();
    this.showToast("销毁音效工具!");
  }

  onClickInit = ()=>{
    AudioMgr.Ins().init();
    this.showToast("初始化音效工具!");
  }

  onClickPlay = ()=>{
    AudioMgr.Ins().play();
    this.showToast("播放音效!");
  }

  private showToast(content: string){
    try {
      promptAction.showToast({
        message: content,
        duration: 2000
      });
    } catch (error) {
      let message = (error as BusinessError).message
      let code = (error as BusinessError).code
      console.error(this.TAG, `showToast args error code is ${code}, message is ${message}`);
    };
  }

  /**
   * 统一样式封装
   */
   ButtonStyle(){
    .width(px2vp(350))
    .height(px2vp(200))
    .margin({ top: px2vp(66) })
  }

  build() {
    Column(){
      Button("初始化音效工具")
        .ButtonStyle()
        .onClick(this.onClickInit)

      Button("播放音效")
        .ButtonStyle()
        .onClick(this.onClickPlay)

      Button("销毁音效工具")
        .ButtonStyle()
        .onClick(this.onClickDestroy)

    }.size({
      width: "100%",
      height: "100%"
    })
  }

}

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

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

相关文章

园区运营管理平台的功能架构

产业园区作为推动地方经济发展的重要载体,其运营管理水平直接影响到园区的竞争力和可持续发展能力,园区运营管理平台作为园区的运营管理工具,旨在通过智能化、自动化的手段提升园区的运营效率和服务水平。 园区运营管理平台不仅为园区管理者提…

45-3 护网溯源 - 为什么要做溯源工作

官网:CVERC-国家计算机病毒应急处理中心 西工大遭网络攻击再曝细节!13名攻击者身份查明→ (baidu.com) 护网溯源是指通过技术手段追踪网络攻击的来源和行为,其重要性体现在以下几个方面: 安全防御:了解攻击源头可以帮助组织加强网络安全防御,及时采取措施防止攻击的再次…

A股冲高回落,金属、地产板块领跌,新股N汇成真首日暴涨753%

行情概述 AH股有色金属、教育及地产板块领跌,军工航天及半导体板块逆势走强;锂电池、创新药概念股也走强。创业板新股N汇成真首日暴涨753%,触发二次临停。 周三A股冲高回落,上证指数收跌0.83%,深成指跌0.8%&#xff…

爬楼梯——动态规划第一步

本问题其实常规解法可以分成多个子问题,爬第 n 阶楼梯的方法数量,等于两个部分之和 爬上 n−1 阶楼梯的方法数量。因为再爬 1 阶就能到第 n 阶爬上 n−2 阶楼梯的方法数量,因为再爬 2 阶就能到第 n 阶 所以我们得到公式 dp[n] dp[n−1] d…

Windows下Qt5.14.2连接华为IoTDA平台

一、华为IoTDA简介 华为云物联网平台(IoT 设备接入云服务)提供海量设备的接入和管理能力,将物理设备联接到云,支撑设备数据采集上云和云端下发命令给设备进行远程控制,配合华为云其他产品,帮助您快速构筑物…

力扣200. 岛屿数量(BFS)

Problem: 200. 岛屿数量 文章目录 题目描述思路及解法复杂度Code 题目描述 思路及解法 1.定义方向数组:定义一个方向数组 DIRECTIONS,表示上、下、左、右四个方向的移动。 2.获取网格的行数和列数同时初始化一个计数器 numIslands 用于记录岛屿的数量。 …

【新书上市】图像画质算法与底层视觉技术

图书主页:https://book.douban.com/subject/36895899/ 购买链接:https://item.jd.com/10105601481762.html 内容介绍 本书主要介绍了图像画质相关的各类底层视觉任务及其相关算法,重点讲解了去噪、超分辨率、去雾、高动态范围、图像合成与图…

计算机网络 —— 数据链路层(无线局域网)

计算机网络 —— 数据链路层(无线局域网) 什么是无线局域网IEEE 802.11主要标准及其特点: 802.11的MAC帧样式 我们来看看无线局域网: 什么是无线局域网 无线局域网(Wireless Local Area Network,简称WLAN…

LLM之RAG实战(三十九)| 高级RAG技术全面解析(附代码)

一、高级RAG概述 基本 RAG 的工作流程可分为三个步骤:索引、检索和生成。在索引阶段,文本被转换为嵌入,然后存储在向量数据库中以创建可搜索的索引。在检索步骤中,用户的查询也被转换为嵌入,此嵌入用于在向量数据库中搜…

为什么3D渲染有的模型是黑的?---模大狮模型网

在3D建模和渲染的过程中,遇到模型渲染出来是黑色的情况并不罕见。这可能是由于多种原因导致的,包括但不限于材质设置问题、灯光配置不当、渲染设置错误等。 一、材质设置问题 材质丢失或错误:如果模型在导入或创建时材质没有正确加载或设置&…

力扣 54.螺旋矩阵

题目描述: 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 示例 1: 输入:matrix [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,2,3,6,9,8,7,4,5]示例 2: 输入&#…

[SaaS] AI+数据,tiktok选品,找达人,看广告数据

TK观察专访丨前阿里“鲁班”创始人用AIGC赋能TikTok获千万融资用AI数据做TikTokhttps://mp.weixin.qq.com/s/xp5UM3ROo48DK4jS9UBMuQ主要还是爬虫做数据的。 商家做内容:1.找达人拍内容,2.商家自己做原生自制内容,3.广告内容。 短视频&…

MariaDB数据导入与导出操作演示

文章目录 整个数据库导出导入先删除库然后再导入 参考这里: MariaDB数据库导出导入. 整个数据库 该部分演示:导出数据库,然后重建数据库,并导入数据的整个过程。 导出 Win R ,打开运行输入cmd并回车,然…

chatglm3-6b小试

原本想在VMware中装个unbutu,再搞chatglm,但经过调研发现业内都是采用双系统来搞chat的开发。于是只好用rufus制作了一个ubuntu22.04的系统盘,你需要准备8G,因为制作好镜像后是7个多G。安装这里就不说了。 1 ubuntu环境 安装好ubu…

python基础篇(2):字符串扩展知识点

1 字符串的三种定义方式 字符串在Python中有多种定义形式: (1)单引号定义法 name 博主帅绝上下五千年 print(name) print(type(name)) 效果如下: (2)双引号定义法 name "博主帅绝上下五千年&qu…

CUDA12.0 + cuDNN9.0.0安装

目录 1. 查看显卡支持的CUDA版本1.1 指令查看1.2 控制面板查看 2. 安装CUDA2.1 下载2.2 安装2.3 验证 3. 安装cuDNN3.1 下载3.2 安装3.2 验证 1. 查看显卡支持的CUDA版本 1.1 指令查看 打开cmd输入nvidia-smiDriver Version表示显卡驱动版本,CUDA Version表示支持…

【AndroidStudio旧版本BUG问题】完美解决运行报错问题Invalid keystore format

由于之前安装的版本导致AndroidStudio 运行报错:Invalid keystore format 在如下截图的路径中删了debug.keystore重新打开Android Studio运行一下就好了!!! 下面介绍各个模块功能: adbkey 是 Android Debug Bridge (AD…

【数据库】SQL--DQL(初阶)

文章目录 DCL1. 基本介绍2. 语法2.1 基础查询2.2 条件查询2.3 聚合函数2.4 聚合查询2.5 分组查询2.6 排序查询2.7 分页查询2.8 综合案例练习2.9 执行顺序 3. DQL总结 DCL 更多数据库MySQL系统内容就在以下专栏: 专栏链接:数据库MySQL 1. 基本介绍 DQL英…

Linux下SpringBoot项目部署(centos系统)

一、首先找到自己的sql文件,没有就从数据库挪进来 二、在Maven下打包一下(点击package),看到BUILD SUCCESS就是打包好了 三、将上面两个文件分别挪到 linux 中对应的文件,没有就创建一个(我的是spring_blog…

【数据库初阶】SQL--DCL

文章目录 DCL1. 基本介绍2. 用户管理2.1 查询用户2.2 创建用户2.3 修改用户密码2.4 删除用户 3. 权限控制3.1 查询权限3.2 授予权限3.3 撤销权限 4. DCL总结 DCL 更多数据库MySQL系统内容就在以下专栏: 专栏链接:数据库MySQL 1. 基本介绍 DCL英文全称是…