AVPlayer无法通过蓝牙耳机输出音频,播放录音均走iOS设备自带端口求解
问题根因
你当前的代码存在两个核心问题导致蓝牙耳机无法正常识别:
- 频繁切换
AVAudioSession类别:播放前切换为.playback类别,该类别默认仅支持音频输出,不会主动触发蓝牙输入设备识别;播放结束后又切换为.recording类别,频繁的类别切换会导致音频路由逻辑混乱,无法正常关联蓝牙设备。 - 配置项不全:仅添加
.allowBluetooth选项无法覆盖所有蓝牙设备的适配场景,且反复调用setActive(true)会干扰系统的音频路由分配。
修正方案
- 统一使用
.playbackAndRecording类别,无需在播放和录音场景来回切换,避免路由混乱 - 配置类别时补充完整选项,适配不同蓝牙协议的设备
- 仅在App启动/音频模块初始化时配置一次音频会话,不要每次播放、停止都重复配置
- 监听音频路由变化通知,适配蓝牙设备的热插拔场景
修正后的代码示例
// 仅在音频模块初始化时执行一次即可 let audioSession = AVAudioSession.sharedInstance() do { // 统一使用playAndRecord类别,配置全蓝牙相关选项 try audioSession.setCategory(.playbackAndRecording, options: [ .allowBluetooth, // 支持HFP协议蓝牙设备的双向传输(录音+播放) .allowBluetoothA2DP, // 支持A2DP协议的高质量蓝牙立体声播放 .defaultToSpeaker // 按需添加,无蓝牙设备时默认使用扬声器输出 ]) try audioSession.setActive(true) } catch { print("音频会话配置失败: \(error.localizedDescription)") // 不要直接使用fatalError,避免非核心异常导致App闪退 } // 监听音频路由变化,处理蓝牙设备连接/断开场景 NotificationCenter.default.addObserver(forName: AVAudioSession.routeChangeNotification, object: nil, queue: .main) { notification in guard let userInfo = notification.userInfo, let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt, let reason = AVAudioSession.RouteChangeReason(rawValue: reasonValue) else { return } switch reason { case .newDeviceAvailable, .oldDeviceUnavailable: // 蓝牙设备连接/断开时,可在此处根据当前路由调整播放/录音逻辑 let currentRoute = audioSession.currentRoute let hasBluetoothDevice = currentRoute.inputs.contains { port in port.portType == .bluetoothHFP || port.portType == .bluetoothA2DP } print("当前是否连接蓝牙音频设备: \(hasBluetoothDevice)") default: break } }
注意事项
- 如果确实需要在特定场景下切换为纯播放模式,切换时也要给
.playback类别添加.allowBluetoothA2DP选项,否则蓝牙播放也会默认走设备扬声器 - 不要用
fatalError处理音频会话异常,部分系统级的音频抢占(比如来电、其他App占用音频通道)会导致配置失败,这类异常捕获后重试即可
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

