Serg P
Serg P

Reputation: 264

AVAudioSessionInterruptionNotification with AVAudioSessionInterruptionWasSuspendedKey triggered when trying to resume from background

AVAudioPlayer plays audio on the background and user pauses it either through headset controls or lock screen controls. If user does it for under 30 seconds and tries to resume - everything works fine. If user tries to resume it in over 30 seconds - audio starts playing, but a second later audioSessionInterruptionNotification from AVAudioSessionDelegate is triggered, with AVAudioSessionInterruptionWasSuspendedKey YES.

After that the app stops reacting for remote controls events completely. Events are being triggered, but AVAudioPlayer does not react to any commands. In fact, [[self audioplayer] isAudioPlaying] returns NO while playback continues.

If I try to handle it the following way - it helps (so I set AVAudioSession to not active, and then playHelper method activates it and plays audio), but there is a glitch, because notification is being triggered after it starts playing.

- (void)audioSessionInterruptionNotification:(NSNotification *)interruption {
    UInt8 interruptionType = [[interruption.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] intValue];

    NSLog(@"Session interrupted > --- %s ---\n", interruptionType == AVAudioSessionInterruptionTypeBegan ? "Begin Interruption" : "End Interruption");
    NSDictionary *notificationUserInfo = [interruption userInfo];
    if (interruptionType == AVAudioSessionInterruptionTypeBegan) {
        if ([notificationUserInfo valueForKey:AVAudioSessionInterruptionWasSuspendedKey]) {
            [[AVAudioSession sharedInstance] setActive:false error:nil];
            [self playHelper];
        } else {
            [self interruptionStarted];
        }
    } else if (interruptionType == AVAudioSessionInterruptionTypeEnded) {
        [self interruptionEnded:(NSUInteger)[notificationUserInfo objectForKey:AVAudioSessionInterruptionOptionKey]];
    }
}

Please advise what could be causing this.

Upvotes: 3

Views: 825

Answers (1)

Adam
Adam

Reputation: 1913

The AVAudioSessionInterruptionWasSuspendedKey notification is thrown because you should deactivate your audio session whenever your app goes to background and nothing is playing. If your player is playing when user pauses from lock screen you don't have to deactivate the session.

You should listen for the notifications when your app is being sent to background and when it becomes active, the code in Swift should look like this.

NotificationCenter.default.addObserver(forName: UIApplication.willResignActiveNotification, object: nil, queue: .main) { sender in
            guard self.player.isPlaying == false else { return }
            self.setSession(active: false)
        }

NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: .main) { sender in
            guard self.player.isPlaying else { return }
            self.setSession(active: true)
        }

    func setSession(active: Bool) -> Bool {
        let session = AVAudioSession.sharedInstance()
        do {
            try session.setCategory(.playback, mode: .default)
            try session.setActive(active)
            return true
        } catch let error {
            print("*** Failed to activate audio session: \(error.localizedDescription)")
            return false
        }
    }

Upvotes: 1

Related Questions