当前位置: 首页 > news >正文

鸿蒙媒体开发系列06——输出设备与音频流管理

如果你也对鸿蒙开发感兴趣,加入“Harmony自习室”吧!扫描下方名片,关注公众号,公众号更新更快,同时也有更多学习资料和技术讨论群。

1、音频输出设备管理

有时设备同时连接多个音频输出设备,需要指定音频输出设备进行音频播放,此时需要使用AudioRoutingManager接口进行输出设备的管理。

👉🏻 创建一个AudioRoutingManager

在使用AudioRoutingManager管理音频设备前,需要先导入模块并创建实例。代码如下:

import audio from '@ohos.multimedia.audio';  // 导入audio模块let audioManager = audio.getAudioManager();  // 需要先创建AudioManager实例let audioRoutingManager = audioManager.getRoutingManager();  // 再调用AudioManager的方法创建AudioRoutingManager实例

目前支持的音频输出设备分别有:

    • EARPIECE:听筒,枚举值为1

    • SPEAKER:扬声器,枚举值为2

    • WIRED_HEADSET:有线耳机(有麦克风),枚举值为3

    • WIRED_HEADPHONES:有线耳机(无麦克风),枚举值为4

    • BLUETOOTH_SCO:蓝牙设备SCO连接,值为7

    • BLUETOOTH_A2DP:蓝牙设备A2DP连接,值为8

    • USB_HEADSET:USB耳机,带麦克风,值为22

👉🏻 获取输出设备信息

使用getDevices()方法可以获取当前所有输出设备的信息。​​​​​​​

audioRoutingManager.getDevices(audio.DeviceFlag.OUTPUT_DEVICES_FLAG).then((data) => {  console.info('Promise returned to indicate that the device list is obtained.');});

👉🏻 监听设备连接状态变化

可以设置监听事件来监听设备连接状态的变化,当有设备连接或断开时触发回调:​​​​​​​

// 监听音频设备状态变化audioRoutingManager.on('deviceChange', audio.DeviceFlag.OUTPUT_DEVICES_FLAG, (deviceChanged) => {  console.info('device change type : ' + deviceChanged.type);  // 设备连接状态变化,0为连接,1为断开连接  console.info('device descriptor size : ' + deviceChanged.deviceDescriptors.length);  console.info('device change descriptor : ' + deviceChanged.deviceDescriptors[0].deviceRole);  // 设备角色  console.info('device change descriptor : ' + deviceChanged.deviceDescriptors[0].deviceType);  // 设备类型});// 取消监听音频设备状态变化audioRoutingManager.off('deviceChange', (deviceChanged) => {  console.info('Should be no callback.');});

👉🏻 设置激活输出类型

可以通过setCommunicationDevice(deviceType: CommunicationDeviceType, active: boolean, callback: AsyncCallback<void>): void 方法设置通信设备激活状态,使用callback方式异步返回结果。代码如下:​​​​​​​

audioRoutingManager.setCommunicationDevice(audio.CommunicationDeviceType.SPEAKER, true, (err) => {  if (err) {    console.error(`Failed to set the active status of the device. ${err}`);    return;  }  console.info('Callback invoked to indicate that the device is set to the active status.');});

其中 deviceType 为输出设备类型,我们在前文中提到过,不再展开说明。

2、音频播放流管理

对于播放音频类的应用,开发者需要关注该应用的音频流的状态以做出相应的操作,比如监听到状态为播放中/暂停时,及时改变播放按钮的UI显示。

👉🏻 读取或监听应用内音频流状态变化

方法1:直接查看AudioRenderer的state:​​​​​​​

let audioRendererState = audioRenderer.state;console.info(`Current state is: ${audioRendererState }`)

方法2:注册stateChange监听AudioRenderer的状态变化:​​​​​​​

audioRenderer.on('stateChange', (rendererState) => {  console.info(`State change to: ${rendererState}`)});

获取state后可对照AudioState来进行相应的操作,比如更改暂停播放按钮的显示等。

👉🏻 读取或监听所有音频流变化

如果部分应用需要查询获取所有音频流的变化信息,可以通过AudioStreamManager读取或监听所有音频流的变化。

如下为音频流管理调用关系图:

图片

