Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BGAppRefreshTask Background Task Not Executing

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!

like image 270
Dean McCrae Avatar asked Apr 10 '20 10:04

Dean McCrae


1 Answers

have break points in the code after submit request and after submitting the request(BGTaskScheduler.shared.submit(request)) then run the command

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

then registered handler will be called for that identifier. Check POC to see further details.

like image 181
SreekanthI Avatar answered Oct 21 '22 12:10

SreekanthI