无法使用 AVPlayer 将 AudioSession 设置为非活动状态

eny*_*nyo 8 ios avplayer mpnowplayinginfocenter swift

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

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)
Run Code Online (Sandbox Code Playgroud)

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

在此处输入图片说明

Rhy*_*man 3

失去锁定屏幕控件的一种快速方法是使音频会话可混合(无需停用音频会话):

try! AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: .mixWithOthers)
Run Code Online (Sandbox Code Playgroud)

.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
    }
}
Run Code Online (Sandbox Code Playgroud)

然后像这样删除目标:

func removeRemoteTargets() {
    let commandCenter = MPRemoteCommandCenter.shared()
    commandCenter.playCommand.removeTarget(playTarget)
    playTarget = nil
    commandCenter.pauseCommand.removeTarget(pauseTarget)
    pauseTarget = nil
}
Run Code Online (Sandbox Code Playgroud)

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

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

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