How do I get a background location update every 1second in my iOS application? - objective-c

I'm looking for a way to get a background location updates forever. I'm using iOS 7.1.
Current Scenario : It is running fine in background but not forever. After every 22 to 30 minutes, GPS Location updates gets suspended.
Note : We get GPS update forever as long as we are moving but when we stop for more than an hour the location update get suspended automatically by OS...again when we start moving the OS does not resume/detect the location update automatically...
So first question is :
How to re-invoke location service from that 22nd or 30th minute so that it can run continuously and forever?
Below set of properties we have set our application plist file :
Required Background Modes :
App registers for location updates
App provides Voice over IP services
App plays audio or streams audio/video using AirPlay
And also we have done this :
UIApplication *app = [UIApplication sharedApplication];
_bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:_bgTask];
_bgTask = UIBackgroundTaskInvalid;
}];
where _bgTask is UIBackgroundTaskIdentifier.
Secondly we also want to capture the GPS Location update in every 1 second. For that we have written a separate timer to capture that location update. please note that once the GPS location update gets suspended by the OS it also suspend our timer.
So second question is : How can I run the timer forever in the background?

Related

Uploading image in background ios

I know there is NSURLSession class which is launched in iOS7 and it does have NSURLSessionUploadTask for uploading data to server, But I need to know whether it will continue uploading even after in background mode if no? then what to do for continue that task in background mode too for complete uploading.
previously we can use beginBackgroundTaskWithExpirationHandler: and endBackgroundTask: which will continue that task to max 10 minutes for iOS6 but in iOS 7 and above it will hardly run upto 3 minutes (as per my knowledge).
So can you please help me guys for any solution or example if available.
The answer for your first question is probably YES, you can continue uploading for the tim e that is permitted by the iOS but for that you need use UIBackgroundTaskIdentifier to get hold of that extra time.
And for the second part of your question for uploading the remaining images when the app is not running you can use Background fetch. When you enable Background fetch the app regularly downloads and processes small amounts of content from the network. So probably by combining UIBackgroundTaskIdentifier and Background fetch you can achieve uploading the images in background.
Below mentioned are the steps to combine UIBackgroundTaskIdentifier and Background fetch.
First let's initialise UIBackgroundTaskIdentifier
-(void) beginBackgroundUploadTask
{
if(self.backgroundTask != UIBackgroundTaskInvalid)
{
[self endBackgroundUploadTask];
}
self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundUploadTask];
}];
}
Once the background task runs out of time from the stipulated allotted time, we should invalidate and end the background task.
-(void) endBackgroundUploadTask
{
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask ];
self. backgroundTask = UIBackgroundTaskInvalid;
}
Do not forget to enable Background Modes in Xcode → Select Project File → Capabilities → Check the Background fetch checkbox.
For further info you can refer the link below:
http://mobisoftinfotech.com/resources/mguide/background-fetch-ios/

UIApplication fixed background fetch interval (private API welcome)

I'm working on an internal app that requires to check the server every 10 mins or so when the application enters background. Normally, I can use APNS when new record arrives.
However, this app will completely skip Apple's garden, so no APN and yes private API.
So the question, is there any way for me to set the background fetch interval directly instead of calling the normal application setMinimumBackgroundFetchInterval:
I also welcome other ideas for the same result.
I recommend implement VOIP background mode, because is simply and provide app wakeup every few minutes. Just set Voice over IP in Background Modes and register handler;
Example:
[[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{
NSLog(#"Here I do something every 600 seconds");
}];
This method more preferable because can work on old iOS, and timeout is fixed vs background fetch where timeout is calculated by user activity and app usage.

iOS 7 - Update Data Every 24 Hours

I'm creating an app that needs to check for data once a day (midnight). I know there is a background fetch mode in iOS7, but from what I know there is no way to force it to update in given time interval. Is there any way to do this and still pass the Appstore review?
Thank you for any suggestions.
There is not real way to do this, since it requires you app to be running in background. background running modes are restricted to audio, VOIP, location and accessory type apps.
What you could do is just check when you last update data in the app when the user launches the app. This way you will only update data when the user starts your app and also only use data when the user is really using the app.
The background fetching will only work if the user is start your app often and iOS will allow you app to do background fetching. iOS will decide when you app is allowed to do a background refresh and you have little influence over the interval.
UIApplicationBackgroundFetchIntervalMinimum
The smallest fetchinterval supported by the system.
Maybe it's not exactly answer you expect but in iOS 7 there is a functionality which allow you to fetch the data every some period of time.
In this scenario iOS intelligently schedules the background fetch events based on your app usage and it helps you save battery life. So this not going to work every 24h but I think you can read the data and if it has been updated refresh the app if not ignore it.
In your Xcode 5 -> Target -> Capabilities turn on Background modes (background fetch).
And in application:didFinishLaunchingWithOptions add:
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
This is a method which will be called:
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
}

ios 7 : didreceiveremotenotification fetchcompletionhandler not getting called when app kept in background for over night testing

I have used VoIP and remote notification as background modes.
I kept my application idle in background for overnight testing.
I have written following code in applicationDidEnterBackground
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{
NSString *message = #"voip keep alive timeout executed....";
NSLog(#"%#",message);
[Logger addEntry:CAT_ML_CORE andSubCategory:SUBCAT_DEBUG andMessage:message];
}];
}
after 1 day keeping application idle in background I found "voip keep alive timeout executed...." got printed in my logs.
This indicated that my app is alive.
But when I send push notification to my app "didreceiveremotenotification fetchcompletionhandler" method doesn't get called.
Which is contradictory to the statement made by Apple "Unlike the application:didReceiveRemoteNotification: method, which is called only when your app is running, the system calls didreceiveremotenotification fetchcompletionhandler method regardless of the state of your app. If your app is suspended or not running, the system wakes up or launches your app and puts it into the background running state before calling the method."
Can someone please tell me why this is happening?
Make sure your APNS payload has "content-available"
content-available - number - Provide this key with a value of 1 to indicate that new content is available.This is used to support Newsstand apps and background content downloads.
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html

