@@ -11,11 +11,12 @@ import UIKit
1111class AudioBackgroundService {
1212 private var player : AVAudioPlayer ?
1313 private var backgroundTask : UIBackgroundTaskIdentifier ?
14+ private var asyncTask : Task < Void , Error > ?
1415}
1516
1617extension AudioBackgroundService : BackgroundServiceProtocol {
1718 var isRunning : Bool {
18- player? . isPlaying ?? false
19+ ( player? . isPlaying ?? false ) || ( backgroundTask != nil && backgroundTask != . invalid )
1920 }
2021
2122 func start( ) -> Bool {
@@ -27,6 +28,7 @@ extension AudioBackgroundService: BackgroundServiceProtocol {
2728
2829 func stop( ) {
2930 NotificationCenter . default. removeObserver ( self , name: AVAudioSession . interruptionNotification, object: nil )
31+ asyncTask? . cancel ( )
3032 stopBackgroundTask ( )
3133 stopAudio ( )
3234 }
@@ -50,20 +52,34 @@ private extension AudioBackgroundService {
5052 }
5153 }
5254
55+ static func cratePlayer( ) throws -> AVAudioPlayer {
56+ // let bundle = Bundle.main.path(forResource: "3", ofType: "wav")
57+ let bundle = Bundle . main. path ( forResource: " sound " , ofType: " m4a " )
58+ let alertSound = URL ( fileURLWithPath: bundle!)
59+ try AVAudioSession . sharedInstance ( ) . setCategory ( . playback, options: . mixWithOthers)
60+ try AVAudioSession . sharedInstance ( ) . setActive ( true )
61+ let player = try AVAudioPlayer ( contentsOf: alertSound)
62+ player. volume = 0.01
63+ player. numberOfLoops = - 1
64+ return player
65+ }
66+
67+ func getPlayer( ) throws -> AVAudioPlayer {
68+ if let player {
69+ return player
70+ }
71+
72+ let newPlayer = try Self . cratePlayer ( )
73+ player = newPlayer
74+ return newPlayer
75+ }
76+
5377 @discardableResult
5478 func playAudio( ) -> Bool {
5579 do {
56- // let bundle = Bundle.main.path(forResource: "3", ofType: "wav")
57- let bundle = Bundle . main. path ( forResource: " sound " , ofType: " m4a " )
58- let alertSound = URL ( fileURLWithPath: bundle!)
59- try AVAudioSession . sharedInstance ( ) . setCategory ( . playback, options: . mixWithOthers)
60- try AVAudioSession . sharedInstance ( ) . setActive ( true )
61- try player = AVAudioPlayer ( contentsOf: alertSound)
62-
63- player? . volume = 0.01
64- player? . numberOfLoops = - 1
65- player? . prepareToPlay ( )
66- player? . play ( )
80+ let player = try getPlayer ( )
81+ // player.prepareToPlay()
82+ player. play ( )
6783 return true
6884 } catch {
6985 print ( error)
@@ -76,15 +92,28 @@ private extension AudioBackgroundService {
7692 }
7793
7894 func startBackgroundTask( ) {
79- guard BackgroundService . isBackgroundNeeded else { return }
95+ guard BackgroundService . isBackgroundNeeded else {
96+ stopBackgroundTask ( )
97+ stopAudio ( )
98+ return
99+ }
80100
81- Task {
101+ asyncTask = Task {
82102 playAudio ( )
83103 stopBackgroundTask ( )
84104
85- backgroundTask = await UIApplication . shared. beginBackgroundTask ( )
105+ backgroundTask = await UIApplication . shared. beginBackgroundTask { [ weak self] in
106+ guard let self else { return }
107+ print ( " \( Date . now. timestamp) [BG] timeout!!! " )
108+ startBackgroundTask ( )
109+ }
110+
86111 stopAudio ( )
87- // await print(UIApplication.shared.backgroundTimeRemaining)
112+ try Task . checkCancellation ( )
113+
114+ // If cannot start BG try again
115+ guard backgroundTask != . invalid else { return startBackgroundTask ( ) }
116+ print ( " \( Date . now. timestamp) [BG] running!!! " )
88117 try await Task . sleep ( for: . seconds( 10 ) )
89118 startBackgroundTask ( )
90119 }
@@ -98,16 +127,10 @@ private extension AudioBackgroundService {
98127 }
99128}
100129
101- extension TimeInterval {
102- var seconds : Int {
103- return Int ( self . rounded ( ) )
104- }
105-
106- var milliseconds : Int {
107- return Int ( self * 1_000 )
108- }
109-
110- var nanoseconds : UInt64 {
111- return UInt64 ( self * 1_000_000_000 )
130+ extension Date {
131+ var timestamp : String {
132+ let formatter = DateFormatter ( )
133+ formatter. dateFormat = " HH:mm:ss.SSSZZZZZ "
134+ return formatter. string ( from: self )
112135 }
113136}
0 commit comments