Ios AVAudioPlayer';忘记';由MPRemoteCommand触发时播放
我正在尝试播放音频文件,并通过锁屏上的远程命令中心控制其播放 如果我这样做:Ios AVAudioPlayer';忘记';由MPRemoteCommand触发时播放,ios,swift,avaudioplayer,mpremotecommandcenter,Ios,Swift,Avaudioplayer,Mpremotecommandcenter,我正在尝试播放音频文件,并通过锁屏上的远程命令中心控制其播放 如果我这样做: 开始播放 暂停播放 锁定装置 从锁屏开始播放(MPRemoteCommandCenter) 这样就不可能从锁屏暂停播放。按钮闪烁,什么也没发生 我怎样才能解决这个问题 详情如下: 似乎在尝试暂停音频时,AVAudioPlayer会为audioPlayer.isplay返回“false” 这发生在我的iPhoneXR、iPhoneSE和iPhone8的iOS13.1上。我没有其他设备可以测试 日志表明AVAudio
- 开始播放
- 暂停播放
- 锁定装置
- 从锁屏开始播放(MPRemoteCommandCenter)
- 似乎在尝试暂停音频时,AVAudioPlayer会为audioPlayer.isplay返回“false”
- 这发生在我的iPhoneXR、iPhoneSE和iPhone8的iOS13.1上。我没有其他设备可以测试
- 日志表明AVAudioPlayer.isplay在开始播放时最初返回true,但随后返回false。播放机的当前时间也在播放开始时左右出现停滞李>
- 我的整个视图控制器低于(~100行)。这是重现问题所需的最低限度
- Github上也提供了演示错误的示例项目
class ViewController: UIViewController {
@IBOutlet weak var playPauseButton: UIButton!
@IBAction func playPauseButtonTap(_ sender: Any) {
if self.audioPlayer.isPlaying {
pause()
} else {
play()
}
}
private var audioPlayer: AVAudioPlayer!
private var hasPlayed = false
override func viewDidLoad() {
super.viewDidLoad()
let fileUrl = Bundle.main.url(forResource: "temp/intro", withExtension: ".mp3")
try! self.audioPlayer = AVAudioPlayer(contentsOf: fileUrl!)
let audioSession = AVAudioSession.sharedInstance()
do { // play on speakers if headphones not plugged in
try audioSession.overrideOutputAudioPort(AVAudioSession.PortOverride.speaker)
} catch let error as NSError {
print("Override headphones failed, probably because none are available: \(error.localizedDescription)")
}
do {
try audioSession.setCategory(.playback, mode: .spokenAudio)
try audioSession.setActive(true)
} catch let error as NSError {
print("Warning: Setting audio category to .playback|.spokenAudio failed: \(error.localizedDescription)")
}
playPauseButton.setTitle("Play", for: .normal)
}
func play() {
playPauseButton.setTitle("Pause", for: .normal)
self.audioPlayer.play()
if(!hasPlayed){
self.setupRemoteTransportControls()
self.hasPlayed = true
}
}
func pause() {
playPauseButton.setTitle("Play", for: .normal)
self.audioPlayer.pause()
}
// MARK: Remote Transport Protocol
@objc private func handlePlay(event: MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus {
print(".......................")
print(self.audioPlayer.currentTime)
let address = Unmanaged.passUnretained(self.audioPlayer).toOpaque()
print("\(address) not playing: \(!self.audioPlayer.isPlaying)")
guard !self.audioPlayer.isPlaying else { return .commandFailed }
print("attempting to play")
let success = self.audioPlayer.play()
print("play() invoked with success \(success)")
print("now playing \(self.audioPlayer.isPlaying)")
return success ? .success : .commandFailed
}
@objc private func handlePause(event: MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus {
print(".......................")
print(self.audioPlayer.currentTime)
let address = Unmanaged.passUnretained(self.audioPlayer).toOpaque()
print("\(address) playing: \(self.audioPlayer.isPlaying)")
guard self.audioPlayer.isPlaying else { return .commandFailed }
print("attempting to pause")
self.pause()
print("pause() invoked")
return .success
}
private func setupRemoteTransportControls() {
let commandCenter = MPRemoteCommandCenter.shared()
commandCenter.playCommand.addTarget(self, action: #selector(self.handlePlay))
commandCenter.pauseCommand.addTarget(self, action: #selector(self.handlePause))
var nowPlayingInfo = [String : Any]()
nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = "Major title"
nowPlayingInfo[MPMediaItemPropertyTitle] = "Minor Title"
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = self.audioPlayer.currentTime
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = self.audioPlayer.duration
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = self.audioPlayer.rate
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
}
}
此日志记录了以下内容(添加了我的//注释):
我束手无策。帮帮我,你是我唯一的希望
编辑:我也试过
永远回来,成功
忽略audioPlayer状态,按照远程指挥中心的指示执行
这两种情况都会导致第一次在锁屏上点击pause
时错误持续存在。随后的轻触将音频重置为原始暂停位置,然后正常工作
更新
- 用AVPlayer替换AVAudioPlayer似乎可以彻底解决这个问题!我相当肯定这是AVAudioPlayer中的一个bug
- 切换到AVPlayer的必要步骤如下
- 我使用了我的一个开发者问题单,并将这个问题提交给了苹果公司。当我收到他们的回复时,我会发布一个答案
- 苹果开发支持部门确认,截至2019年12月5日,该问题尚无已知的解决办法。我已经向feedbackassistant.apple.com提交了一个问题,当问题发生变化时,我会更新这个答案李>
- 这确实是AVAudioPlayer中的一个bug
如果您不想切换到AVPlayer,另一个解决方法是在暂停前检查是否播放,如果没有,请在暂停前调用play。虽然不漂亮,但效果很好:
if (!self.player.isPlaying) [self.player play]; [self.player pause];
@马特,我只是根据你的建议尝试了一下,但没用。我正在用我试过的代码对问题进行编辑。@matt我也试过你想让我做的事。编辑附在我的问题后面。现在,第一次点击锁屏暂停按钮时忽略了第一次点击。很抱歉我误解了你,谢谢你的帮助。@objc private func handlePlay(event: MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus { guard !self.audioPlayer.isPlaying else { return .success } self.audioPlayer.play() return .success } @objc private func handlePause(event: MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus { print(self.audioPlayer.isPlaying) guard self.audioPlayer.isPlaying else { return .success } self.pause() return .success }
@objc private func handlePlay(event: MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus { self.audioPlayer.play() MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyElapsedPlaybackTime] = self.audioPlayer.currentTime MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] = self.audioPlayer.rate return .success } @objc private func handlePause(event: MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus { self.audioPlayer.pause() MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyElapsedPlaybackTime] = self.audioPlayer.currentTime MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] = self.audioPlayer.rate return .success }
if (!self.player.isPlaying) [self.player play]; [self.player pause];