无法使用 AVPlayer 将 AudioSession 设置为非活动状态
Unable to set AudioSession inactive with AVPlayer
我正在使用 AVPlayer
在我的 iOS 应用程序中播放音频(因为我正在播放的音频文件不是本地的),当我的曲目结束时,我想隐藏信息中心控件,但出现此错误:
AVAudioSession.mm:1079:-[AVAudioSession setActive:withOptions:error:]: Deactivating an audio session that has running I/O. All I/O should be stopped or paused prior to deactivating the audio session.
但是我之前暂停了我的AVPlayer
。
这是我的代码:
player.pause()
player.replaceCurrentItem(with: nil)
MPNowPlayingInfoCenter.default().nowPlayingInfo = nil
try? audioSession.setActive(false, options: .notifyOthersOnDeactivation)
由于这个错误,本机控件仍然可见,但不再工作。
您收到该错误是因为您在取消分配播放器之前停用了音频会话:
您可以通过以下方式解除分配:
play.pause()
player = nil
但您应该先声明您的播放器为可选播放器。
你的问题是关于:
您必须删除
player.replaceCurrentItem(with: nil)
MPNowPlayingInfoCenter.default().nowPlayingInfo = nil
一个只保留这个
player.pause()
try? audioSession.setActive(true, options: .notifyOthersOnDeactivation)
失去锁定屏幕控件的快速方法是使您的音频会话可混合(无需停用您的音频会话):
try! AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: .mixWithOthers)
当你想要它们时,删除 .mixWithOthers
。
另一种可能更可口的方法是在暂停播放后删除 MPRemoteCommandCenter
目标。例如如果你这样设置
var playTarget: Any? = nil
var pauseTarget: Any? = nil
func addRemoteTargets() {
let commandCenter = MPRemoteCommandCenter.shared()
playTarget = commandCenter.playCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
print("play \(event)")
return .success
}
pauseTarget = commandCenter.pauseCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
print("pause \(event)")
return .success
}
}
然后像这样删除目标:
func removeRemoteTargets() {
let commandCenter = MPRemoteCommandCenter.shared()
commandCenter.playCommand.removeTarget(playTarget)
playTarget = nil
commandCenter.pauseCommand.removeTarget(pauseTarget)
pauseTarget = nil
}
p.s。这些是 "seems to work!" 个答案。我不知道您应该如何确定 AVPlayer
何时完成其音频 I/O(除了通过 setActive:false
失败的轮询)。我的理由是成为锁定屏幕/"Now Playing App" 有 3 个部分(这在某处有记录,this 是我现在能找到的最接近的东西,尽管最明确的文档是如何做到这一点的作品在系统日志中):
- 不可混合的音频会话类别
MPRemoteCommandCenter
整合
- 当前或"recently" 完成的音频 IO
因此,如果您可以删除其中任何一个,锁定屏幕控件应该会消失。
试试这个
player.pause()
player.replaceCurrentItem(with: nil)
player = nil
AVPlayer
不会立即停止,因此您需要订阅其状态更改以在暂停时捕获。只有这样你才能安全地停用 AVAudioSession
。
Swift 5 个例子
var timeControlObservation: NSKeyValueObservation?
timeControlObservation = player.observe(\.timeControlStatus, changeHandler: { [weak player] (_, _) in
guard let player = player else {
return
}
if player.timeControlStatus != .playing {
// Finish your work here
AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
timeControlObservation = nil
}
}
player.pause()
我正在使用 AVPlayer
在我的 iOS 应用程序中播放音频(因为我正在播放的音频文件不是本地的),当我的曲目结束时,我想隐藏信息中心控件,但出现此错误:
AVAudioSession.mm:1079:-[AVAudioSession setActive:withOptions:error:]: Deactivating an audio session that has running I/O. All I/O should be stopped or paused prior to deactivating the audio session.
但是我之前暂停了我的AVPlayer
。
这是我的代码:
player.pause()
player.replaceCurrentItem(with: nil)
MPNowPlayingInfoCenter.default().nowPlayingInfo = nil
try? audioSession.setActive(false, options: .notifyOthersOnDeactivation)
由于这个错误,本机控件仍然可见,但不再工作。
您收到该错误是因为您在取消分配播放器之前停用了音频会话: 您可以通过以下方式解除分配:
play.pause()
player = nil
但您应该先声明您的播放器为可选播放器。
你的问题是关于:
您必须删除
player.replaceCurrentItem(with: nil)
MPNowPlayingInfoCenter.default().nowPlayingInfo = nil
一个只保留这个
player.pause()
try? audioSession.setActive(true, options: .notifyOthersOnDeactivation)
失去锁定屏幕控件的快速方法是使您的音频会话可混合(无需停用您的音频会话):
try! AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: .mixWithOthers)
当你想要它们时,删除 .mixWithOthers
。
另一种可能更可口的方法是在暂停播放后删除 MPRemoteCommandCenter
目标。例如如果你这样设置
var playTarget: Any? = nil
var pauseTarget: Any? = nil
func addRemoteTargets() {
let commandCenter = MPRemoteCommandCenter.shared()
playTarget = commandCenter.playCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
print("play \(event)")
return .success
}
pauseTarget = commandCenter.pauseCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
print("pause \(event)")
return .success
}
}
然后像这样删除目标:
func removeRemoteTargets() {
let commandCenter = MPRemoteCommandCenter.shared()
commandCenter.playCommand.removeTarget(playTarget)
playTarget = nil
commandCenter.pauseCommand.removeTarget(pauseTarget)
pauseTarget = nil
}
p.s。这些是 "seems to work!" 个答案。我不知道您应该如何确定 AVPlayer
何时完成其音频 I/O(除了通过 setActive:false
失败的轮询)。我的理由是成为锁定屏幕/"Now Playing App" 有 3 个部分(这在某处有记录,this 是我现在能找到的最接近的东西,尽管最明确的文档是如何做到这一点的作品在系统日志中):
- 不可混合的音频会话类别
MPRemoteCommandCenter
整合- 当前或"recently" 完成的音频 IO
因此,如果您可以删除其中任何一个,锁定屏幕控件应该会消失。
试试这个
player.pause()
player.replaceCurrentItem(with: nil)
player = nil
AVPlayer
不会立即停止,因此您需要订阅其状态更改以在暂停时捕获。只有这样你才能安全地停用 AVAudioSession
。
Swift 5 个例子
var timeControlObservation: NSKeyValueObservation?
timeControlObservation = player.observe(\.timeControlStatus, changeHandler: { [weak player] (_, _) in
guard let player = player else {
return
}
if player.timeControlStatus != .playing {
// Finish your work here
AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
timeControlObservation = nil
}
}
player.pause()