i know that this questions may be repeated some times but i need some clarifications so i asked here.
My requirement is I got location using my iPhone every 20 sec and update my Web Application using the web services.It's also working on Background.
I know that i will got the location in background using the Background Fetch but i little confuse here.I want to update My web database every 20 sec using web services. is it possible to update Web database every 20 second using web service in Application Background mode?
Thanks in advance.
Try to use NSURLSession using its task you can do background upload and download.
After 1st request complete start timer which start the second request.
Good tutorial for NSURLSession is here..
tutsplus (its 4 part tutorial)
Here
And check the NSURLSession document here..
Its supported in iOS7+. But if user force close the application it will be stopped.
No. Minimal interval when your app "wakes up" in background mode is 6-10 minutes.
If your phone is active and unlocked. If your phone is "sleeping", this interval may be some hours.
In your project ->capabilities->background modes turn on "background fetch"
In your appDelegate
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
//Add your code here You will have 30 sec. to do all that you want in background mode
completionHandler(UIBackgroundFetchResultNewData); }
Related
I'm making an app that receives constant updates (potentially hundreds of times a day) and, to make for a better user experience, it would be nice to have these downloaded in the background.
Looking at Apple's[1] documentation I need to set the background mode to "Background fetch". Exploring deeper you can read about the application:performFetchWithCompletionHandler[2] function which states that:
When this method is called, your app has up to 30 seconds of wall-clock time to perform the download operation and call the specified completion handler block... If your app takes a long time to call the completion handler, it may be given fewer future opportunities to fetch data in the future.
The problem is our downloads will take longer than 30 seconds to download, and as such would rather not face the wrath of Apple sending updates fewer and farther between, thus exacerbating the issue!
So, am I able to do this somehow?
Also, I have created a crude experiment whereby I create a NSTimer:scheduledTimerWithTimeInterval to run every minute which logs to the console. This successfully works both on the iPhone in simulation (has been running for 30 mins plus) and also when I place it on a phone (a week plus)... why would this be!?
It may be hard to do because of the Apple 30s obligation. They decided so to eventually prevent big download to happen not to drain battery and data plan.
You must be sure you really need to download that much data (as it takes this long) in background, plus hundred times a day!
I mean, when your app goes foreground after a (long) background period, it may not be updated and it's normal case. So you need to do the update when the app goes foreground; only one update is needed. Otherwise, you should step back and rethink the update process.
Found a solution:
You can bypass Apple's application:performFetchWithCompletionHandler function and set your own timer. To do this make sure you do the following:
Have selected Background fetch under Your app settings > "Capabilities" > "Background Modes".
In AppDelegate.m, within application:didFinishLaunchingWithOptions, add the following code:
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
// Nothing
}];
You can now add a NSTimer in your AppDelegate and it will continue to run whilst in the background. E.g.,
_timerBg = [NSTimer scheduledTimerWithTimeInterval:1800
target:self
selector:#selector(bgFunction)
userInfo:nil
repeats:YES];
So, i want my app to do background execution for only a fixed amount of time, this is in case the user does not manually stop the app, and the app therefore in theory could run in background forever(is that even possible?).
I'm using the code below (just a test app) to test how long exactly a background task can run before ending. I read somewhere that 10 minutes is the longest we can do background execution, and there is no way to get beyond that(?). However, my code will only execute in the background for 3 minutes.
So to sum up my questions:
Is it possible to tell the app to execute in the background for x > 10 minutes?
2.Do i have any other options for something similar? (the actual app i need this implemented in, receives location updates in the background, the user could have the phone in the background for as long as 30 minutes, and suddenly not receiving updates would be bad)
- (void)viewDidLoad {
[super viewDidLoad];
counterTask = [[UIApplication sharedApplication]
beginBackgroundTaskWithExpirationHandler:^{
// do something }];
count=0;
theTimer=[NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:#selector(countUp)
userInfo:nil
repeats:YES];
}
- (void)countUp {
if (count==10000) {
[theTimer invalidate];
[[UIApplication sharedApplication] endBackgroundTask:counterTask];
} else {
NSLog(#"asd");
count++;
NSString *currentCount;
currentCount=[[NSString alloc] initWithFormat:#"%d",count];
_theCount.text=currentCount;
long seconds = lroundf([[UIApplication sharedApplication] backgroundTimeRemaining]);
NSLog([NSString stringWithFormat:#"%ld",seconds]);
}
}
I read somewhere that 10 minutes is the longest we can do background execution, and there is no way to get beyond that(?). However, my code will only execute in the background for 3 minutes.
yes you are right before iOS 7 iOS allowed 10 minutes max for apps to execute in background , however since iOS 7 they have reduced this time to 180 seconds.
But if you want to get Location Updates in background than you can add Required Background modes property in your info.Plist file. Using this you will be able to run your app in background for getting location updates Apple will review your request while reviewing your app for app store submission so be sure to use this mode only if you using it for its actual purpose.
Following are various modes for which apple allows background execution you can take a look at it at Apples Doc on background execution
Edit
If you wish to stop getting location Updates after specific time once user goes to backGround you can do this
- (void)applicationDidEnterBackground:(UIApplication *)application {
[self performSelector:#selector(stopGettingLocationUPdates) withObject:nil afterDelay:1800];
}
-(void)stopGettingLocationUPdates{
[self.locationManager stopUpdatingLocation]
}
This will stop updates after 30 mins.
Your code is not running in the background. It is not testing what you want to test.
Apple's docs say:
Executing a Finite-Length Task in the Background Apps that are
transitioning to the background can request an extra amount of time to
finish any important last-minute tasks. To request background
execution time, call the
beginBackgroundTaskWithName:expirationHandler: method of the
UIApplication class.
The actual time you get is not specified and is probably decided ad hoc based on power consumption, memory needs and so on. They may be a maximum.
They go on to say:
Implementing Long-Running Background Tasks For tasks that require more
execution time to implement, you must request specific permissions to
run them in the background without their being suspended. In iOS, only
specific app types are allowed to run in the background:
Apps that play audible content to the user while in the background, such as a music player app
Apps that record audio content while in the background.
Apps that keep users informed of their location at all times, such as a navigation app
Apps that support Voice over Internet Protocol (VoIP)
Apps that need to download and process new content regularly
Apps that receive regular updates from external accessories
Apps that implement these services must declare the services they support and use system frameworks to implement the relevant aspects of
those services. Declaring the services lets the system know which
services you use, but in some cases it is the system frameworks that
actually prevent your application from being suspended.
I use this code to execute function every X minutes:
- (void)executeEveryOneMinute
{
[self myFunction];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(60 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self executeEveryOneMinute];
});
}
And it works when app is in foreground.
But when app goes background it doesn't work anymore.
When I return app to foreground again it execute function once.
And continue to call function every minute again.
So how to make this to work in background too?
See the Background Execution and Multitasking section of the iOS App Programming Guide: App States and Multitasking for a discussion of the possibilities. You can, for example, keep the app running in the background for a few minutes in order to complete some finite length task. Or you can continue to run the app in the background for a longer period of time if it's performing one of a very particular list of functions (quoting from the aforementioned document):
Apps that play audible content to the user while in the background, such as a music player app
Apps that record audio content while in the background.
Apps that keep users informed of their location at all times, such as a navigation app
Apps that support Voice over Internet Protocol (VoIP)
Apps that need to download and process new content regularly
Apps that receive regular updates from external accessories
Apps that implement these services must declare the services they support and use system frameworks to implement the relevant aspects of those services. Declaring the services lets the system know which services you use, but in some cases it is the system frameworks that actually prevent your application from being suspended.
But, a fundamental design principle in iOS battery/power management is that random apps can not (and should not) continue to run in the background. If you share what precisely you're trying to do (namely, what precisely you're doing inside that executeEveryOneMinute method), though, we can offer counsel on how to achieve the desired effect, if possible.
If you're trying to have an upload continue in the background, in iOS 7 and greater, you should consider using NSURLSession with a background session configuration ([NSURLSessionConfiguration backgroundSessionConfiguration:identifier]; there is a similar method in iOS 8). This will continue to attempt to upload (automatically, without further intervention on your part) not only after your app has left the foreground, but even after the app is terminated (e.g. due to memory pressure or a crash). AFNetworking offers a NSURLSession-based class, AFURLSessionManager, which supports this (though it's not NSOperation-based). This way, you enjoy background uploads, but conforms to Apple guidelines on background operation, notably with less dramatic battery impact than retrying yourself every 60 seconds.
I'd suggest you refer to the latter part of WWDC 2013 video What’s New in Foundation Networking, which demonstrates this process (they're doing a download, but the idea is the same for uploads).
Timer works on Main thread. When application goes into background, its timers become invalid. So, you cant do the same when application goes into background.
You can't do this with help of timer as it will be invalidated in background. You can try check this.
You should use background tasks to achieve what you want
UIApplication* app = [UIApplication sharedApplication];
task = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:task];
task = UIBackgroundTaskInvalid;
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do the work associated with the task.
NSLog(#"Started background task timeremaining = %f", [app backgroundTimeRemaining]);
if (connectedToNetwork) {
// do work son...
}
[app endBackgroundTask:task];
task = UIBackgroundTaskInvalid;
});
i am trying download load the large videos(400 mb) into background cont.... until end of the video in iOS-7 using Xcode-5 . But After 10 or 5 min downloading is stop .
i wrote the code like below and i set the "background fetch mode is YES". Is There any wrong with my code.
Ref 1: https://developer.apple.com/library/ios/documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html
Ref 2:
Question : How can i kept alive the my URL request upto my videos are downloaded in background mode?
Thanks in Advence.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIApplication *app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier m_backgroundTaskId;
m_backgroundTaskId = [[UIApplication sharedApplication]
beginBackgroundTaskWithExpirationHandler:^(void) {
m_isWentBackground = YES;
[m_dataController saveUnfineshedDownoadsToFile];
[[UIApplication sharedApplication]
endBackgroundTask:m_backgroundTaskId];
m_backgroundTaskId = UIBackgroundTaskInvalid;
}];
}
You are doing it wrong, the beginBackgroundTaskWithExpirationHandler will give you up to 10 extra minutes to download, but if you want real background download, you have to look into Background Transfer Service
You have 2 tutorials:
One from techtopia
Other from tuts plus
Background processing is only allowed to a maximum of 10 minutes in ios unless your app is of one of the following types..
Apps that play audible content to the user while in the background, such as a music player app
Apps that keep users informed of their location at all times, such as a navigation app
Apps that support Voice over Internet Protocol (VoIP)
Newsstand apps that need to download and process new content
Apps that receive regular updates from external accessories
Refer the following for more info..
http://docs.xamarin.com/guides/cross-platform/application_fundamentals/backgrounding/part_3_ios_backgrounding_techniques/ios_backgrounding_with_tasks/
https://stackoverflow.com/a/9738707/919545
The beginBackgroundTaskWithExpirationHandler of UIApplication is supposed to be used a "task finisher". There is nothing wrong with your code, but it is the purpose of this code that is the problem.
This operation will be kept alive for a maximum of 10 min or so, and it is the operating system which decides for how long the task will be operational. If you are downloading a 400mb video, it is not what you need.
You should consider another way to do this task - Which is not in a background operation.
A background operation, by Apple own definition can not last more than 10 minutes.
Perhaps, performing queued background operations, that will gradually append data, until you will have the complete video? Or doing this operation while app is not in background in another thread?
A 400mb video does not sounds like something a mobile device should do, as default.
I have created a sample code to download a file from network repeatedly(every 30 secs or so). In iOS 7 using Background transfer services with NSURLSession
I followed this tutorial http://mobile.tutsplus.com/tutorials/iphone/ios-7-sdk-background-transfer-service/
and added a timer like this to repeat it.
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
mute = [NSTimer scheduledTimerWithTimeInterval:30.0f
target:self
selector:#selector(startDownload)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:mute forMode:NSRunLoopCommonModes];
When I run it(in background by clicking home button) in simulator and on iPad connected to the Xcode(where I can see the logs) everything works fine and it keeps downloading continuously.
But when I disconnect the iPad from the Mac and run it on the iPad in background after around 3 seconds it stops running (handleEventsForBackgroundURLSession in AppDelegate get called).
In Xcode project capabilities I have selected Background fetch as Background Modes.
What am I missing here or what have I done wrong so that it gets stop after around 3 minutes?
(According to the documentations with iOS 7 Background transfer services it should run continuously as there's no time limit in background for this.)
Thanks
Background tasks in iOS7 will only give you 30 seconds at most (dramatically down from 10 minutes). You should use the new fetch background mode instead. You should not be using a timer, but use the newly provided API to ask the OS to be woken up in regular intervals and set up your download using NSURLSession.
Background Fetch is something different. Background Fetch will wake up your app for periodic fetches of new data (typically, a < 30s network request looking for updates). This is not related to background NSURLSessions and should probably be turned off if you aren't actually using it for queuing NSURLSessionDownloadTasks or other update purposes.
From what I understand, it's possible that the behavior you are seeing is actually normal. I do not believe that background NSURLSessionDownloadTasks are guaranteed to run continuously or on any device configuration (AC vs battery, WiFi vs Cellular, etc.) You said that you disconnected from your Mac which would switch device state from charging to battery. Among other factors, that could be enough to pause transfers or decrease download limits. Unfortunately, this system appears to be very opaque to developers.
To be sure you are getting the highest priority available, make sure your discretionary property on your NSURLSessionConfiguration is set to false. Download tasks created while the app is in the background will always have this set to true, so just an FYI there.
Apple's sample code will put you on the right track: https://developer.apple.com/library/iOS/samplecode/SimpleBackgroundTransfer/Introduction/Intro.html
Try the below steps. This worked fine for me.
In your .h
UIBackgroundTaskIdentifier bgTask;
In .m
//background task code
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ [app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
[NSTimer scheduledTimerWithTimeInterval:30.0f target:self selector:#selector(startDownload) userInfo:nil repeats:YES];
And yor method for downloading is
-(void)startDownload{
NSLog(#"will log even if in background or foreground");
}
Practically using [[UIApplication sharedApplication]beginBackgroundTaskWithExpirationHandler: ^{}]; will give you only 180 sec.Xcode provides the facility of background active app while debugging only just to ease developers.
NSURLSession download tasks are indeed not bound to time restrictions. But they are completely managed by the system. They may get postponed if the system resources are low. They are normally dialed down when there is no wifi or when the device is not plugged. The system also observes your app's use of the background transfer services and may treat it with lower priority if it detects that it abuses the feature. A background transfer every 30 seconds, is certainly considered an abuse.
I suggest dropping the use of Background Transfer Services and set up the entire thing using background fetch (which is a completely different thing btw). Just be careful if you want to reach the store, you must fall in one of the accepted uses cases for the feature to be approved for your app. If not, then there is little hope. Not sure what you are trying to do. Maybe you don't really need to have so much background activity.