URLSessionDownloadTask in background never triggers handle(_ backgroundTasks: Set) for WKURLSession​Refresh​Background​Task

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



URLSessionDownloadTask in background never triggers handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) for WKURLSession​Refresh​Background​Task



Trying to understand why, when scheduling a background URLSessionDownloadTask in WatchKit 3.0. the func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) never fires for WKURLSession​Refresh​Background​Task, but other tasks come through like WKApplicationRefreshBackgroundTask and WKSnapshotRefreshBackgroundTask.


handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>)


WKURLSession​Refresh​Background​Task


WKApplicationRefreshBackgroundTask


WKSnapshotRefreshBackgroundTask



My code in the Watch ExtensionDelegate...


ExtensionDelegate


func applicationDidBecomeActive()
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.

scheduleBackgroundRefresh(in: 10)


func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>)
// Sent when the system needs to launch the application in the background to process tasks. Tasks arrive in a set, so loop through and process each one.
for task in backgroundTasks
// Use a switch statement to check the task type
switch task
case let backgroundTask as WKApplicationRefreshBackgroundTask:
// Be sure to complete the background task once you’re done.
scheduleURLSession()
backgroundTask.setTaskCompleted()
case let snapshotTask as WKSnapshotRefreshBackgroundTask:
// Snapshot tasks have a unique completion call, make sure to set your expiration date
snapshotTask.setTaskCompleted(restoredDefaultState: true, estimatedSnapshotExpiration: Date.distantFuture, userInfo: nil)
case let connectivityTask as WKWatchConnectivityRefreshBackgroundTask:
// Be sure to complete the connectivity task once you’re done.
connectivityTask.setTaskCompleted()
case let urlSessionTask as WKURLSessionRefreshBackgroundTask: // This is never fired, Don't know why, arrrgggggg
// Be sure to complete the URL session task once you’re done.

let backgroundConfigObject = URLSessionConfiguration.background(withIdentifier: urlSessionTask.sessionIdentifier)
let backgroundSession = URLSession(configuration: backgroundConfigObject, delegate: self, delegateQueue: nil) // delegate set to self here after rejoining the session

print("Rejoining session ", backgroundSession)

urlSessionTask.setTaskCompleted() // probably need to postpone this until the url `urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)` has completed, but either way, this switch case is never met
default:
// make sure to complete unhandled task types
task.setTaskCompleted()




func scheduleURLSession()
if let url = URL(string: "https://some.path.com")
let backgroundConfigObject = URLSessionConfiguration.background(withIdentifier: NSUUID().uuidString)
let backgroundSession = URLSession(configuration: backgroundConfigObject, delegate: nil, delegateQueue: nil) // nil delegate here because delegate is "supposed" to be set in `handle(_ backgroundTasks:)` delegate method ("Rejoining session").

let task = backgroundSession.downloadTask(with: url)
task.resume()
else
print("Url error")



func scheduleBackgroundRefresh(in seconds: TimeInterval)
let fireDate = Date(timeIntervalSinceNow: seconds)
// optional, any SecureCoding compliant data can be passed here
let userInfo = ["reason" : "background update"] as NSDictionary

WKExtension.shared().scheduleBackgroundRefresh(withPreferredDate: fireDate, userInfo: userInfo) (error) in
if (error == nil)
print("successfully scheduled background task, use the crown to send the app to the background and wait for handle:BackgroundTasks to fire.")





Here's Apple's sample code for reference



Any ideas why URLSessionDownloadTask in background never triggers handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) to fire?


URLSessionDownloadTask


handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>)





Could it be because your delegateQueue is always nil? Wahat about setting it to OperationQueue.main?
– francisaugusto
Mar 30 '17 at 12:18



nil


OperationQueue.main




1 Answer
1



You have set preferredFireDate to 10 seconds. As apple said there is no guaranty to fire handle method so quickly.



preferredFireDate



The time of the next background snapshot refresh task. The system
makes every effort to wake your app in the background at some point
after the scheduled time, but the precise time is not guaranteed.



When I set this parameter to 30 seconds I had to wait about 10 minutes till system called handle method.



Also you have to set delegate for WKExtension.



WKExtension.shared().delegate = self //self is an object where handle metod is implemented


WKExtension.shared().delegate = self //self is an object where handle metod is implemented



Edit



Background app refresh tasks are budgeted. In general, the system performs approximately one task per hour for each app in the dock (including the most recently used app). This budget is shared among all apps on the dock. The system performs multiple tasks an hour for each app with a complication on the active watch face. This budget is shared among all complications on the watch face. After you exhaust the budget, the system delays your requests until more time becomes available.






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard