【问题标题】:Unable to set AudioSession inactive with AVPlayer无法使用 AVPlayer 将 AudioSession 设置为非活动状态
【发布时间】:2019-10-01 15:09:35
【问题描述】:

我正在使用AVPlayer 在我的 iOS 应用程序中播放音频(因为我正在播放的音频文件不是本地的),当我的曲目完成时,我想隐藏 InfoCenter 控件,但我收到此错误:

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)

由于此错误,本机控件仍然可见,但不再起作用。

【问题讨论】:

  • 嗯...这对我没有帮助。我没有使用队列.. 我只有一个 AVPlayer 一次播放一首曲目...
  • 我猜this link 会帮你解决这个问题。
  • 如果你停止而不是暂停怎么办?
  • @matt AVPlayer 没有像 AVAudioPlayer 那样的停止功能

标签: ios swift avplayer mpnowplayinginfocenter


【解决方案1】:

消除锁定屏幕控制的一种快速方法是使您的音频会话可混合(不停用您的音频会话):

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
}

附言这些是“似乎有效!”答案。我不知道您应该如何确定 AVPlayer 何时完成其音频 I/O(除了通过 setActive:false 轮询失败)。我的理由是成为锁屏/“正在播放的应用程序”有 3 个部分(这在某处有记录,this 是我现在能找到的最接近的东西,尽管关于它如何工作的最明确的文档是在系统日志中):

  1. 不可混合的音频会话类别
  2. MPRemoteCommandCenter 整合
  3. 当前或“最近”完成的音频 IO

因此,如果您可以删除其中任何一个,锁定屏幕控件应该会消失。

【讨论】:

  • 删除togglePlayPauseCommand 目标是唯一对我有用的方法。所有其他提示(将播放器设置为 nil 等)并没有改变我收到的错误消息。
  • 您添加的任何命令也必须删除,我应该明确说明
  • 是的,我很清楚。我已经删除了我正在使用的所有目标并且它有效。我的评论是参考其他解决方案,这对我不起作用。
【解决方案2】:

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()

【讨论】:

    【解决方案3】:

    您收到该错误是因为您在释放播放器之前停用了音频会话: 您可以使用以下方式解除分配:

    play.pause()
    player = nil
    

    但您应该首先将您的播放器声明为可选。 您的问题与以下内容有关: Impossible to stop AVPlayer

    【讨论】:

      【解决方案4】:

      你必须删除

      player.replaceCurrentItem(with: nil)
      MPNowPlayingInfoCenter.default().nowPlayingInfo = nil
      

      只保留这个

      player.pause()
      try? audioSession.setActive(true, options: .notifyOthersOnDeactivation)
      

      【讨论】:

      • 这不起作用。还是得到了:Deactivating an audio session that has running I/O. All I/O should be stopped or paused prior to deactivating the audio session.
      【解决方案5】:

      试试这个

      player.pause()
      player.replaceCurrentItem(with: nil)
      player = nil
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-31
        • 2018-05-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-21
        • 1970-01-01
        相关资源
        最近更新 更多