From d7fe163de39e985f145174229c1d6038ed87a3d1 Mon Sep 17 00:00:00 2001 From: Gautier de Lataillade Date: Mon, 3 Jun 2024 18:20:31 +0200 Subject: [PATCH] Use optimized blank audio & backgrounf fetch --- assets/blank_30.mp3 | Bin 0 -> 30293 bytes example/ios/Podfile.lock | 4 +- example/ios/Runner.xcodeproj/project.pbxproj | 18 ++++ example/lib/screens/home.dart | 2 +- ios/Classes/SwiftAlarmPlugin.swift | 86 +++++++------------ 5 files changed, 51 insertions(+), 59 deletions(-) create mode 100644 assets/blank_30.mp3 diff --git a/assets/blank_30.mp3 b/assets/blank_30.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..59821a534bba4c4a2acf0b51767abe7056efe188 GIT binary patch literal 30293 zcmeI44}=s^9LI-U5p`Xwh!g1#cgc3O)se(imsZ=At|ckz%H>E`WQ*vJl0;G@q9YP1 zk;IWWnnWT_BvBHP9Ca%a+2+kOv-9WP&bi&&-Ff%fWA|phJ3H^U@4e6azTcbK^oCSi z6OZ{jy1F`y*9J|CW%lKIRxL{!f32;iXgwA3M+TkE^x>X9V`GM<#ZPNmu0@ManL4du z=B(Lsn&!@1u&8h+tUx9{G6`1twD*Kgm4e~kS4{pYVZ zxly+LM%hwHrzFNd3uEW4&0I_7Y+I*W(hB)T-PjS^B=%<7w{)b8u*}y&KA}&y6%lLJ zcv$Zc2Q}GJKxvjLE2YXhsj}6lSVa&e*ljDG!U?5Uq9pX(s7g{CWPC@~w-5;Es#NKh zD)*(zfKMp~^uksG0S!r%g#Kw%#SCcJmI48dOsG-}$T?3SAeoZTf7)g99AgIL98~3i zijCf1g78oYC{@$C3$LL@-KkYilN0=_!^TKJ&NxI3iQ!s|T}}(GG8w}gV_o(kfbQx; zuGRzpgbS{_K12=GmU7_2g$w0?PVcI1?+W)2)KG0}2>!vpDx0EmnjE;OEiRM;dO3|z zIlH7>K;QygnCo7ZN~FO*mF*Jz0~g@JeI@5g}aQ|L}kK zKm4D0Ic)gYr5rAl3yAz5KnLihfX@1d$_^d=!9Vy1|0b)Ug@5o5{=q-^r*Z!W_kYN4 zg7&ZSmNO}g*pORJsLG|wlnW?gjWImsOh6dgiW*w@NB%EDEA;RW{=q*c^kbaRg9~s` zQCukJ(D8rxKl~pTbW467(VrQFe=6gG{2z7+yHsj+1^?h5b_u&QS?v=1gMaW3{=q+I zX6(DLDq<;T@_#A=Jz|YfId?%oD)%ns(q+m81pi2AlF%%b(8T|#JVL=g_y_;s-xx2K r!~azS7h=H4W<9@1Z0-90JU+!$cb-qH_=#L&iswY*E4KX8A{o#>F*L_k literal 0 HcmV?d00001 diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 2ff0110d..ee190cad 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -33,8 +33,8 @@ SPEC CHECKSUMS: alarm: 6c1f6a9688f94cd6bf8f104c67cc26e78c9d8d13 Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 flutter_fgbg: 31c0d1140a131daea2d342121808f6aa0dcd879d - permission_handler_apple: 036b856153a2b1f61f21030ff725f3e6fece2b78 - shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 + permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 PODFILE CHECKSUM: c4c93c5f6502fe2754f48404d3594bf779584011 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 1ebb8375..c538aafe 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -139,6 +139,7 @@ 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 38B35C95769EE88AAB27208F /* [CP] Embed Pods Frameworks */, + 4A919127DC74F79AA2F73A63 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -253,6 +254,23 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + 4A919127DC74F79AA2F73A63 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; diff --git a/example/lib/screens/home.dart b/example/lib/screens/home.dart index 12e74b19..c133ce8d 100644 --- a/example/lib/screens/home.dart +++ b/example/lib/screens/home.dart @@ -110,7 +110,7 @@ class _ExampleAlarmHomeScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('alarm 3.1.4')), + appBar: AppBar(title: const Text('Battery Test #4')), body: SafeArea( child: alarms.isNotEmpty ? ListView.separated( diff --git a/ios/Classes/SwiftAlarmPlugin.swift b/ios/Classes/SwiftAlarmPlugin.swift index 136abc68..7f7bf441 100644 --- a/ios/Classes/SwiftAlarmPlugin.swift +++ b/ios/Classes/SwiftAlarmPlugin.swift @@ -26,7 +26,7 @@ public class SwiftAlarmPlugin: NSObject, FlutterPlugin { private var alarms: [Int: AlarmConfiguration] = [:] - private var silentAudioPlayer: AVAudioPlayer? + static private var silentAudioPlayer: AVAudioPlayer? private let resourceAccessQueue = DispatchQueue(label: "com.gdelataillade.alarm.resourceAccessQueue") private var notifOnKillEnabled: Bool! @@ -187,15 +187,15 @@ public class SwiftAlarmPlugin: NSObject, FlutterPlugin { } private func startSilentSound() { - let filename = registrar.lookupKey(forAsset: "assets/long_blank.mp3", fromPackage: "alarm") + let filename = registrar.lookupKey(forAsset: "assets/blank_30.mp3", fromPackage: "alarm") if let audioPath = Bundle.main.path(forResource: filename, ofType: nil) { let audioUrl = URL(fileURLWithPath: audioPath) do { - self.silentAudioPlayer = try AVAudioPlayer(contentsOf: audioUrl) - self.silentAudioPlayer?.numberOfLoops = -1 - self.silentAudioPlayer?.volume = 0.1 + SwiftAlarmPlugin.silentAudioPlayer = try AVAudioPlayer(contentsOf: audioUrl) + SwiftAlarmPlugin.silentAudioPlayer?.numberOfLoops = -1 + SwiftAlarmPlugin.silentAudioPlayer?.volume = 0.1 self.playSilent = true - self.silentAudioPlayer?.play() + SwiftAlarmPlugin.silentAudioPlayer?.play() NotificationCenter.default.addObserver(self, selector: #selector(handleInterruption), name: AVAudioSession.interruptionNotification, object: nil) } catch { NSLog("[SwiftAlarmPlugin] Error: Could not create and play silent audio player: \(error)") @@ -206,28 +206,13 @@ public class SwiftAlarmPlugin: NSObject, FlutterPlugin { } @objc func handleInterruption(notification: Notification) { - guard let info = notification.userInfo, - let typeValue = info[AVAudioSessionInterruptionTypeKey] as? UInt, - let type = AVAudioSession.InterruptionType(rawValue: typeValue) else { - return - } - - switch type { - case .began: - self.silentAudioPlayer?.play() - NSLog("SwiftAlarmPlugin: Interruption began") - case .ended: - self.silentAudioPlayer?.play() - NSLog("SwiftAlarmPlugin: Interruption ended") - default: - break - } + SwiftAlarmPlugin.silentAudioPlayer?.play() } private func loopSilentSound() { - self.silentAudioPlayer?.play() + SwiftAlarmPlugin.silentAudioPlayer?.play() DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { - self.silentAudioPlayer?.pause() + SwiftAlarmPlugin.silentAudioPlayer?.pause() DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) { if self.playSilent { self.loopSilentSound() @@ -306,10 +291,10 @@ public class SwiftAlarmPlugin: NSObject, FlutterPlugin { safeModifyResources { if self.alarms.isEmpty { self.playSilent = false + SwiftAlarmPlugin.cancelBackgroundTasks() DispatchQueue.main.async { - self.silentAudioPlayer?.stop() + SwiftAlarmPlugin.silentAudioPlayer?.stop() NotificationCenter.default.removeObserver(self) - SwiftAlarmPlugin.cancelBackgroundTasks() } } } @@ -348,32 +333,23 @@ public class SwiftAlarmPlugin: NSObject, FlutterPlugin { } } - private func backgroundFetch() { + @available(iOS 13.0, *) + private func backgroundFetch(task: BGTask) { self.mixOtherAudios() - self.silentAudioPlayer?.pause() - self.silentAudioPlayer?.play() - - safeModifyResources { - let ids = Array(self.alarms.keys) - - for id in ids { - NSLog("SwiftAlarmPlugin: Background check alarm with id \(id)") - if let audioPlayer = self.alarms[id]?.audioPlayer, let dateTime = self.alarms[id]?.triggerTime { - let currentTime = audioPlayer.deviceCurrentTime - let time = currentTime + dateTime.timeIntervalSinceNow - audioPlayer.play(atTime: time) - } + NSLog("SwiftAlarmPlugin: Background fetch triggered") - if let alarm = self.alarms[id], let delayInSeconds = alarm.triggerTime?.timeIntervalSinceNow { - DispatchQueue.main.async { - self.safeModifyResources { - alarm.timer = Timer.scheduledTimer(timeInterval: delayInSeconds, target: self, selector: #selector(self.executeTask(_:)), userInfo: id, repeats: false) - } - } - } - } + guard let silentAudioPlayer = SwiftAlarmPlugin.silentAudioPlayer else { + NSLog("SwiftAlarmPlugin: Failed to initialize silent audio player") + task.setTaskCompleted(success: false) + return } + + silentAudioPlayer.play() + + task.setTaskCompleted(success: true) + NSLog("SwiftAlarmPlugin: Background fetch completed successfully.") + SwiftAlarmPlugin.scheduleAppRefresh() } private func stopNotificationOnKillService() { @@ -456,12 +432,10 @@ public class SwiftAlarmPlugin: NSObject, FlutterPlugin { static public func registerBackgroundTasks() { if #available(iOS 13.0, *) { BGTaskScheduler.shared.register(forTaskWithIdentifier: backgroundTaskIdentifier, using: nil) { task in - self.scheduleAppRefresh() - sharedInstance.backgroundFetch() - task.setTaskCompleted(success: true) + sharedInstance.backgroundFetch(task: task) } } else { - NSLog("SwiftAlarmPlugin: BGTaskScheduler not available for your version of iOS lower than 13.0") + NSLog("SwiftAlarmPlugin: BGTaskScheduler not available for iOS versions lower than 13.0") } } @@ -469,15 +443,15 @@ public class SwiftAlarmPlugin: NSObject, FlutterPlugin { static func scheduleAppRefresh() { if #available(iOS 13.0, *) { let request = BGAppRefreshTaskRequest(identifier: backgroundTaskIdentifier) + request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) // 15 minutes - request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) do { try BGTaskScheduler.shared.submit(request) } catch { NSLog("SwiftAlarmPlugin: Could not schedule app refresh: \(error)") } } else { - NSLog("SwiftAlarmPlugin: BGTaskScheduler not available for your version of iOS lower than 13.0") + NSLog("SwiftAlarmPlugin: BGTaskScheduler not available for iOS versions lower than 13.0") } } @@ -486,7 +460,7 @@ public class SwiftAlarmPlugin: NSObject, FlutterPlugin { if #available(iOS 13.0, *) { BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: backgroundTaskIdentifier) } else { - NSLog("SwiftAlarmPlugin: BGTaskScheduler not available for your version of iOS lower than 13.0") + NSLog("SwiftAlarmPlugin: BGTaskScheduler not available for iOS versions lower than 13.0") } } -} \ No newline at end of file +}