无法通过AVPlayer设置AudioSession处于非活动状态

时间:2019-05-14 14:36:08

标签: ios swift avplayer mpnowplayinginfocenter

我正在使用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)

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

enter image description here

5 个答案:

答案 0 :(得分:2)

丢失锁屏控件的快速方法是使音频会话可混合(停用音频会话):

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。这些是“似乎可以工作!”答案。我不知道您应该如何确定AVPlayer何时完成其音频I / O(除了通过setActive:false进行的轮询失败之外)。我的理由是,成为锁定屏幕/“正在播放应用程序”有3个部分(这在某处有记录,this是我现在所能找到的最接近的东西,尽管有关此情况的最明确的记录作品在系统日志中):

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

因此,如果您可以卸下这些部件中的任何一个,则锁定屏幕控件应消失。

答案 1 :(得分:1)

您收到该错误,是因为您在取消分配播放器之前先停用了音频会话: 您可以使用以下方法取消分配它:

play.pause()
player = nil

,但是您应该先声明播放器为可选播放器。 您的问题与: Impossible to stop AVPlayer

答案 2 :(得分:0)

您必须删除

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

唯一保留此

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

答案 3 :(得分:0)

尝试一下

if(isset($_POST['submit'])) {
    $id     = $_POST['id'];
    for($i = 0; $i < count($_FILES['file_upload']['name']); $i++){
      $filetmp  = $_FILES['file_upload']['tmp_name'][$i];
      $filename = basename($_FILES['file_upload']['name'][$i]);
      $filetype = $_FILES['file_upload']['type'][$i];
      $filepath = "../images/".$filename;
      move_uploaded_file($filetmp,$filepath);
    }
      $mainfiles = implode(", ", $filename);

      $sql  = "INSERT INTO pictures2 (";
      $sql .= "image, photograph_id";
      $sql .= ") VALUES ('";
      $sql .= $database->escape_character($mainfiles) ."', '";  
      $sql .= $id ."')";
      $result = $database->query($sql);
        if($result){
        $session->message('<div class="success-msg">Pictures uploaded sucessfully.</div>');
        }

}

答案 4 :(得分:0)

AVPlayer不会立即停止,因此您需要订阅其状态更改以使其暂停。只有这样,您才能安全地停用AVAudioSession

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