8

When I force my device to go in sleep mode by pressing the power button, my background task stops by calling the delegate method didCompleteWithError with the error :

The operation couldn’t be completed. Operation not permitted

How can I configure my NSURLSession to continue the download even in sleep mode?

Is it even possible? If not, what options do I have? I need to download a file of 300Mb, so with a low connection the application will go in sleep mode before the end of the download.

Here is the creation of my session :

static NSURLSession *backgroundSession;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
   backgroundSession = [NSURLSession sessionWithConfiguration:
                       [NSURLSessionConfiguration backgroundSessionConfiguration:
                       @"com.myapp.mytask"] delegate:self.
                       myDelegate delegateQueue:self.myQueue];
});

NSURLSessionDownloadTask *task = [backgroundSession downloadTaskWithRequest:
                                  self.urlRequest];
[task resume];
ragu89
  • 335
  • 7
  • 22
  • 1
    The download doesn't stop directly when I lock the device. the error arrives after 5-10 seconds. – ragu89 Sep 11 '14 at 13:42
  • 2
    I have managed to fix this issue in our projects by using the technique here http://stackoverflow.com/a/32821437/1905256. – James Newbould Oct 07 '15 at 15:28

1 Answers1

7

The problem is that the Data Protection Capability is activated. With that enabled all files are stored with NSFileProtectionComplete by default, even the temporary file used to download by the NSURLSession:

The default level of protection is complete protection, in which files are encrypted and inaccessible when the device is locked. You can programmatically set the level of protection for files created by your app, as described in “Protecting Data Using On-Disk Encryption” in iOS App Programming Guide.

With NSFileProtectionComplete activated on that file you cannot access it when the device is locked.

I'm not sure if the temporary download file can be configured to not use data protection, it seems like that is not exposed by NSURLSession.

Source: App Distribution Guide

Ben-G
  • 4,996
  • 27
  • 33
  • NSURLSession background downloads work by handing the download off to nsnetworkd, a background daemon that continues download work on your behalf. If you're using them correctly, you don't need your app to run in the background. They'll continue even if your app is suspended. – Matt Gibson Sep 11 '14 at 17:28
  • Thanks for the info. I haven't used NSURLSession extensively yet. Any other clue what could be going wrong? – Ben-G Sep 11 '14 at 17:43
  • I made new test, and it appears I have this problem only when I deploy my app in-house, through my MDM. If I run the application directly from xCode on my device:it works. But when I install the application from my MDM and run it, every time the app go in background for more than 10 seconds : It stops. – ragu89 Sep 12 '14 at 12:55
  • At this point I'm really just guessing. Maybe your MDM policy requires all/most files to be encrypted upon screen locking (using NSFileProtection) and therefore the download daemon can no longer write to the encrypted file when the screen is locked? Once again, just guessing. – Ben-G Sep 12 '14 at 15:21
  • Is it possible the problem comes because Data Protection is activated? I just made an example with a new provisioning profile without data protection, and it seems to work this time. – ragu89 Sep 16 '14 at 07:56
  • Definitely, that seems cause the problem. See updated answer. – Ben-G Sep 16 '14 at 21:18
  • Been trying to solve this for days, thanks so much for the answer! – Kyle L Nov 03 '14 at 22:50
  • My app stops downloading after 10 seconds of device lock. This problem occurs only on some devices even if I use same code/build/prov profile to debug. Any clue? I do NSLog over `UIApplication.sharedApplication.backgroundTimeRemaining` in didWriteData:totalBytesWritten of NSURLSessionDownloadTask delegate handler. – Ashok Dec 15 '14 at 22:31