在进行应用开发的过程中,开发者需要使用getStreamManager()创建一个AudioStreamManager实例,进而通过该实例管理音频流。开发者可通过调用on('audioRendererChange')监听音频流的变化,在音频流状态变化、设备变化时获得通知。同时可通过off('audioRendererChange')取消相关事件的监听。另外,开发者可以主动调用getCurrentAudioRendererInfoArray()来查询播放流的唯一ID、播放流客户端的UID、音频流状态等信息。

2.1、具体步骤

1. 创建AudioStreamManager实例。

在使用AudioStreamManager的API前,需要使用getStreamManager()创建一个AudioStreamManager实例。​​​​​​​

import audio from '@ohos.multimedia.audio';let audioManager = audio.getAudioManager();let audioStreamManager = audioManager.getStreamManager();

2. 使用on('audioRendererChange')监听音频播放流的变化。如果音频流监听应用需要在音频播放流状态变化、设备变化时获取通知,可以订阅该事件。​​​​​​​

audioStreamManager.on('audioRendererChange',  (AudioRendererChangeInfoArray) => {  for (let i = 0; i < AudioRendererChangeInfoArray.length; i++) {    let AudioRendererChangeInfo = AudioRendererChangeInfoArray[i];    console.info(`## RendererChange on is called for ${i} ##`);    console.info(`StreamId for ${i} is: ${AudioRendererChangeInfo.streamId}`);    console.info(`Content ${i} is: ${AudioRendererChangeInfo.rendererInfo.content}`);    console.info(`Stream ${i} is: ${AudioRendererChangeInfo.rendererInfo.usage}`);    console.info(`Flag ${i} is: ${AudioRendererChangeInfo.rendererInfo.rendererFlags}`);     for (let j = 0;j < AudioRendererChangeInfo.deviceDescriptors.length; j++) {      console.info(`Id: ${i} : ${AudioRendererChangeInfo.deviceDescriptors[j].id}`);      console.info(`Type: ${i} : ${AudioRendererChangeInfo.deviceDescriptors[j].deviceType}`);      console.info(`Role: ${i} : ${AudioRendererChangeInfo.deviceDescriptors[j].deviceRole}`);      console.info(`Name: ${i} : ${AudioRendererChangeInfo.deviceDescriptors[j].name}`);      console.info(`Address: ${i} : ${AudioRendererChangeInfo.deviceDescriptors[j].address}`);      console.info(`SampleRates: ${i} : ${AudioRendererChangeInfo.deviceDescriptors[j].sampleRates[0]}`);      console.info(`ChannelCount ${i} : ${AudioRendererChangeInfo.deviceDescriptors[j].channelCounts[0]}`);      console.info(`ChannelMask: ${i} : ${AudioRendererChangeInfo.deviceDescriptors[j].channelMasks}`);    }  }});

3. (可选)使用off('audioRendererChange')取消监听音频播放流变化。​​​​​​​

audioStreamManager.off('audioRendererChange');console.info('RendererChange Off is called ');

4. (可选)使用getCurrentAudioRendererInfoArray()获取所有音频播放流的信息。

该接口可获取音频播放流唯一ID,音频播放客户端的UID,音频状态以及音频播放器的其他信息。​​​​​​​

