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

如何用AVAudioPlayerNode更新MPNowPlayingInfoCenter/MPRemoteCommandCenter播放暂停控件?

解决方案:同步MPNowPlayingInfoCenter/MPRemoteCommandCenter与AVAudioPlayerNode状态

核心思路

直接手动更新MPNowPlayingInfoCenter的播放状态参数,同时确保MPRemoteCommandCenter的命令回调与播放器内部逻辑绑定,无需暂停整个AVAudioEngine即可实现控件同步。

具体实现步骤

1. 初始化远程命令中心

在播放器初始化阶段,注册播放/暂停命令的回调,确保锁屏、控制中心等外部控件触发时,能正确调用你的播放/暂停方法:

func setupRemoteCommands() {
    let commandCenter = MPRemoteCommandCenter.shared()
    
    // 绑定播放命令
    commandCenter.playCommand.addTarget { [weak self] _ in
        guard let self = self else { return .commandFailed }
        self.playPlayerNode()
        return .success
    }
    
    // 绑定暂停命令
    commandCenter.pauseCommand.addTarget { [weak self] _ in
        guard let self = self else { return .commandFailed }
        self.pausePlayerNode()
        return .success
    }
}

2. 修改暂停方法(移除audioEngine暂停操作)

只暂停playerNode,同时手动更新MPNowPlayingInfoCenter的状态参数:

func pausePlayerNode() {
    playerNode.pause()
    displayLink?.isPaused = true
    
    DispatchQueue.main.async {
        self.musicPlayerControlsManager.isPlaying = false
        // 更新播放状态到控制中心
        var nowPlayingInfo = MPNowPlayingInfoCenter.default().nowPlayingInfo ?? [:]
        nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = 0.0 // 0代表暂停
        nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = self.playerNode.currentTime
        MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
    }
}

3. 修改播放方法(同步更新控制中心状态)

播放时同样更新MPNowPlayingInfoCenter,仅在audioEngine未运行时启动它:

func playPlayerNode() {
    if !audioEngine.attachedNodes.isEmpty && audioFile != nil {
        DispatchQueue.main.async {
            self.musicPlayerControlsManager.isPlaying = true
            self.displayLink?.isPaused = false
            // 更新播放状态到控制中心
            var nowPlayingInfo = MPNowPlayingInfoCenter.default().nowPlayingInfo ?? [:]
            nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = 1.0 // 1代表播放
            MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
        }
        
        // 仅在引擎未运行时启动,避免重复启动导致的延迟
        if !audioEngine.isRunning {
            do {
                try audioEngine.start()
            } catch {
                print(error.localizedDescription)
            }
        }
        playerNode.play()
    }
}

4. 配置后台播放权限

在Info.plist中添加后台音频模式,确保锁屏后控制中心仍能正常工作:

  • 添加Required background modes数组,包含App plays audio or streams audio/video using AirPlay选项

关键说明

  • 移除audioEngine.pause()操作,仅控制playerNode的播放/暂停,可彻底避免引擎启停带来的卡顿和延迟
  • MPNowPlayingInfoPropertyPlaybackRate是同步控件状态的核心参数,0对应暂停状态,1对应播放状态
  • 注册MPRemoteCommandCenter回调,可确保外部控件触发操作时,播放器内部状态与控件保持一致

内容的提问来源于stack exchange,提问作者User95797654974

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 04:15:27