web-dev-qa-db-ja.com

着信後にAVplayerが再開する

音楽の再生にAVPlayerを使用しています。私の問題は、電話がかかってきた後、プレーヤーが再開しないことです。着信があったときにこれをどのように処理しますか?

26
user2889249

IOS 6以降、デリゲートメソッドを使用する前に、AVAudioSessionInterruptionNotificationAVAudioSessionMediaServicesWereResetNotificationを処理する必要があります。

最初に、AVAudioSessionシングルトンを呼び出して、目的の用途に合わせて構成します。

例えば:

AVAudioSession *aSession = [AVAudioSession sharedInstance];
[aSession setCategory:AVAudioSessionCategoryPlayback
          withOptions:AVAudioSessionCategoryOptionAllowBluetooth 
                error:&error];
[aSession setMode:AVAudioSessionModeDefault error:&error];
[aSession setActive: YES error: &error];

次に、AVAudioSessionが呼び出す通知のために、2つのメソッドを実装する必要があります。

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(handleAudioSessionInterruption:)
                                             name:AVAudioSessionInterruptionNotification
                                           object:aSession];

1つ目は、着信や目覚まし時計などが原因で呼び出される割り込みです。

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(handleMediaServicesReset)
                                             name:AVAudioSessionMediaServicesWereResetNotification
                                           object:aSession];

2つ目は、何らかの理由でメディアサーバーがリセットされた場合、この通知を処理してオーディオを再構成するか、ハウスキーピングを実行する必要があります。ちなみに、通知ディクショナリにはオブジェクトが含まれていません。

再生の中断を処理する例を次に示します。

- (void)handleAudioSessionInterruption:(NSNotification*)notification {

    NSNumber *interruptionType = [[notification userInfo] objectForKey:AVAudioSessionInterruptionTypeKey];
    NSNumber *interruptionOption = [[notification userInfo] objectForKey:AVAudioSessionInterruptionOptionKey];

    switch (interruptionType.unsignedIntegerValue) {
        case AVAudioSessionInterruptionTypeBegan:{
            // • Audio has stopped, already inactive
            // • Change state of UI, etc., to reflect non-playing state
        } break;
        case AVAudioSessionInterruptionTypeEnded:{
            // • Make session active
            // • Update user interface
            // • AVAudioSessionInterruptionOptionShouldResume option
            if (interruptionOption.unsignedIntegerValue == AVAudioSessionInterruptionOptionShouldResume) {
                // Here you should continue playback.
                [player play];
            }
        } break;
        default:
            break;
    }
}

オプションの値がAVAudioSessionInterruptionOptionShouldResumeのときに再生を再開する必要があることに注意してください。

その他の通知については、次の点に注意してください。

- (void)handleMediaServicesReset {
// • No userInfo dictionary for this notification
// • Audio streaming objects are invalidated (zombies)
// • Handle this notification by fully reconfiguring audio
}

よろしく。

55
javiergov

AVAudioSessionは、割り込みの開始と終了時に通知を送信します。参照 オーディオ割り込みの処理

- (id)init
{
    if (self = [super init]) {
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];

        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
        [center addObserver:self selector:@selector(audioSessionInterrupted:) name:AVAudioSessionInterruptionNotification object:nil];
    }
}

- (void)audioSessionInterrupted:(NSNotification *)notification
{
    int interruptionType = [notification.userInfo[AVAudioSessionInterruptionTypeKey] intValue];
    if (interruptionType == AVAudioSessionInterruptionTypeBegan) {
        if (_state == GBPlayerStateBuffering || _state == GBPlayerStatePlaying) {
            NSLog(@"Pausing for audio session interruption");
            pausedForAudioSessionInterruption = YES;
            [self pause];
        }
    } else if (interruptionType == AVAudioSessionInterruptionTypeEnded) {
        if ([notification.userInfo[AVAudioSessionInterruptionOptionKey] intValue] == AVAudioSessionInterruptionOptionShouldResume) {
            if (pausedForAudioSessionInterruption) {
                NSLog(@"Resuming after audio session interruption");
                [self play];
            }
        }
        pausedForAudioSessionInterruption = NO;
    }
}
9
Neal Ehardt

それが機能するように私は2秒待つ必要があります。

        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {

            self.player.play()
        }

Func全体:

func playerInterruption(notification: NSNotification) {

    guard let userInfo = notification.userInfo,
        let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
        let type = AVAudioSessionInterruptionType(rawValue: typeValue) else {
            return
    }
    if type == .began {
        // Interruption began, take appropriate actions (save state, update user interface)
        player.pause()
    }
    else if type == .ended {

        guard let optionsValue =
            userInfo[AVAudioSessionInterruptionOptionKey] as? UInt else {

                return
        }
        let options = AVAudioSessionInterruptionOptions(rawValue: optionsValue)
        if options.contains(.shouldResume) {
            // Interruption Ended - playback should resume

            DispatchQueue.main.asyncAfter(deadline: .now() + 2) {

                self.player.play()
            }

        }
    }
}
1
Chen Jiling

「AVAudioPlayer」コントローラーで同じ問題が発生しました。 「AVAudioSession.interruptionNotification」を使用すると、オーディオがバックグラウンドで再生されていても、中断が終了するとオーディオの再生を再開できます。

    @objc func interruptionNotification(notification: Notification) {
    guard let type = notification.userInfo?[AVAudioSessionInterruptionTypeKey] as? UInt,
        let interruption = AVAudioSession.InterruptionType(rawValue: type) else {
            return
    }

    if interruption == .began{
        print("Pause audio....")
        self.player?.pause()
        do {
            try AVAudioSession.sharedInstance().setActive(false)
            print("AVAudioSession is inactive")
        } catch let error as NSError {
            print(error.localizedDescription)
        }
    }

    if interruption == .ended{
        print("Play audio....")
        do {
            try AVAudioSession.sharedInstance().setActive(true)
            print("AVAudioSession is Active again")
            self.player?.play()
        } catch let error as NSError {
            print(error.localizedDescription)
        }
    }
}

ここでは、最初に、中断されたときにInActive AVAudioSessionを、中断が終了するとActive AVAudioSessionを実行する必要があります。ちゃんと動いているので試してみてください!

1
kb920

場合によっては、play()を呼び出しても、AVPlayerが再生を再開しないことがあります。プレーヤーをリロードするだけで問題を解決できます:

    func interruptionNotification(_ notification: Notification) {
    guard let type = notification.userInfo?[AVAudioSessionInterruptionTypeKey] as? UInt,
      let interruption = AVAudioSessionInterruptionType(rawValue: type) else {
        return
    }
    if interruption == .ended && playerWasPlayingBeforeInterruption {
      player.replaceCurrentItem(with: AVPlayerItem(url: radioStation.url))
      play()
    }
  }
1