When my app is initially downloaded, the user needs to download a large file something like 200MB (upper limit). I definitely can\'t expect the user to keep the app open til
It is possible to start a background task when you begin the download:
Apps that are transitioning to the background can request an extra amount of time to finish any important last-minute tasks.
Executing a Finite-Length Task in the Background
However, such a task is limited to an undefined amount of execution time by the system. However, a 200Mb file download may be too large a task in this case.
Add below in your - (void)applicationDidEnterBackground:(UIApplication *)application
UIApplication *app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgTask;
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
}];
and you are good to go... I have this in one of my published download manager app
This will work just fine. You can also check how much time you have, since apple only enable 10 minutes background tasks. Use:
NSTimeInterval ti = [[UIApplication sharedApplication]backgroundTimeRemaining];
NSLog(@"backgroundTimeRemaining: %f", ti); // just for debug
You could use NSURLSession introduced in iOS 7.0 and later to continue the uploading/download of an file even when the app is suspended.
Apple documentation
The NSURLSession class and related classes provide an API for downloading content. This API provides a rich set of delegate methods for supporting authentication and gives your app the ability to perform background downloads when your app is not running or, in iOS, while your app is suspended.
And
Background sessions let you perform uploads and downloads of content in the background while your app is not running. You can create a background session configuration by calling the backgroundSessionConfiguration: method on the NSURLSessionConfiguration class.
A cool tutorial to use NSURLSession at this link.
In one of my apps, I was loading huge amount of data. I definitely can't expect the user to keep the app in foreground until the data is downloaded. I just use following code to get the data downloading while app is in background. Its working properly :-)
Please go through following steps:
1) use following line in header file of ViewController
@property (nonatomic) UIBackgroundTaskIdentifier backgroundTask;
synthesis it in .m file.
2) in ViewDidLoad assign UIBackgroundTaskIdentifier like:
self.backgroundTask = UIBackgroundTaskInvalid;
3) Use following line of code, here I am just keeping on getDataFromServer method inside beginBackgroundTaskWithExpirationHandler: block.
self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
self.backgroundTask = UIBackgroundTaskInvalid;
}];
/* Here your downloading Code, let say getDataFromServer method */
[self getDataFromServer]; // Its dummy method
/* Your downloading Code End Here */
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
self.backgroundTask = UIBackgroundTaskInvalid;
});
4) If you want to check time remaining to download data in background, include following line in applicationDidEnterBackground:(UIApplication *)application delegate method of AppDelegate:
NSLog(@"Background time remaining = %.1f seconds", [UIApplication sharedApplication].backgroundTimeRemaining);
AFNetworking allows you to perform heavy operation in background.
AFNetworking Library is a excellent combination of NSURLConnection and NSOperationQueue.This library is used for Asynchronous downloading in the background not affecting the other application.
AFNetworking allows you to handle the downloading with ExpirationHandle i.e. if anyhow during the downloading the connection is lost , it will again connect to it.
Library Source for AFNetworking
Reference Source AFNetworking works in Background
Apple Reference Link Apple
Background Execution and Multitasking Apple
#pragma mark - View Loading handling
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
}
#pragma mark - Background handling when application goes background
UIBackgroundTaskIdentifier background_task;
- (void)appDidEnterBackground:(NSNotification *)notification {
UIApplication *application = [UIApplication sharedApplication];
if([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)])
{
NSLog(@"Multitasking Supported");
if (background_task == UIBackgroundTaskInvalid) {
background_task = [application beginBackgroundTaskWithExpirationHandler:^ {
NSLog(@"Background task expiration\n");
//Clean up code. Tell the system that we are done.
[application endBackgroundTask: background_task];
background_task = UIBackgroundTaskInvalid;
}];
//To make the code block asynchronous
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//### background task starts
NSLog(@"Running in the background\n");
for(int cnt=0; cnt<10; cnt++) //while(TRUE)
{
NSLog(@"Background time Remaining: %f",[[UIApplication sharedApplication] backgroundTimeRemaining]);
[NSThread sleepForTimeInterval:1]; //wait for 1 sec
}
//#### background task ends
//Clean up code. Tell the system that we are done.
NSLog(@"here you can do something before it really enters background");
[NSThread sleepForTimeInterval:1]; //wait for 1 sec
[application endBackgroundTask: background_task];
background_task = UIBackgroundTaskInvalid;
});
}
else
{
NSLog(@"Multitasking Not Supported");
}
}
}
You can know more from this slide.
I just do some simple useful modification from the snippet of this slide.
Hope this helps.