HarmonyOS 鸿蒙Next中自动和手动切换音频设备问题
HarmonyOS 鸿蒙Next中自动和手动切换音频设备问题 【问题描述】:自动和手动切换音频设备问题
【问题现象】:
1、无法获取到所有可切换输出音频设备列表信息;
2、使用setDefaultOutputDevice可切换设备类型有限(外接有线耳机和蓝牙耳机等),且使用AVCastPicker切换后,再次调用本接口不生效;
3、使用AVCastPicker无法自动切换扬声器,无法通过设置属性改变其状态;
4、使用C底层代码切换成扬声器后,无法改变AVCastPicker状态,AVCastPicker状态还是听筒,此时需要点击AVCastPicker两次才能切换成听筒;
【版本信息】:DevEco Studio 5.0.2 Release、HarmonyOS 5.1.0、 sdk5.0.1(13)
【复现代码】:
AVCastPicker() //进入会议自动切换api未知
【尝试解决方案】:使用audioRoutingManager?.setCommunicationDevice单独修改扬声器的状态(但官网显示后续setCommunicationDevice接口会废弃)
【问题场景】:
我想自动切换音频设备,主要是不用AVCastPicker的话,我拿不到所有可输出设备信息,我想切换也不知道切换成啥。现在用AVCastPicker和setDefaultOutputDevice都实现不了,视频会议有需要设置进会是否开启扬声器需求
更多关于HarmonyOS 鸿蒙Next中自动和手动切换音频设备问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

