@@ -31,7 +31,8 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate, CAPBridgedPlugin {
3131 CAPPluginMethod ( name: " resume " , returnType: CAPPluginReturnPromise) ,
3232 CAPPluginMethod ( name: " setCurrentTime " , returnType: CAPPluginReturnPromise) ,
3333 CAPPluginMethod ( name: " clearCache " , returnType: CAPPluginReturnPromise) ,
34- CAPPluginMethod ( name: " getPluginVersion " , returnType: CAPPluginReturnPromise)
34+ CAPPluginMethod ( name: " getPluginVersion " , returnType: CAPPluginReturnPromise) ,
35+ CAPPluginMethod ( name: " deinitPlugin " , returnType: CAPPluginReturnPromise)
3536 ]
3637 internal let audioQueue = DispatchQueue ( label: " ee.forgr.audio.queue " , qos: . userInitiated, attributes: . concurrent)
3738 private var audioList : [ String : Any ] = [ : ] {
@@ -44,6 +45,12 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate, CAPBridgedPlugin {
4445 var fadeMusic = false
4546 var session = AVAudioSession . sharedInstance ( )
4647
48+ // Track if audio session has been initialized
49+ private var audioSessionInitialized = false
50+ // Store the original audio category to restore on deinit
51+ private var originalAudioCategory : AVAudioSession . Category ?
52+ private var originalAudioOptions : AVAudioSession . CategoryOptions ?
53+
4754 // Add observer for audio session interruptions
4855 private var interruptionObserver : Any ?
4956
@@ -53,7 +60,8 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate, CAPBridgedPlugin {
5360
5461 self . fadeMusic = false
5562
56- setupAudioSession ( )
63+ // Don't setup audio session on load - defer until first use
64+ // setupAudioSession()
5765 setupInterruptionHandling ( )
5866
5967 NotificationCenter . default. addObserver ( forName: UIApplication . didEnterBackgroundNotification, object: nil , queue: . main) { [ weak self] _ in
@@ -84,6 +92,13 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate, CAPBridgedPlugin {
8492 }
8593
8694 private func setupAudioSession( ) {
95+ // Save the original audio session category before making changes
96+ if !audioSessionInitialized {
97+ originalAudioCategory = session. category
98+ originalAudioOptions = session. categoryOptions
99+ audioSessionInitialized = true
100+ }
101+
87102 do {
88103 // Only set the category without immediately activating/deactivating
89104 try self . session. setCategory ( AVAudioSession . Category. playback, options: . mixWithOthers)
@@ -127,6 +142,13 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate, CAPBridgedPlugin {
127142 }
128143
129144 @objc func configure( _ call: CAPPluginCall ) {
145+ // Save original category on first configure call
146+ if !audioSessionInitialized {
147+ originalAudioCategory = session. category
148+ originalAudioOptions = session. categoryOptions
149+ audioSessionInitialized = true
150+ }
151+
130152 if let fade = call. getBool ( Constant . FadeKey) {
131153 self . fadeMusic = fade
132154 }
@@ -234,6 +256,11 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate, CAPBridgedPlugin {
234256 let time = max ( call. getDouble ( " time " ) ?? 0 , 0 ) // Ensure non-negative time
235257 let delay = max ( call. getDouble ( " delay " ) ?? 0 , 0 ) // Ensure non-negative delay
236258
259+ // Ensure audio session is initialized before first play
260+ if !audioSessionInitialized {
261+ setupAudioSession ( )
262+ }
263+
237264 // Use sync for operations that need to be blocking
238265 audioQueue. sync {
239266 guard !audioList. isEmpty else {
@@ -608,4 +635,36 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate, CAPBridgedPlugin {
608635 call. resolve ( [ " version " : self . PLUGIN_VERSION] )
609636 }
610637
638+ @objc func deinitPlugin( _ call: CAPPluginCall ) {
639+ // Stop all playing audio
640+ audioQueue. sync ( flags: . barrier) {
641+ for (_, asset) in self . audioList {
642+ if let audioAsset = asset as? AudioAsset {
643+ audioAsset. stop ( )
644+ }
645+ }
646+ }
647+
648+ // Restore original audio session settings if we changed them
649+ if audioSessionInitialized, let originalCategory = originalAudioCategory {
650+ do {
651+ // Deactivate our audio session
652+ try self . session. setActive ( false , options: . notifyOthersOnDeactivation)
653+
654+ // Restore original category and options
655+ if let originalOptions = originalAudioOptions {
656+ try self . session. setCategory ( originalCategory, options: originalOptions)
657+ } else {
658+ try self . session. setCategory ( originalCategory)
659+ }
660+
661+ audioSessionInitialized = false
662+ } catch {
663+ print ( " Failed to restore audio session: \( error) " )
664+ }
665+ }
666+
667+ call. resolve ( )
668+ }
669+
611670}
0 commit comments