BackgroundRefreshManager.swift 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. // LoopFollow
  2. // BackgroundRefreshManager.swift
  3. import BackgroundTasks
  4. import UIKit
  5. class BackgroundRefreshManager {
  6. static let shared = BackgroundRefreshManager()
  7. private init() {}
  8. private let taskIdentifier = "\(Bundle.main.bundleIdentifier ?? "com.loopfollow").audiorefresh"
  9. func register() {
  10. BGTaskScheduler.shared.register(forTaskWithIdentifier: taskIdentifier, using: nil) { task in
  11. guard let refreshTask = task as? BGAppRefreshTask else { return }
  12. self.handleRefreshTask(refreshTask)
  13. }
  14. }
  15. private func handleRefreshTask(_ task: BGAppRefreshTask) {
  16. LogManager.shared.log(category: .taskScheduler, message: "BGAppRefreshTask fired")
  17. // Guard against double setTaskCompleted if expiration fires while the
  18. // main-queue block is in-flight (Apple documents this as a programming error).
  19. var completed = false
  20. task.expirationHandler = {
  21. guard !completed else { return }
  22. completed = true
  23. LogManager.shared.log(category: .taskScheduler, message: "BGAppRefreshTask expired")
  24. task.setTaskCompleted(success: false)
  25. self.scheduleRefresh()
  26. }
  27. DispatchQueue.main.async {
  28. guard !completed else { return }
  29. completed = true
  30. if let mainVC = self.getMainViewController() {
  31. if !mainVC.backgroundTask.player.isPlaying {
  32. LogManager.shared.log(category: .taskScheduler, message: "audio dead, attempting restart")
  33. mainVC.backgroundTask.stopBackgroundTask()
  34. mainVC.backgroundTask.startBackgroundTask()
  35. LogManager.shared.log(category: .taskScheduler, message: "audio restart initiated")
  36. } else {
  37. LogManager.shared.log(category: .taskScheduler, message: "audio alive, no action needed", isDebug: true)
  38. }
  39. }
  40. self.scheduleRefresh()
  41. task.setTaskCompleted(success: true)
  42. }
  43. }
  44. func scheduleRefresh() {
  45. let request = BGAppRefreshTaskRequest(identifier: taskIdentifier)
  46. request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60)
  47. do {
  48. try BGTaskScheduler.shared.submit(request)
  49. } catch {
  50. LogManager.shared.log(category: .taskScheduler, message: "Failed to schedule BGAppRefreshTask: \(error)")
  51. }
  52. }
  53. private func getMainViewController() -> MainViewController? {
  54. MainViewController.shared
  55. }
  56. }