async function getCurrentAudioRendererInfoArray(){  await audioStreamManager.getCurrentAudioRendererInfoArray().then( function (AudioRendererChangeInfoArray) {    console.info(`getCurrentAudioRendererInfoArray  Get Promise is called `);    if (AudioRendererChangeInfoArray != null) {      for (let i = 0; i < AudioRendererChangeInfoArray.length; i++) {        let AudioRendererChangeInfo = AudioRendererChangeInfoArray[i];        console.info(`StreamId for ${i} is: ${AudioRendererChangeInfo.streamId}`);        console.info(`Content ${i} is: ${AudioRendererChangeInfo.rendererInfo.content}`);        console.info(`Stream ${i} is: ${AudioRendererChangeInfo.rendererInfo.usage}`);        console.info(`Flag ${i} is: ${AudioRendererChangeInfo.rendererInfo.rendererFlags}`);          for (let j = 0;j < AudioRendererChangeInfo.deviceDescriptors.length; j++) {          console.info(`Id: ${i} : ${AudioRendererChangeInfo.deviceDescriptors[j].id}`);          console.info(`Type: ${i} : ${AudioRendererChangeInfo.deviceDescriptors[j].deviceType}`);          console.info(`Role: ${i} : ${AudioRendererChangeInfo.deviceDescriptors[j].deviceRole}`);          console.info(`Name: ${i} : ${AudioRendererChangeInfo.deviceDescriptors[j].name}`);          console.info(`Address: ${i} : ${AudioRendererChangeInfo.deviceDescriptors[j].address}`);          console.info(`SampleRates: ${i} : ${AudioRendererChangeInfo.deviceDescriptors[j].sampleRates[0]}`);          console.info(`ChannelCount ${i} : ${AudioRendererChangeInfo.deviceDescriptors[j].channelCounts[0]}`);          console.info(`ChannelMask: ${i} : ${AudioRendererChangeInfo.deviceDescriptors[j].channelMasks}`);        }      }    }  }).catch((err) => {    console.error(`Invoke getCurrentAudioRendererInfoArray failed, code is ${err.code}, message is ${err.message}`);  });}

【注意】

对所有音频流状态进行监听的应用需要申请权限ohos.permission.USE_BLUETOOTH,否则无法获得实际的设备名称和设备地址信息,查询到的设备名称和设备地址(蓝牙设备的相关属性)将为空字符串。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • RK3568平台(网络篇)MAC地址烧录
  • 【Vmware16安装教程】
  • C++——求3个数中最大的数(分别考虑整数、双精度数、长整数的情况),用函数模板来实现。
  • sqlgun新闻管理系统
  • microchip中使用printf给AVR单片机串口重定向
  • 轴承表面缺陷检测系统源码分享
  • 医院用餐人次查询表——智慧大屏幕————未来之窗行业应用跨平台架构
  • Ansible——Playbook基本功能???
  • Python编码系列—Python团队开发工作流:高效协作的艺术
  • (黑马点评)二、短信登录功能实现
  • 黑神话悟空mac可以玩吗
  • 人类行为识别系统源码分享
  • Python学习——【2.1】if语句相关语法
  • vue3 生命周期,代码说明
  • Git使用—把当前仓库的一个分支push到另一个仓库的指定分支、基于当前仓库创建另一个仓库的分支并推送到对应仓库(mit6828)
  • 【RocksDB】TransactionDB源码分析
  • chrome扩展demo1-小时钟
  • HTTP中的ETag在移动客户端的应用
  • Java精华积累:初学者都应该搞懂的问题
  • Sequelize 中文文档 v4 - Getting started - 入门
  • ucore操作系统实验笔记 - 重新理解中断
  • Vue 2.3、2.4 知识点小结
  • vue2.0项目引入element-ui
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 分布式熔断降级平台aegis
  • 用 Swift 编写面向协议的视图
  • python最赚钱的4个方向,你最心动的是哪个?
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • ​LeetCode解法汇总518. 零钱兑换 II
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • ## 基础知识
  • #window11设置系统变量#
  • #每天一道面试题# 什么是MySQL的回表查询
  • (2)从源码角度聊聊Jetpack Navigator的工作流程
  • (javascript)再说document.body.scrollTop的使用问题
  • (Java数据结构)ArrayList
  • (二)c52学习之旅-简单了解单片机
  • (转)利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载 【反射】...
  • .dat文件写入byte类型数组_用Python从Abaqus导出txt、dat数据
  • .JPG图片,各种压缩率下的文件尺寸
  • .NET 3.0 Framework已经被添加到WindowUpdate
  • .NET Compact Framework 多线程环境下的UI异步刷新
  • .NET Core WebAPI中封装Swagger配置
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .NET Remoting学习笔记(三)信道
  • [ vulhub漏洞复现篇 ] JBOSS AS 4.x以下反序列化远程代码执行漏洞CVE-2017-7504
  • []新浪博客如何插入代码(其他博客应该也可以)
  • [20180312]进程管理其中的SQL Server进程占用内存远远大于SQL server内部统计出来的内存...
  • [android] 看博客学习hashCode()和equals()
  • [C++]STL之map
  • [caffe(二)]Python加载训练caffe模型并进行测试1
  • [CC-FNCS]Chef and Churu
  • [Flutter]打包IPA