大佬,我的编辑器咋提示没有selectOutputDevice这个方法呀
系统接口仅供系统应用使用,
找HarmonyOS工作还需要会Flutter的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17
- 无法获取所有可切换输出音频设备列表信息
依据:
getAvailableDevices(deviceUsage: DeviceUsage): AudioDeviceDescriptors方法可以获取音频可选设备列表(同步返回结果)。getDevicesSync(deviceFlag: DeviceFlag): AudioDeviceDescriptors也可获取设备列表,但注意其返回可能包含听筒(EARPIECE)设备。
建议方案:
使用 getAvailableDevices 并指定设备用途(如 MEDIA_OUTPUT_DEVICES)来获取当前可用的输出设备列表。示例:
import { audio } from '@kit.AudioKit';
import { BusinessError } from '@kit.BasicServicesKit';
try {
let devices = audioRoutingManager.getAvailableDevices(audio.DeviceUsage.MEDIA_OUTPUT_DEVICES);
console.info("可用设备列表: " + JSON.stringify(devices));
} catch (err) {
console.error("获取设备列表失败: " + err);
}
注意:设备列表可能包括扬声器(SPEAKER)、有线耳机(WIRED_HEADSET)、蓝牙设备(BLUETOOTH_A2DP)等,但具体设备依赖实际连接状态。
2. setDefaultOutputDevice 的限制和 AVCastPicker 的优先级问题
依据:
setDefaultOutputDevice仅适用于 语音消息、VoIP语音通话或VoIP视频通话 场景,且仅支持听筒(EARPIECE)、扬声器(SPEAKER)和系统默认设备(DEFAULT)。外接设备(如蓝牙耳机)不支持通过此接口设置。- 如果使用 AVCastPicker 切换过设备,再次调用
setDefaultOutputDevice将不生效(AVCastPicker 优先级更高)。
建议方案:
- 若需切换外接设备(如蓝牙耳机),必须使用 AVCastPicker 组件(推荐)或系统级路由 API(如
selectOutputDevice)。 - 自动切换需求应通过编程方式调用
selectOutputDevice或selectOutputDeviceByFilter(见下文)。
3. AVCastPicker 无法自动切换扬声器及状态同步问题
依据:
- AVCastPicker 是 UI 组件,用于用户手动切换设备。它本身不提供直接编程控制接口(如设置属性自动切换)。
- 应用可通过监听设备变化事件(如
preferOutputDeviceChangeForRendererInfo)更新 UI 状态,实现自定义样式。
自动切换的替代方案:
使用 AudioRoutingManager 的 selectOutputDevice 或 selectOutputDeviceByFilter 接口直接切换设备:
// 示例:切换到扬声器
let deviceDesc: audio.AudioDeviceDescriptors = [{
deviceRole: audio.DeviceRole.OUTPUT_DEVICE,
deviceType: audio.DeviceType.SPEAKER, // 设备类型:扬声器
id: 1, // 需从设备列表中获取实际ID
// ... 其他参数(如name、address等需匹配实际设备)
}];
audioRoutingManager.selectOutputDevice(deviceDesc).then(() => {
console.info("切换到扬声器成功");
}).catch((err: BusinessError) => {
console.error("切换失败: " + err);
});
注意事项:
selectOutputDevice是系统接口,可能需要系统权限(如ohos.permission.MANAGE_AUDIO_CONFIG)。- 设备描述符(如
id)必须与当前可用设备匹配(可通过getAvailableDevices获取)。
4. C底层代码切换后 AVCastPicker 状态不同步的问题
依据:
- AVCastPicker 的状态与 AVSession 绑定。若通过底层C代码直接切换设备,可能绕过 AVSession 框架,导致状态不同步。
- 设备切换应统一通过 AVSession 管理(如使用
castAudio系统接口),以确保 AVCastPicker 状态同步。
解决方案:
- 避免直接使用底层C接口切换设备。应通过 ArkTS 层的
AVSession或AudioRoutingManager接口操作。 - 若必须用C代码,需确保调用后主动通知 AVSession 更新状态。
针对视频会议场景的自动切换方案
核心需求:进入会议时自动开启扬声器。
推荐方案:
- 获取设备列表:使用
getAvailableDevices确认扬声器可用。 - 自动切换设备:通过
selectOutputDevice直接切换到扬声器(而非依赖 AVCastPicker)。 - 监听切换结果:注册
outputDeviceChange事件确认切换成功。
示例代码:
import { audio } from '@kit.AudioKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 1. 创建AudioRenderer(通话场景需使用VOICE_COMMUNICATION类型)
let rendererInfo: audio.AudioRendererInfo = {
usage: audio.StreamUsage.STREAM_USAGE_VOICE_COMMUNICATION, // 语音通话场景
rendererFlags: 0
};
let audioRenderer = await audio.createAudioRenderer({ rendererInfo });
// 2. 自动切换到扬声器
let speakerDevice = audioRoutingManager.getAvailableDevices(audio.DeviceUsage.MEDIA_OUTPUT_DEVICES)
.find(device => device.deviceType === audio.DeviceType.SPEAKER);
if (speakerDevice) {
audioRoutingManager.selectOutputDevice([speakerDevice]).then(() => {
console.info("扬声器切换成功");
}).catch((err: BusinessError) => {
console.error("切换失败: " + err);
});
}
// 3. 监听设备变化(可选)
audioRenderer.on('outputDeviceChange', (devices: audio.AudioDeviceDescriptors) => {
console.info("当前输出设备: " + devices[0].deviceType);
});
大佬,我的编辑器咋提示没有selectOutputDevice这个方法呀,
找HarmonyOS工作还需要会Flutter的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17
系统权限仅开放给系统应用,普通应用无法申请。不开放自动强制选择音频输出设备的接口。
在HarmonyOS鸿蒙Next中,音频设备切换支持自动和手动两种模式。自动模式下,系统根据连接状态和设备优先级自动选择音频输出设备,例如插入有线耳机时自动切换到耳机输出。手动切换需在控制中心或设置中指定音频路由,用户可主动选择扬声器、蓝牙设备等。切换逻辑基于设备连接事件和用户操作,系统API如AudioRoutingManager管理相关行为。音频策略确保切换过程无中断,维持播放连贯性。
在HarmonyOS Next中,音频设备切换涉及AVCastPicker和AudioRoutingManager的配合使用。针对您的问题:
-
获取音频设备列表:通过
AudioRoutingManager.getDevices()获取所有可用音频设备,使用AudioDeviceDescriptor筛选输出设备(如扬声器、耳机)。 -
自动切换扬声器:
- 进入会议时,调用
AudioRoutingManager.setCommunicationDevice(AudioDeviceDescriptor),传入扬声器设备描述符,实现自动切换。 - 尽管
setCommunicationDevice可能废弃,但目前是推荐方案,后续可关注API更新。
- 进入会议时,调用
-
状态同步问题:
- 使用
AVCastPicker时,通过监听onAudioDeviceSelected事件同步设备状态。 - 若底层切换导致状态不一致,需在代码中手动调用
AVCastPicker.updateDevice()刷新界面。
- 使用
-
代码示例:
// 获取设备列表 let devices = audioRoutingManager.getDevices(AudioDeviceFlag.OUTPUT_DEVICES_FLAG); // 自动切换至扬声器 audioRoutingManager.setCommunicationDevice(speakerDescriptor); // 监听AVCastPicker选择 AVCastPicker({ onAudioDeviceSelected: (device) => { /* 处理逻辑 */ } });
建议结合事件监听与状态管理,确保UI与底层状态一致。当前可继续使用setCommunicationDevice,同时关注HarmonyOS SDK更新。


