Android开发控制USB DAC侧音时如何不影响其他应用播放音频
问题描述
我有一款通过Type-C接口连接手机的耳机,其内置USB DAC,通过USB协议与Type-C接口通信。
为控制该耳机的侧音音量,我编写了如下实现代码:
UsbInterface usbInterface = theDevice.getInterface(0); UsbDeviceConnection connection = usbManager.openDevice(theDevice); connection.claimInterface(usbInterface, true); byte[] buffer = intTo2Bytes(volume); connection.controlTransfer(0x21,0x01,0x0100,0x0200,new byte[]{0x00},1,100); connection.controlTransfer(0x21,0x01,0x0200,0x0200,buffer,2,100); connection.controlTransfer(0x21,0x01,0x0100,0x0500,new byte[]{0x00},1,100); connection.controlTransfer(0x21,0x01,0x0201,0x0500,new byte[]{0x00,0x00},2,100); connection.controlTransfer(0x21,0x01,0x0202,0x0500,new byte[]{0x00,0x00},2,100); connection.releaseInterface(usbInterface); connection.close();
上述指令地址与控制命令,是我将耳机连接至Windows笔记本、通过系统设置调整侧音音量时,使用Wireshark对USB端口抓包得到的。指令实际运行生效,执行后可在耳机中听到自身侧音。
但执行完上述操作后,其他应用无法在该USB设备上正常播放音频。
核心诉求:如何通过上述方式(或其他可用API)实现侧音音量调整,同时保证设备音频播放功能正常运行?
解决方案
- 问题根源出在
connection.claimInterface(usbInterface, true)这行:第二个参数传true代表强制抢占接口所有权,会直接断开系统音频服务(Android端为AudioFlinger、USB audio HAL层)已经持有的USB音频连接。后续即使调用releaseInterface和close释放连接,系统音频服务也不会自动重新绑定该USB设备,直接导致其他应用无法通过设备播放音频。 - 优先使用系统标准API调整,不要直接抢占USB接口:Android 12及以上版本的
AudioManager原生支持USB音频设备侧音控制,先通过getDevices(AudioManager.GET_DEVICES_OUTPUTS)拿到对应耳机的AudioDeviceInfo实例,直接调用系统侧音调节接口设置参数即可,走系统原生音频通路完全不会打断现有音频播放。 - 如果必须走自定义USB控制传输:
- 调用
claimInterface时第二个参数传false,用非强制模式申请接口权限,不要硬抢系统已经占用的接口 - 不要直接默认拿0号接口操作,先遍历设备下所有
UsbInterface,区分开音频流接口(USB Audio Class标准中音频流接口类代码为0x01、子类为0x02)和厂商自定义控制接口,只申请控制命令对应的目标接口权限,不要触碰音频流传输接口 - 不要照搬Windows抓包拿到的全量指令序列:Windows USB音频栈在发控制指令前后会附带大量自身状态维护相关的指令,抓包时会一并抓到,这类指令不需要发送,发多了反而会打乱设备的音频接口状态,导致系统无法识别为标准音频输出设备。可以逐个删减非必要指令,找到仅修改侧音音量的最小生效指令集,减少对设备状态的改动
- 发完控制指令立刻释放接口、关闭连接,不要长时间持有USB设备连接
- 调用
- 如果以上方案执行后仍出现音频播放异常,可以在控制指令执行完成后,主动触发系统USB音频重枚举:临时关闭再开启USB音频功能,或通过系统权限发送USB设备插拔广播,让系统音频服务重新绑定设备音频接口,恢复正常播放能力。
内容的提问来源于stack exchange,提问作者Developer_ken
相关产品推荐
相关产品推荐

