I have a situation where I need to download multiple files sequentially as each download depends on its previous downloaded file. (I am processing the file in background itself)
I am using NSURLSessionConfiguration backgroundSessionConfiguration.
There is a scenario where NSURLSessionDownloadTask initiates while the application is in background. This crashes the app with Assertion permittedbackgroundduration.
So, my question is, am I doing wrong by initiating the download task in background???
Thanks in advance,
- Satya
You have limited time when on background, so chances are that you're taking too long to process the file.
If you don't call the completion handler fast enough, the system will crash your app.
Or you may have made a mistake and you are not calling the completion handler at all on the scenario where NSURLSessionDownloadTask initiates in background.
Related
I have been using NSURLSession to do background uploading to AWS S3. Something like this:
NSURLSessionConfiguration* configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:#“some.identifier"];
NSURLSession* session = [NSURLSession sessionWithConfiguration:configuration delegate:someDelegate delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionUploadTask* task = [session uploadTaskWithRequest:request fromFile:[NSURL fileURLWithPath:httpBody]];
[task resume];
In someDelegate, I have implemented didSendBodyData, didCompleteWithError and handleEventsForBackgroundURLSession.
I have three questions:
I have noticed that if I close the app while uploading is in progress, transfer will continue and successfully finish. Is handleEventsForBackgroundURLSession called when the transfer is finished while the app is closed?
Assuming that the answer to the first question is yes, how can I delete httpBody in handleEventsForBackgroundURLSession? This is a temporary file that is not needed once transfer is complete.
I would appreciate it if someone explained, in detail, how background transfer works in iOS. That is when memory is created, which callbacks are called at which states and how the app is woken up once the transfer is completed. Thanks.
When the app delegate's handleEventsForBackgroundURLSession is called, you should:
save the completion handler;
instantiate your background NSURLSession;
let all of your delegate methods to be called;
in your URLSession:task:didCompleteWithError:, you can remove those temp files; and
in URLSessionDidFinishEventsForBackgroundURLSession:, you can call that saved completion handler.
A few additional notes:
There seems to be some confusion about what happens when an app is terminated.
If the app is terminated in the course of its normal lifecycle, the URLSession daemon will keep the background requests going, finishing your uploads, and then wake up your app when it's done.
But manually force-quitting the app (e.g., double tapping on home button, swiping up on the app to force it to quit) is a completely different thing (effectively, the user is saying "stop this app and everything associated with it"). That will stop background sessions. So, yes, background sessions will continue after the app is terminated, but, no, not if the user force-quit the app.
You talk about setting breakpoints and observing this in Xcode. You should be aware that the process of being attached to Xcode will interfere with the normal app life cycle (it keeps it running in background, preventing it from being suspended or, during the normal course of events, terminating).
But when testing background session related code, it's critical to be test the handleEventsForBackgroundURLSession workflow when your app was terminated, so to that end, I'd suggest not using Xcode debugger when testing this dimension of background sessions.
I use the new OSLog unified logging system, because the macOS Console can watch what is logged by the app, while not having Xcode running at all. Then I can write code that starts some download or upload, terminates app and then watch the logging statements I have inserted in order to observe the restarting of the app in background via the macOS console. See Unified Logging and Activity Tracing video for a tutorial of how to watch iOS logs from the macOS Console.
I want to know about the behaviour of NSURLSessionDataTask in background.
Does NSURLSessionDataTask get paused right away (as soon as the app enters background)? or does iOS give some time hopefully 30 seconds or so until the response ?
No, You will not continue with NSURLSessionDataTask in background mode with defaultSessionConfiguration !
If you want to continue execution in background then you need to configure session with backgroundSessionConfiguration.
When you are using backgroundSessionConfiguration you can't send data directly to server, you have to give file url and from that url you have to send bytes or chunks to server, and you have to use uploadTask or downloadTask with backgroundSessionConfiguration!!
If you wants little time after entering in background then you can use UIBackgroundTaskIdentifier. These are very huge concepts to explain every thing here, It's better that you read documentations from apple or some tutorial for that!!! You should refer Apple Documentation for Background Execution and Apple documentation for NSURLSession !
I want to upload a file to a server using NSURLSession.
Cases Are:
1. It should resume uploading a file to the server from where it stopped because of app crash.
2. It should handle background upload as well.
Try AFNetworking Library to upload image asynchronously.You can find a brief example in this thread.
You should use background NSURLSession. If your app crashed or user left the app while upload was in progress, with a background NSURLSession the upload would continue seamlessly in the background. When the upload is done, your app will be notified of this via the delegate (and if your app wasn't alive at the time the download finished, it will be started in a background mode, at which point you can do whatever cleanup you need).
So create NSURLSessionConfiguration with backgroundSessionConfigurationWithIdentifier, and then instantiate a NSURLSession with that configuration.
There are a few caveats:
You cannot use completion handler pattern. You have to use delegate-based implementation.
You have to implement handleEventsForBackgroundURLSession in the app delegate, capturing the completionHandler it passes you and also instantiate the background session again. Likewise, in your NSURLSession delegate methods, you have to implement URLSessionDidFinishEventsForBackgroundURLSession, which will call the saved completion handler.
For more information, see Background Task Considerations in URL Session Programming Guide, see a section of the same name (but different text) in the NSURLSession class reference, or see the WWDC 2013 What's New in Foundation Networking, where Apple first introduced us to background sessions.
I have a question about AFNetworking 2 and background downloads/uploads thanks to the new iOS7 NSURLSession background requests
Is this automatically handled by my AFHTTPRequestOperationManager ? Does it automatically set my requests'session to background mode?
I saw that the AFURLSessionManager Has a setDidFinishEventsForBackgroundURLSessionBlock Method but I wonder if everything is automatic?
If my app is killed or suspended, will requests keep on going? How can I get a callback when my app is relaunched?
Thanks a lot for your help!
AFHTTPRequestOperationManager uses the old NSURLConnection so that doesn't facilitate background downloading.
AFURLSessionManager uses NSURLSession under the hood so that does. I think you still need to configure the NSURLSession appropriately.
"The NSURLSession class supports background transfers while your app is suspended. Background transfers are provided only by sessions created using a background session configuration object (as returned by a call to backgroundSessionConfiguration:)."
Suggested reading:URL Loading System
If the application uses NSURLConnection to start a download while the app is in the foreground, but then the app moves to the background before the data has finished downloaded, then how should the app make use of beginbackgroundtaskwithexpirationhandler: for this already existing connection?
There's plenty of reference material available showing how to use NSURLConnection initWithRequest: to START a download AFTER the app has moved into the background, there is nothing showing how to deal with the situation where NSURLConnection initWithRequest: has already been called while the app is in the foreground but hasn't yet finished when the app moves into the background and how to continue.
TIA
You need to start it as a background task for task that you wish to continue in background even if that task is in foreground beginning with. Check out the section "beyond the basics" in this Apple doc: https://developer.apple.com/library/ios/ipad/#technotes/tn2277/_index.html