BGAppRefreshTask Background Task Not Executing

孤街浪徒 提交于 2020-06-09 02:59:27

问题


I am using the new iOS13 background task framework, with the implementation of a BGAppRefreshTask type. My problem is, my device is never calling the task, even after waiting several hours, but I am able to successfully run the code using the Debugger trick of calling _simulateLaunchForTaskWithIdentifier.

I have setup the following:

  • Enabled my app with the Background Modes capability, a checking the "Background fetch".
  • Added my background Id to Info.plist under "Permitted background task scheduler identifiers": "com.XYZ.PearWeather.backgroundAlerts".

I have registered the task from application(didFinishLaunchingWithOptions) in my AppDelegate:

        BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.XYZ.PearWeather.backgroundAlerts", using: nil) { task in
            self.backgroundAlerts(task: task as! BGAppRefreshTask)
        }

I am scheduling the task in a func within the AppDelegate, and calling it from my SceneDelegate sceneDidEnterBackground(). It was originally a static func, but I have now changed it to an instance func, and getting the AppDelegate instance (since I have tried many changes in desperation):

    func sceneDidEnterBackground(_ scene: UIScene) {
        (UIApplication.shared.delegate as! AppDelegate).scheduleBackgroundAlerts()
    }
    func scheduleBackgroundAlerts() {
        let request = BGAppRefreshTaskRequest(identifier: "com.XYZ.PearWeather.backgroundAlerts")

        request.earliestBeginDate = Date(timeIntervalSinceNow: 5 * 60)

        do {
            try BGTaskScheduler.shared.submit(request)
        } catch {
            print("Could not schedule app refresh: \(error)")
        }
    }

At least in the Debugger scenario, there is no error in the submit call. I have tried many different values for the timeIntervalSinceNow parameter above. I am also calling this scheduleBackgroundAlerts() func from the task handler itself, which is as follows:

    func backgroundAlerts(task: BGAppRefreshTask) {

        scheduleBackgroundAlerts()

        task.expirationHandler = {
            // After all operations are cancelled, the completion block below is called to set the task to complete.
            task.setTaskCompleted(success: false)
        }

        AlertsOperation.showNotification()


        task.setTaskCompleted(success: true)
    }

This implementation has changed a lot - I have originally used an OperationQueue, tried placing the scheduleBackgroundAlerts() call at the beginning and end of the func, etc. Now it is stripped down. The AlertOperation.showNotification() is also very simple now:

    static func showNotification() {

        let now = Date()
        let bg = Locale.currentLocale().formattedTime(date: now)
        SettingsManager.shared.settings.bg = bg
    }

This is just storing a value in UserDefaults (in my SettingsManager, details of which are not relevant here) that I am able to read back in my app to see if anything happened.

Now, the original implementation of this func issues a local notification using UNUserNotificationCenter etc, which is what I am trying to do in this background task. This worked fine from the Debugger, but I reduced it to this simple code just to make a very small implementation.

As I say, calling the task handler from the Debugger works fine, using:

e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.XYZ.PearWeather.backgroundAlerts"]

But nothing is happening from the device itself. I cannot see what I have missed. I do not know how to log any exception from within the background task handler either.

I am new to Swift and iOS, so any pointers appreciated. Most of the code above is almost a copy of the many tutorials on this subject. For me, though, things are not working and I have run out of options!


回答1:


Here is what I use.

In my AppDelegate, the iOS13 code. Older style fetch not included:

class AppDelegate: UIResponder, UIApplicationDelegate, URLSessionDelegate, UNUserNotificationCenterDelegate {
var backgroundSessionCompletionHandler: (() -> Void)?
var backgroundSynchTask: UIBackgroundTaskIdentifier = .invalid

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13.0, *) {
    BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.WH.Air-Compare.WayneBGrefresh", using: nil) { task in
        self.handleAppRefresh(task: task as! BGAppRefreshTask)
        self.logSB.verbose("iOS 13  Registered for Background duty")
    }
} else {
    // Fallback on earlier versions
    self.logSB.verbose("iOS < 13  Registering for Background duty")
UIApplication.shared.setMinimumBackgroundFetchInterval(UIApplication.backgroundFetchIntervalMinimum)
}
}

func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler:@escaping () -> Void) {
let dateFormatter = DateFormatter()  // format the date for output
dateFormatter.dateStyle = DateFormatter.Style.medium
dateFormatter.timeStyle = DateFormatter.Style.long
let convertedDate = dateFormatter.string(from: Date())
self.logSB.info("Background URLSession handled at \(convertedDate)")
self.logSB.info("Background URLSession ID \(identifier)")
let config = URLSessionConfiguration.background(withIdentifier: "WayneBGconfig")
let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
session.getTasksWithCompletionHandler { (dataTasks, uploadTasks, downloadTasks) -> Void in
    // yay! you have your tasks!
    self.logSB.info("Background completion handler here with \(downloadTasks.count) tasks")
    for i in 0...max(0,downloadTasks.count - 1) {
        let description: String = downloadTasks[i].taskDescription!
        self.logSB.info("Task ID \(i) is \(description)")
    }
}
backgroundSessionCompletionHandler = completionHandler
}

func applicationDidEnterBackground(_ application: UIApplication) {
if #available(iOS 13.0, *) {
    scheduleAppRefresh()
} else {
    // Fallback on earlier versions
}
}

@available(iOS 13.0, *)
func scheduleAppRefresh() {
logSB.info("Scheduling the AppRefresh in iOS 13 !!")
let request = BGAppRefreshTaskRequest(identifier: "com.WH.Air-Compare.WayneBGrefresh")
request.earliestBeginDate = Date(timeIntervalSinceNow: 2 * 60) // Fetch no earlier than 2 minutes from now

do {
    try BGTaskScheduler.shared.submit(request)
} catch {
    logSB.error("Could not schedule app refresh: \(error)")
}
}


来源:https://stackoverflow.com/questions/61138351/bgapprefreshtask-background-task-not-executing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!