Post

Replies

Boosts

Views

Activity

Reply to WatchOS: background refresh file is downloaded but didFinishDownloadingTo: never called...
Hi Andy, In your WatchOS app extension's Signing and Capabilities section do you have a "Background Modes" section? I do. Additionally I have session type set to "None" and for Modes I have "Remote Notification" checked. I believe that is all you need. What on earth is "BAR"? The issue is that for me, background processing occurs only if the user has started my app and it now is in the application dock. If the app is dead, although it gets started by WatchOS at the desired time, it cannot process the data file until the user brings it to the foreground. I just want to know if that is the intended functionality or if I'm missing something.
Jul ’20
Reply to WatchOS: background refresh file is downloaded but didFinishDownloadingTo: never called...
I believe that BAR stands for Background Application Refresh. Therefore the snippet you posted from WWDC is for scheduling one. I'm also pretty certain that you need to at least add background session type set to "None" to your app's signing and capabilities and that is what the error in the console is complaining about. I have mine set to process remote notifications but it doesn't have to be set to anything, especially if you don't need to use an extended runtime session. Also the session type has a choice for "None" which represents a generic background refresh session that you want to create. Your app doesn't have to have an extended background runtime session, it just needs to declare that it uses a background refresh of a generic type ("None") Why not give it a try? The worst that will happen is nothing
Jul ’20
Reply to WatchOS: background refresh file is downloaded but didFinishDownloadingTo: never called...
Hi Andy, Very happy for you! So your first issue was because you were using SwiftUI, instead of a Storyboard? I'm glad you got it working. If you reboot your watch, does your app get started in the background and allowed to finish processing in the background? Mine updates my complications well but only if I started the app, still has issues when launched by WatchOS. If the watch was on the charger and locked when my app was woken up, I'd get a bunch of permission denied errors. This was due to various configuration files which I used that had the default complete file protection on, so my app couldn't access them if launched while the watch was locked. It still doesn't work in the most extreme case when on the charger, as I now get "Operation not permitted" in the  urlSession(_ session: , task: , didCompleteWithError error: ) method when trying to initiate the download. Finally I noticed a lot of issues because of various data I had stored in the keychain accessible only if the user set a passcode and the device had to be unlocked when the app was launched. If you use the keychain you may want to review your code. I test the app on 2 watches simultaneously, one running WatchOS 7 and the other running WatchOS 6.2.8. I don't know if it's because of WatchOS 7 or because that watch is my regular Apple Watch, as opposed to the other one which is just for testing, but my WatchOS 7 watch schedules tasks in a much more timely fashion.
Jul ’20
Reply to WatchOS: background refresh file is downloaded but didFinishDownloadingTo: never called...
Hi Andy, Regarding using SwiftUI for your app and the complications, maybe you missed something? In the WWDC'20 as you know there are videos demoing how to create complications using SwiftUI. Maybe that's only for >= WatchOS 7.. If your WatchOS app creates and writes to any files, the default is to have complete file protection, meaning those files will NOT be accessible for reading to your app if the screen is locked (regardless of whether it is on the charger or not). So if your app is eventually started by WatchOS in the background, accessing any of those files will fail and throw an exception. The only files you can access when the screen is locked and your app is running in the background are either files you explicitly created with no file protection or the file(s) which WatchOS downloaded for you in the temp area via the background refresh download task. When using background refresh either on WatchOS or iOS there's a tradeoff between usability and security. You most likely don't have to worry about that if the nature of your data doesn't require strong security, and from what you've shared, it looks like your app is fine. My issues seem to stem from wanting to make a highly secure WatchOS app, but complications require security to be more lax than the default. I may have to change my app architecture and utilize complication push notifications instead of background refresh. We'll see.
Aug ’20
Reply to Complication stops updating when Apple Watch is on the charger
Hi Andy, Thanks for the suggestion, unfortunately I already have that. The one thing my app is doing is that when it transitions to the background it explicitly suspends timers and if started by WatchOS in the background my app does not fully initialize itself by design. I thought that was okay, especially since the complication update code is self contained and doesn't really need the app portion to initialize itself until it's in the foreground. I thought I was supposed to do that, but maybe I shouldn't?
Aug ’20
Reply to Complication stops updating when Apple Watch is on the charger
It appears that when the app resumes the URLSession's download task, less than 50 milliseconds later, the request fails: Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted" UserInfo={NSErrorFailingURLStringKey=https:[my request url], NSErrorFailingURLKey=https:[my request url], _NSURLErrorRelatedURLSessionTaskErrorKey=( "BackgroundDownloadTask <UUID1>.<1>", "LocalDownloadTask <UUID2>.<1>" ), _NSURLErrorFailingURLSessiontaskErrorKey=BackgroundDownloadTask <UUID3>.<1>} How do I determine the reason why the operation is not permitted when the app is launched in the background? This seems to be the reason why my complication can't update when started by WatchOS. Anyone care to take a guess?
Aug ’20
Reply to watchOS: Background URL session always takes over an hour to return
Hi Developer555, I have 2 watches, a personal one (Series 5) and a development one (Series 4). On my wrist, the personal watch gets data approximately every 15 minutes. Sometimes it skips for an hour. When the watch is charging I get no updates at all and my app is killed. Perhaps my app uses too much memory and that's why it's killed when the watch is charging? Not sure. I can configure my app to download data for complication refresh every 30 minutes, 45 minutes, an hour or 2 hours. It works well, provided that my app is suspended in the background. If the app is killed for whatever reason, even though WatchOS restarts my app and it schedules a refresh, I don't get URLSession download result until I make the app go into the foreground. Haven't gotten an answer as to whether that is intended functionality or if I need to do something. I should point out that the amount of data I get is always less than 500 bytes. On the development watch, I don't get the updates in as frequent a manner, but it may be because I use it only for development. I've started to wear it as well to see if that improves the refresh frequency. So to summarize: Check the size of the download data Check whether your app is suspended in the background when a refresh is triggered Watch out for any files which can only be written to if the watch is not locked. WatchOS schedules your task based on how much work it does and how often your app is used If your app has more than one complication type I'd add it to as many watch faces as possible, to see if that helps you detect the issue. Question for you, does it work fine on the simulator? I'd try that first with Xcode attached to your app. On the simulator when connected to Xcode, refreshes will be done in a very timely fashion and there's no budget to worry about. All the best,Sal
Aug ’20
Reply to WatchOS: background refresh file is downloaded but didFinishDownloadingTo: never called...
@developer555, The NSURLSession task is scheduled when the system activates my app in the background and calls the handle(_:) method in my ExtensionDelegate. When the task type is WKApplicationRefreshBackgroundTask I take 2 actions: Schedule the next background refresh to occur in 15 minutes Call a method which then creates a background URLSession configuration, and then creates a URLSession for my network request. After creating the session, I resume it just before leaving that method. func handle(_ bkTasks: Set<WKRefreshBackgroundTask>) { for aTask in bkTasks { switch aTask { case let bkTask as WKApplicationRefreshBackgroundTask: scheduleNextAppBackgroundRefresh() createAndResumeURLSession() bkTask.setTaskCompletedWithSnapshot(false) case let urlSessionTask as WKURLSessionRefreshBackgroundTask: /* This adds the urlSessionTask to a list, which will be used to mark &#9;&#9;all tasks as completed upon successful download of data &#9;&#9; */ handleDownload(urlSessionTask) default: // Ensure that unhandled tasks are marked as complete aTask.setTaskCompletedWithSnapshot(false) } } At some point in the future I may get back data from the NSURLSession. Note that the neither the background refresh nor the URLSession task scheduling is contingent upon getting data successfully. This is because there may be network issues such as timeouts which occur. Please note that this is all boilerplate code, and you should be able to find some examples on the net Hope this helps. Let me know Note: This has me thinking as to whether I need to take any actions such as mark tasks completed if an error occurs during the download. I suspect I need to.
Sep ’20
Reply to watchOS: Background URL session always takes over an hour to return
@developer555, I do not schedule a URLSessionTask at all. I only schedule a background refresh. I create the URLSession background task uses the default settings. I do not use earliestBeginDate nor do I have the willBeginDelayedRequest delegate method implemented. Perhaps you're doing more than you need? Do a search on always show fresh content on WatchOS. There's a pretty good tutorial that comes up, that illustrates the bare minimum you need to get it going. You may want to compare your work with the tutorial. You're probably missing a very small amount of code. Let me know how it turns out
Sep ’20
Reply to watchOS: Background URL session always takes over an hour to return
@developer555, Yes, please check out that blog and let me know. On the topic of complication updates, would you know if you're penalized for updating a complication while your app is in the foreground? Or is it only when updating in the background? My app's data model gets updated every 2 seconds when in the foreground and I update the complication then as well. I know that if you're updating a complication via the transferUserInfo for complications there's a budget, but what about when you're just updating it from the WatchOS app?
Sep ’20
Reply to watchOS: Background URL session always takes over an hour to return
@developer555, I also just added earliestBeginDate and the willBeginDelayedRequest delegate method, calling the completionHandler with .continueLoading. Here's what I observed: The scheduled background refresh always schedules the background refresh task exactly when specified (every 15 minutes) When it fires, a NSURLSession is created with a background configuration type I set earliestBeginDate to now + a few seconds, since I already have an interval of 15 minutes for when I schedule the background refresh. On a simulator, if the debugger is attached everything works fine. As soon as I detach the debugger, the background refresh task is still scheduled appropriately, but the URL session is no longer started! On a real device, I sometimes get a NSURLSession executed in the background at a 15 minute interval, but most of the time only the application refresh task is triggered. The spacing between each NSURLSession creation is 15 minutes and30 seconds. Is it possible that this is just the way that it works? When updating a complication in the background from a WatchOS app, perhaps I'm exceeding the 96 complication updates that I'm trying to do in a 24 hour period? I've added code that keeps track of every complication update, both when done in the background and foreground. Not sure when the 24 hour period starts, so hopefully this'll shed some light on my issue. But then again, this is an issue with NSURLSession and not the complication update. I'm starting to think that the NSURLSession being kicked off is a function of how many apps are on the watch, and how many are scheduling background refreshes.
Sep ’20