iOS:playAndRecord类别下蓝牙耳机pauseCommand按键未被检测问题咨询
iOS蓝牙耳机按键无法触发MPRemoteCommandCenter的pauseCommand问题
我开发了一款iOS应用,使用AVAudioSession的playAndRecord类别与default模式实现蓝牙耳机的音频录制与播放,计划通过MPRemoteCommandCenter利用耳机按键启停录制,但耳机按键操作(尤其是pauseCommand)无法被检测到。
问题代码
UIApplication.shared().beginReceivingRemoteControlEvents() let audioSession = AVAudioSession.sharedInstance() audioSession.setCategory(.playAndRecord, mode: .default, options: [.allowBluetooth]) audioSession.setActive(true) let audioEngine = AVAudioEngine() let audioPlayerNode = AVAudioPlayerNode() audioEngine.attach(audioPlayerNode) audioEngine.connect(audioPlayerNode, to: audioEngine.outputNode, format: nil) audioEngine.inputNode.installTap(onBus: 0, bufferSize: 8000, format: nil) { buffer, time in // 处理音频数据 } let cmdCenter = MPRemoteCommandCenter.shared() cmdCenter.playCommand.addTarget { event in print("registered play") try! audioEngine.start() return .success } cmdCenter.playCommand.isEnabled = true cmdCenter.pauseCommand.addTarget { event in // ---- 此代码从未被执行 ---- print("registered pause") audioEngine.pause() return .success } cmdCenter.pauseCommand.isEnabled = true
解决方案
问题核心在于playAndRecord类别下系统对耳机按键的默认优先级,以及应用未正确告知系统自身的音频活跃状态,需从以下几点调整:
1. 替换废弃的远程控制API
iOS 13及以上版本中,beginReceivingRemoteControlEvents()已被废弃,改用以下方式启用远程控制:
UIApplication.shared.isRemoteControlEnabled = true
2. 配置MPNowPlayingInfoCenter
必须设置Now Playing信息,让系统识别应用处于音频活跃状态,否则pauseCommand不会被触发:
let nowPlayingInfo = [ MPMediaItemPropertyTitle: "音频录制", MPMediaItemPropertyArtist: "你的应用名称" ] MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
3. 完善音频会话配置与错误处理
避免使用try!强制解包,添加必要的音频会话选项,并确保激活成功后再配置远程命令。
4. 同步更新播放状态
触发play/pause命令时,更新Now Playing的播放速率,让系统同步应用的音频状态:
// 启动录制时设置播放速率为1 MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] = 1.0 // 暂停录制时设置播放速率为0 MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] = 0.0
修正后的完整代码
import AVFoundation import MediaPlayer // 启用远程控制 UIApplication.shared.isRemoteControlEnabled = true let audioSession = AVAudioSession.sharedInstance() do { // 配置音频会话,支持蓝牙耳机并允许混音 try audioSession.setCategory(.playAndRecord, mode: .default, options: [.allowBluetooth, .mixWithOthers]) try audioSession.setActive(true) // 设置Now Playing信息,告知系统应用的音频状态 let nowPlayingInfo = [ MPMediaItemPropertyTitle: "蓝牙耳机录制", MPMediaItemPropertyArtist: "测试应用" ] MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo let audioEngine = AVAudioEngine() let audioPlayerNode = AVAudioPlayerNode() audioEngine.attach(audioPlayerNode) audioEngine.connect(audioPlayerNode, to: audioEngine.outputNode, format: nil) audioEngine.inputNode.installTap(onBus: 0, bufferSize: 8000, format: nil) { buffer, time in // 处理音频数据 } let cmdCenter = MPRemoteCommandCenter.shared() // 处理play命令 cmdCenter.playCommand.addTarget { [weak audioEngine] event in guard let engine = audioEngine else { return .commandFailed } do { try engine.start() // 更新播放状态为活跃 MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] = 1.0 print("录制已启动") return .success } catch { print("启动音频引擎失败: \(error.localizedDescription)") return .commandFailed } } cmdCenter.playCommand.isEnabled = true // 处理pause命令 cmdCenter.pauseCommand.addTarget { [weak audioEngine] event in guard let engine = audioEngine else { return .commandFailed } engine.pause() // 更新播放状态为暂停 MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] = 0.0 print("录制已暂停") return .success } cmdCenter.pauseCommand.isEnabled = true } catch { print("音频会话配置失败: \(error.localizedDescription)") }
关键说明
- 未设置
MPNowPlayingInfoCenter时,系统无法识别应用的音频活跃状态,会拦截耳机pause按键事件; - iOS 13+需使用
isRemoteControlEnabled替代旧版API,确保远程命令能被接收; playAndRecord类别下添加.mixWithOthers选项,避免与系统音频抢占资源,提高按键事件传递的优先级。
内容的提问来源于stack exchange,提问作者erksch
相关产品推荐
相关产品推荐

