AVplayer возобновляется после входящего звонка

Я использую AVPlayer для воспроизведения музыки. Моя проблема в том, что после входящего звонка плеер не возобновит работу. Как мне справиться с этим, когда приходит входящий звонок?

4 ответа

Начиная с iOS 6 вы должны справиться AVAudioSessionInterruptionNotification а также AVAudioSessionMediaServicesWereResetNotificationДо этого вы должны были использовать методы делегата.

Сначала вы должны вызвать синглтон AVAudioSession и настроить его для желаемого использования.

Например:

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

Затем вы должны реализовать два метода для уведомлений, которые вызовет AVAudioSession:

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

Первый - для любого прерывания, которое будет вызвано из-за входящего вызова, будильника и т. Д.

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

Второе, если медиа-сервер перезагружается по какой-либо причине, вы должны обработать это уведомление, чтобы перенастроить аудио или выполнить любую служебную работу. Кстати, словарь уведомлений не будет содержать никаких объектов.

Вот пример для обработки прерывания воспроизведения:

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

С уважением.

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;
    }
}

Привет всем, кто это читал. Хочу поделиться своим опытом сAVAudioSessionInterruptionNotification. Это сводило меня с ума. Я потратил день, чтобы найти решение. Я перепробовал все написанное выше и ничего не помогло. iOS 13.2.3. По какой-то причине это уведомление не работает должным образом сAVAudioSessionCategoryPlayback. И исправление для меня было просто заменить его наAVAudioSessionCategoryPlayAndRecord и я начал получать AVAudioSessionInterruptionTypeEnded См. Пример ниже:

-(void)setupAudioSession {

    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
    [[AVAudioSession sharedInstance] setMode:AVAudioSessionModeDefault error:nil];
    [[AVAudioSession sharedInstance] setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];    
}

После этого зарегистрируйте своего наблюдателя, например:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionHandleIntrruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];

И собственно реализуем метод прерывания:

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

    NSDictionary *userInfo = notification.userInfo;
    int interruptionType = [userInfo[AVAudioSessionInterruptionTypeKey] intValue];

    if (interruptionType == AVAudioSessionInterruptionTypeBegan) {
        //Interruption begun

    } else if (interruptionType == AVAudioSessionInterruptionTypeEnded) {
        int interruptionOption = [userInfo[AVAudioSessionInterruptionOptionKey] intValue];

        BOOL shouldResumePlayback = interruptionOption == AVAudioSessionInterruptionOptionShouldResume;

        if (shouldResumePlayback) {
            //Resume playback if needed
        }
    }
}

Надеюсь, это поможет кому-то сэкономить много времени.

В некоторых случаях мой AVPlayer не возобновлять игру, даже если я позвоню play(), Только перезагрузка плеера помогает мне решить проблему:

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

У меня была такая же проблема в контроллере "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, когда прерывание закончилось. Он работает отлично, попробуйте!

Мне нужно подождать 2 секунды, чтобы все заработало.

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

            self.player.play()
        }

Весь функционал:

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

        }
    }
}
Другие вопросы по тегам