Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resuming AVPlayer after being interrupted with SwiftUI

I'm building a radio streaming app using AVPlayer and AVPlayerItem. I've built my app to keep playing the radio in the background like this:

do {
    try AVAudioSession.sharedInstance().setCategory(.playback)
    try AVAudioSession.sharedInstance().setActive(true)
} catch {
   print(error)
}

After the AVPlayer is interrupted (for example, when the user receives a call) the AVPlayer isn't resuming playing. I need to actively play it again in order to listen to the streaming.

How can I make the AVPlayer to automatically resume after being interrupted using SwiftUI? (I've found some solutions but non of them is suitable for working with SwiftUI.

Thank you!

like image 798
F.SO7 Avatar asked Sep 15 '25 22:09

F.SO7


2 Answers

There's nothing related to SwiftUI, or UI in general, to restart playback after an interruption.

As said in apple documentation:

First register to the notification of the interruption:

func registerForNotifications() {
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(handleInterruption),
                                           name: .AVAudioSessionInterruption,
                                           object: AVAudioSession.sharedInstance())
}

Then handle the notification like this:

func handleInterruption(_ notification: Notification) {
    guard let info = notification.userInfo,
        let typeValue = info[AVAudioSessionInterruptionTypeKey] as? UInt,
        let type = AVAudioSessionInterruptionType(rawValue: typeValue) else {
            return
    }
    if type == .began {
        // Interruption began, take appropriate actions (save state, update user interface)
    }
    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
        }
    }
}

If that doesn't help, you could explain better the issue you are having with other solutions that don't work in your case.

like image 145
Enricoza Avatar answered Sep 17 '25 13:09

Enricoza


SwiftUI

Call the .onReceive function on your play button like this:

.onReceive(NotificationCenter.default.publisher(for: AVAudioSession.interruptionNotification)) { event in
    guard let info = event.userInfo,
        let typeValue = info[AVAudioSessionInterruptionTypeKey] as? UInt,
        let type = AVAudioSession.InterruptionType(rawValue: typeValue) else {
            return
    }
    if type == .began {
        // Interruption began, take appropriate actions (save state, update user interface)
    }
    else if type == .ended {
        guard let optionsValue =
            info[AVAudioSessionInterruptionOptionKey] as? UInt else {
                return
        }
        let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)
        if options.contains(.shouldResume) {
            // Interruption Ended - playback should resume
            player.play()
        }
    }
}
like image 26
Malsor Avatar answered Sep 17 '25 12:09

Malsor