Background task doesn't seem to get cancelled/ended

We're currently developing an iOS app that needs to check location in the background. At first, we tried to use significant location changes, but they aren't accurate enough/don't trigger often enough. We considered using region monitoring, but from what I've read online, that isn't always accurate either, and you also have the problem of a limited number of regions to monitor. (We may eventually try region monitoring.) At the moment, however, we're attempting to use the standard location updates to track the user location in the background, with a plan to have it at check at intervals of 5 minutes, or so.
The app is registered for location updates in the background (using 'App registers for location updates' for 'Required background modes'), and we start a background task which checks the location once, stops location updates, then uses NSThread sleepForTimeInterval: to (at the moment, while we're in development) pause the task for 10 seconds. It then checks the location once again, stops location updates, pauses for 10 seconds, etc.
This appears to work as expected... When the app goes into the background, we receive a log/notification with our location update every 10 seconds, and when the app is reopened, the logs/notifications stop. However, the problem is that when the app then goes into the background for a second time, it appears the original background task was never cancelled, and a new one is created, so there are now two tasks running, each checking location at 10 sec on intervals. If the app is opened/sent to the background multiple times, then a background task is started for each of them.
I thought about setting a flag to say "has the app been sent to the background at least once?", and only run the task if it's the first time it's sent to the background, but this seems to cause additional problems, and (as a relatively new iOS developer) I'm curious as to why the background tasks aren't being cancelled when the app enters the foreground.
The AppDelegate.h file contains...
#interface AppDelegate : UIResponder <UIApplicationDelegate, CLLocationManagerDelegate> {
UIWindow *window;
UINavigationController *navigationController;
UIBackgroundTaskIdentifier bgTask;
BOOL inBackground;
}
The AppDelegate.m file contains...
- (void)applicationDidEnterBackground:(UIApplication *)application {
inBackground = YES;
bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
while (inBackground == YES) {
NSLog(#"%#", #"Check location...");
[locationManager startUpdatingLocation];
[NSThread sleepForTimeInterval:10];
}
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
inBackground = NO;
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
The location updates are working as expected, I just can't work out why the background tasks aren't being cancelled/ended when the app enters the foreground. I do wonder if it's anything to do with the NSThread sleepForTimeInterval:, but I'm not sure if it is, or how to fix it (if indeed, it is). Thanks, in advance, for any help!
You don't manage location updates by sleeping and then requesting them. You manage location updates by setting "location" in UIBackgroundMode (as you do), and then implementing a CLLocationManagerDelegate. This has nothing to do with beginBackgroundTaskWithExpirationHandler:. That's for requesting additional time (up to about 10 minutes) to finish a given operation. You shouldn't be calling that at all just to get location updates.
Once you've registered as a location app in UIBackgroundMode, you will automatically get updates whenever the location changes within the accuracy you specified for your location manager. The system will do all the work for you.
What you're describing may actually hurt battery life because it frustrates the OS's ability to manage the multiple location sensors (of which the GPS is just one). Tell the OS what you need by setting the correct accuracy (if significant changes is too coarse), and let it do its job. Getting really accurate location from the GPS is expensive. You should do battery testing before assuming that it's cheaper to do every 5 minutes than to leave on. The best thing you can do to preserve power is to reduce the required accuracy. You might turn it down to a coarse level, and then when you come to the foreground move it to an accurate level. But keeping track of precisely where the user is every 5 minutes is going to be expensive. It's hard to fix that.
BTW, what you're really trying to do here is get to run "something" every 5 minutes. There is no mechanism for that in iOS. You can either ask for location services or not (and configure it in various ways). You can't ask for "I want to wake up every five minutes and ... do anything." After about 10 minutes you're going to be killed if you don't call endBackgroundTask:.
To your question of why the tasks aren't being cancelled, see How to use beginBackgroundTaskWithExpirationHandler for already running task in iOS. As I said, this "background tasks" is not the tool you want for this problem. It's completely unrelated.
I'm fairly certain that your instance variable bgTask is being reallocated when the app comes back into the foreground, so the value doesn't contain the identifier you're looking to kill. Consider saving this identifier in NSUserDefaults or something a little more permanent and retrieving it later.