NSUrlSession suspend and resume issue on device lock - ios

I am uploading file to server by using multipart form data with NSURLSession. When the application goes in background I want to suspend the request and resume when application comes in foreground again. So I simply do [session suspend] and [session resume]. This is working fine when the app goes in background only. But if the device gets locked, when going back in foreground and try to resume, I get a network connection lost error. I understand that when device is locked, all open sockets are closed and therefore the issue, but is there some way to make this work without the need of starting the upload from beginning?

You should switch your foreground session to a background session before the app goes to background, and then there is no need to suspend it. Your file will be uploaded by OS while in background (eventually).

Unfortunately, according to the documentation, you need to use a file to perform your background upload.
From "Background Transfer Considerations":
Only upload tasks from a file are supported (uploading from data objects or a stream will fail after the program exits).
(In addition to that, there is no guarantee when or why your app will be terminated. Trying to avoid device locking alone won't be sufficient; there are a myriad other ways your app may be terminated.)

Related

Handling large number of API requests in iOS App (Not using Alamofire)

How to handle the states in which the app goes into foreground setting off a number of requests (around 3-4 minimum) because that information is required in the app, and then going to background?
What I have tried is to use a RequestManager to suspend the URLSessionDataTasks when app goes into background and when app resumes, resume those tasks again. But I don't see this working very well.
Is there a standard way to go about this?
Suspending tasks won't work, because the session no longer exists if your app gets jettisoned for low memory.
The most straightforward approach would be to use a download task in a background session, then read the resulting temporary file when it finishes downloading. Download and upload tasks in background sessions are the only types of tasks that can survive your app getting jettisoned while in the background because of memory pressure.
If you absolutely must avoid downloading while the app is in the background (why?), you could create a download task in either a foreground or background session, then stop the download tasks by calling cancelByProducingResumeData: when your app gets backgrounded. You can later continue the request by calling downloadTaskWithResumeData:.
There is a rather large caveat with that approach, though, which is that the resume data portions of the API are not nearly as well tested as the background downloading portions. Case in point: in every version of iOS 10 from the first beta until 10.2, support for resume data was completely broken. (There is a rather horrific workaround, in case you choose to go down that path.)
So I would recommend the first approach unless you have some contractual or legal obligation not to do so.

How to run an swift app in background when close app?

I want some information stored in the database server if disconnected the Internet stored database sqlite when Internet connection to send data to the server (even when the app is closed) What is your suggestion for the job
This cannot be done, your application will work for just a short time in background after you terminate the application.
Read more about the Background Execution on Apples Developer site.
iOS app can't run on background. You can handle changes of connection (wifi , 4g, none) when app is on foreground. Or you can add background task which gives you additional time to save data into database etc.
Method is called beginBackgroundTaskWithName:expirationHandler: in applicationDidEnterBackground. More documentations is here Executing Finite-Length Tasks : https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html

Timeout when using NSUrlSession with call started in foreground but app moved to background

If a basic call to post some data to a server using NSURLSession (in this case using Alamofire) a call is started with the app in foreground, while the call is in progress the app is move to the background and is suspended. When the app comes back to the foreground, what happens to the call that was in progress? Does it timeout (App is using default 60 seconds ephemeralSessionConfiguration) or will it receive some other error? If the timeout has not yet been reached is the call still waiting or has the OS terminated it? I have the default background mode and have no requested no background time. Trying to debug an issue that happened in the field.
Your network requests are suspended when your app is suspended. So basically the answer is that it depends on whether the server gives up on you while your app is in the background, and on whether the socket in the kernel gives up on your app while it is suspended.
As a rule, if you need to move data while your app is in the background, you should be using a background session and a download or upload task. That way, the actual data transfer happens in a separate process (that doesn't get suspended) and your app will get the data.
With that said, using a background session is fundamentally in conflict with using an ephemeral configuration, because it involves storing data on disk. So if you really need an ephemeral configuration for some reason, your app's requests are likely to just fail a few seconds after the user hits the home button, and there's not much you can do about it as long as you're making requests ephemerally.

How can an iOS app reconnect to a background download if the user relaunches the app while the download is occurring?

iOS 7 introduced the ability to run downloads in the background if an app is terminated. Apple documentation and available examples provide information about how to respond to events triggered by these background downloads so that the download can complete in the background, ready for the user to get access to the downloaded resource when they restart the app.
However, the documentation and examples do not appear to provide information about how to handle the case where an app begins a background transfer, is terminated, but then is restarted by the user before the background transfer has ended. If an app needs to provide the user with information that a background transfer is ongoing but not finished, how can that state be detected and how can the app get progress updates on the background transfer to keep the user informed about how the background download is going?
Thanks in advance for any suggestions.
If you create a new background session with an identical identifier, iOS is smart enough to recreate the relevant connections for you. It 'knows' the 'new' background session is, in fact, a resumption of the old one, and will give you the old one back.
From there, you remain responsible for configuring delegates and other aspects of your personal code (re-)using the session.
As I'm aware background session has an identifier so I think you can resume it by that identifier.

NSURLSession background download - resume over network failure

After reading the Apple documentation about the background download with the new iOS7 api (NSURLSession), I'm a bit disappointed. I was sure that Apple was managing the pause/resume over the network availability in the background (or provide an option to do so) but no…
So reading the documentation, this is what we've got:
https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/URLLoadingSystem/NSURLSessionConcepts/NSURLSessionConcepts.html
When any task completes, the NSURLSession object calls the
delegate’s URLSession:task:didCompleteWithError: method with either an
error object, or nil if the task completed successfully.
If the task is a resumable download task, the NSError object’s userInfo dictionary
contains a value for the NSURLSessionDownloadTaskResumeData key. Your
app should use reachability APIs to determine when to retry, and
should then call downloadTaskWithResumeData: or
downloadTaskWithResumeData:completionHandler: to create a new download
task to continue that download. Go to step 3 (creating and resuming
task objects).
So far I understand the solution, but my question is: What architecture is the best to handle the loss of the network and resume downloading in the background?
On my side I'm using reachability and each time the network is available, I resume all tasks (referenced over a NSArray when creating), and suspends them when network is lost. This works well in foreground but for the background I need help on the following points:
If my app has no connectivity in foreground, if I go to the background without connectivity all my tasks remains suspended and won't came back if network is available…
Losing network in background, stop all my downloads/tasks.
Scenario:
In foreground, I start downloading my tasks
I go to background and after 10s switch to "aireplan mode"
All my tasks got an error. So in the method URLSession:task:didCompleteWithError: I resume them using
downloadTaskWithResumeData or if I can't (because some have not
enough resume data) I'm creating a new task without resume-ing it (except if network is back at that time).
Then I put the wifi up
As I'm still in background I cannot trigger a "resume" when network is back without launching the application…
How do I address these points? Have I missed something?
As I'm still in background I cannot trigger a "resume" when network is back without launching the application…
you can use "background fetch",when the app is launched by fetch,then you can check network and resume the download task.
You should create the NSURLSession with background configurations, then your task is sent to a background demon and your app get called when it is completed.
Implementing:
application:handleEventsForBackgroundURLSession:completionHandler:
in the app delegate - without calling the completionHandler - causes the app to hang around in the background after the device loses its connection whilst suspended. That way, the app can still listen to reachability notifications and restart the download when a network connection becomes available once again. However, this is a pretty dodgy approach and may not pass Apple's app store submission guidelines. Additionally, this approach isn't much help when the connection is lost while the app is in the foreground and the connection regained whilst the app is suspended.
In the end I did the following:
Made use of the application:handleEventsForBackgroundURLSession:completionHandler: notification to pause my downloads in the background.
Made use of the intermittent background fetch notification (ie. application:performFetchWithCompletionHandler:completionHandler) to check connection status and restart any paused downloads. (hat-tip #gugupluto)
This still doesn't provide optimal download performance and may lead users to wonder why their "background download" hasn't finished once they reopen the app, but it seems to be the best we can hope for from Apple for now.

Resources