Skip to content

Commit

Permalink
Setup AVAudioSession notification handling to process interruptions
Browse files Browse the repository at this point in the history
  • Loading branch information
wvanhaevre committed Aug 9, 2024
1 parent 8807110 commit c14e338
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 1 deletion.
6 changes: 5 additions & 1 deletion ios/THEOplayerRCTView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ public class THEOplayerRCTView: UIView {
var adsConfig = AdsConfig()
var castConfig = CastConfig()
var uiConfig = UIConfig()
var backgroundAudioConfig = BackgroundAudioConfig()

var mediaControlConfig = MediaControlConfig() {
didSet {
Expand All @@ -34,6 +33,11 @@ public class THEOplayerRCTView: UIView {
self.pipControlsManager.setPipConfig(pipConfig)
}
}
var backgroundAudioConfig = BackgroundAudioConfig() {
didSet {
self.updateInterruptionNotifications()
}
}

// MARK: Events
var onNativePlayerReady: RCTDirectEventBlock?
Expand Down
50 changes: 50 additions & 0 deletions ios/backgroundAudio/THEOplayerRCTView+BackgroundAudioConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import Foundation
import THEOplayerSDK
import AVFAudio

struct BackgroundAudioConfig {
var enabled: Bool = false
Expand All @@ -19,6 +20,9 @@ extension THEOplayerRCTView: BackgroundPlaybackDelegate {
return
}
player.backgroundPlaybackDelegate = DefaultBackgroundPlaybackDelegate()
NotificationCenter.default.removeObserver(self,
name: AVAudioSession.interruptionNotification,
object: AVAudioSession.sharedInstance())
}

public func shouldContinueAudioPlaybackInBackground() -> Bool {
Expand All @@ -27,6 +31,52 @@ extension THEOplayerRCTView: BackgroundPlaybackDelegate {

return self.backgroundAudioConfig.enabled
}

func updateInterruptionNotifications() {
// Get the default notification center instance.
if self.backgroundAudioConfig.shouldResumeAfterInterruption {
NotificationCenter.default.addObserver(self,
selector: #selector(handleInterruption),
name: AVAudioSession.interruptionNotification,
object: AVAudioSession.sharedInstance())
} else {
NotificationCenter.default.removeObserver(self,
name: AVAudioSession.interruptionNotification,
object: AVAudioSession.sharedInstance())
}
}


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

// Switch over the interruption type.
switch type {
case .began:
// An interruption began. Update the UI as necessary.
if DEBUG_INTERRUPTIONS { PrintUtils.printLog(logText: "[INTERRUPTION] An interruption began")}
case .ended:
// An interruption ended. Resume playback, if appropriate.
if DEBUG_INTERRUPTIONS { PrintUtils.printLog(logText: "[INTERRUPTION] An interruption ended")}
guard let optionsValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt else { return }
let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)
if options.contains(.shouldResume) {
// An interruption ended. Resume playback.
if let player = self.player {
if DEBUG_INTERRUPTIONS { PrintUtils.printLog(logText: "[INTERRUPTION] Ended interruption should resume playback => play()")}
player.play()
}
} else {
// An interruption ended. Don't resume playback.
if DEBUG_INTERRUPTIONS { PrintUtils.printLog(logText: "[INTERRUPTION] Ended interruption should not resume playback.")}
}
default: ()
}
}
}

struct DefaultBackgroundPlaybackDelegate: BackgroundPlaybackDelegate {
Expand Down

0 comments on commit c14e338

Please sign in to comment.