You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 07:15:45