I am trying to upload file, images, videos when app is in background state to own cloud server in iOS Swift. Own cloud library has the capability to start upload through OS so that upload happens even when app is killed, but it doesn't even work for me in background state properly. I am not sure how to make upload happen when app is in background.
// Its used to upload the file to ownCloud
func uploadFileMedia(uploadPath: String, localPath: String){
Async.background(){
AppDelegate.sharedOCCommunication()?.uploadFileSession(localPath, toDestiny: uploadPath, on: AppDelegate.sharedOCCommunication(), progress: { (progress) in
SpeedLog.print(progress as Any)
}, successRequest: { (response, desc) in
// Success
self.getShareURL(url: uploadPath.replacingOccurrences(of: AppDependency.sharedInstance.ownCloudBaseUrl + AppDependency.sharedInstance.ownCloudRemaingToCreateFile, with: ""))
}, failureRequest: { (reponsnse, desc, error) in
// failure
self.isUploadStarted = false
self.totalNumberOfProcedure = 0
self.markThefileNeedToBeHandledAgain(id: self.fileName)
_ = self.saveJobCardRawString(fileName: self.fileName, rawString: self.aJobCardObj!.toJSON().rawString()!)
}, failureBeforeRequest: { (error) in
// error in file
self.isUploadStarted = false
self.totalNumberOfProcedure = 0
self.markThefileNeedToBeHandledAgain(id: self.fileName)
_ = self.saveJobCardRawString(fileName: self.fileName, rawString: self.aJobCardObj!.toJSON().rawString()!)
})
AppDelegate.sharedOCCommunication()?.setTaskDidComplete({ session, task, error in
print(session)
print(task)
print(error)
})
}
}
You asked:
Own cloud library has the capability to start upload through OS so that upload happens even when app is killed, but it doesn't even work for me in background state properly.
First, a minor clarification: Background uploads do not proceed if the app is “killed”. Background uploads only proceed if the app is gracefully suspended (i.e., the user leaves the app to go do something else). The background uploads even proceed if the app gracefully terminates during the course of its normal lifecycle (e.g., the user is using some other app that requires so much memory that iOS starts jettisoning various suspended apps, including yours).
But if a user manually kills an app (i.e., performs a “force quit” by launching the task manager and swiping up on your app to manually kill it), iOS will interpret that as “the user would like to stop everything associated with the app”. Bottom line, if a user force-quits an app, background uploads and downloads will stop. There is nothing you can do about this. It is how the OS works.
You said:
I am trying to upload file, images, videos when app is in background state to own cloud server in iOS Swift.
Obviously, we cannot comment on this without seeing its implementation. But glancing at the OwnCloud source code, they do appear to be using background URLSessionConfiguration
.
I would refer you to Downloading Files in the Background, which outlines the main aspects of the process of using a background URLSession
:
URLSession
with a “background” URLSessionConfiguration
.URLSessionTask
.application(_:handleEventsForBackgroundURLSession:completionHandler:)
in the app delegate to capture the completion handler.urlSessionDidFinishEvents(forbackgroundurlsession:)
, call the saved completion handler (when you are done handling all the events).The only upload-related requirement for background session that is not outlined in that document is that uploads must use file-based upload (which, given your uploadFileSession
method name, I assume you are doing).
There are two aspects of this code snippet that are worrying:
The reference to Async.background
.
This suggests a conflation of two very different uses of the word “background”. In the context of a background URLSessionConfiguration
, “background” refers to the app state (e.g., foreground, background, suspended, etc.). This has nothing to do with “background” in the context of a background thread or background queue.
You can start a background URLSession
from the main thread. Do not conflate a background session with a background thread/queue.
The use of completion handler closures.
This code snippet is supplying several closures when starting the upload. That does not make much sense.
When using a background URLSession
, we do not use completion handler closures. First, you cannot even start a background URLSessionTask
using a completion handler method (or the newer async
-await
renditions). Second, it does not make sense to use completion handlers with background sessions.
As we discussed above, when starting a URLSessionTask
in the out-of-process background URLSession
, your app may be suspended and later jettisoned while the upload is in progress. You may elect to have your app relaunched when the requests are done, but your app may be starting from scratch. Any closures provided when the request was initiated are now long gone.
Now, if these are closures that are called when the request is submitted to the background URLSession
, then that is fine. Or, in the case of “progress”, if this closure is merely for debugging uploads that happen to proceed while the app happens to still be running in the foreground, then that is fine, too. But that is only of utility for debugging purposes.
But just remember that if the app had happened to terminate while the uploads were in progress, and was restarted again later when the uploads were done, then all these closures will be gone. It will only call the various URLSessionDelegate
methods (assuming you properly restart the background URLSession
with the same name). But do not rely on any of these closures to be called if the app had been gracefully terminated (not “force-quit”) in the intervening period of time.