如何用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
相关产品推荐
相关产品推荐

