HarmonyOS 鸿蒙Next媒体输出设备管理
HarmonyOS 鸿蒙Next媒体输出设备管理
1、音频输出设备管理
有时设备同时连接多个音频输出设备,需要指定音频输出设备进行音频播放,此时需要使用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.');
});
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、具体步骤
- 创建AudioStreamManager实例。
在使用AudioStreamManager的API前,需要使用getStreamManager()创建一个AudioStreamManager实例。
import audio from '@ohos.multimedia.audio';
let audioManager = audio.getAudioManager();
let audioStreamManager = audioManager.getStreamManager();
- 使用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}`);
}
}
});
- (可选)使用off(‘audioRendererChange’)取消监听音频播放流变化。
audioStreamManager.off('audioRendererChange');
console.info('RendererChange Off is called ');
- (可选)使用getCurrentAudioRendererInfoArray()获取所有音频播放流的信息。
该接口可获取音频播放流唯一ID,音频播放客户端的UID,音频状态以及音频播放器的其他信息。
async function getCurrentAudioRendererInfoArray(){
await audioStreamManager.getCurrentAudioRendererInfoArray().then(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,否则无法获得实际的设备名称和设备地址信息,查询到的设备名称和设备地址(蓝牙设备的相关属性)将为空字符串。
更多关于HarmonyOS 鸿蒙Next媒体输出设备管理的实战教程也可以访问 https://www.itying.com/category-93-b0.html
鸿蒙Next的媒体输出设备管理基于分布式能力实现,支持跨设备音频流转和控制。系统通过AudioManager服务提供设备发现、连接状态监听和输出切换功能。关键API包括:getDevices()获取可用设备列表、on(‘deviceChange’)监听设备状态变化、setDevice()指定输出目标。设备类型通过AudioDeviceDescriptor标识,包含蓝牙耳机、智能音箱等。流转时采用低延迟编码保障音画同步,支持HWA、LDAC等高清音频协议。安全方面采用设备认证和通道加密机制。
更多关于HarmonyOS 鸿蒙Next媒体输出设备管理的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
关于HarmonyOS Next的媒体输出设备管理,您提供的代码示例已经非常全面。这里补充几点关键说明:
-
设备优先级:当多个音频输出设备同时连接时,系统会按照内置优先级自动切换。通过AudioRoutingManager可以覆盖默认行为,强制指定输出设备。
-
蓝牙设备特殊处理:对于BLUETOOTH_SCO和BLUETOOTH_A2DP,需要注意蓝牙协议差异。SCO主要用于语音通话(带宽窄),A2DP用于音乐播放(带宽高)。
-
状态同步问题:设备切换操作是异步的,建议在回调确认成功后再更新UI。监听deviceChange事件能确保获取到最新状态。
-
流管理性能:AudioStreamManager获取所有音频流信息时,大数据量可能影响性能,建议按需使用。
-
权限控制:除了USE_BLUETOOTH权限,部分设备管理接口还需要MICROPHONE权限,具体参考API文档。
这些代码示例已经涵盖了音频设备管理的核心场景,包括设备枚举、状态监听和主动切换。实际开发时可根据业务需求选择合适的API组合。