web-dev-qa-db-fra.com

AVplayer reprend après un appel entrant

J'utilise AVPlayer pour la lecture de musique. Mon problème est que, après un appel entrant, le lecteur ne reprendra pas. Comment gérer cela quand un appel entrant arrive?

24
user2889249

À partir de iOS 6, vous devez gérer AVAudioSessionInterruptionNotification et AVAudioSessionMediaServicesWereResetNotification. Avant cela, vous deviez utiliser des méthodes de délégation.

Vous devez d’abord appeler le singleton AVAudioSession et le configurer pour votre utilisation souhaitée. 

Par exemple:

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

Ensuite, vous devez implémenter deux méthodes, pour les notifications que AVAudioSession appellera:

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

La première concerne toutes les interruptions appelées en raison d’un appel entrant, d’un réveil, etc.

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

Le second, si le serveur multimédia est réinitialisé pour une raison quelconque, vous devez gérer cette notification pour reconfigurer l'audio ou effectuer toute opération de maintenance. En passant, le dictionnaire de notification ne contiendra aucun objet. 

Voici un exemple pour gérer l'interruption de la lecture:

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

Notez que vous devez reprendre la lecture lorsque la valeur optionnelle est AVAudioSessionInterruptionOptionShouldResume

Et pour l'autre notification, vous devez prendre en charge les éléments suivants:

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

Cordialement.

55
javiergov

AVAudioSession enverra une notification quand une interruption commence et se termine. Voir Traitement des interruptions audio

- (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;
    }
}
8
Neal Ehardt

Dans certains cas, ma AVPlayer ne reprend pas la lecture, même si j'appelle play(). Seulement recharger le lecteur m'aide à résoudre le problème:

    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
Vitaliy Gozhenko

Je dois attendre 2 secondes pour que cela fonctionne.

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

            self.player.play()
        }

Le func entier:

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

        }
    }
}
0
Chen Jiling