We implemented a functionality that tracks the user location on the background at least every 15 minutes. At the moment the background tracking works great for a couple of hours, some cases up until 8 hours, and other cases can go up to 6 days.
The issue is that at a certain point while the user is stationary the app stops managing the location updates for no apparent reason, and reopening the application will not resume the tracking process. We know that the app is not managing the location updates because the device logs show an event from locationd sending the position to our app, but there's no code execution.
We understand that the OS at any time can terminate the application, but we would like to be able to manage those cases to correctly communicate this behavior to the user that expects tracking to keep functioning or for the tracking to continue sending locations in the background.
This issue seems to be inconsistent across our user base, we've identified that users with iOS 14.4+ and from the iPhone 8 up to the iPhone 13 present this problem.
Our current configuration for the location manager is:
AppDelegate.m
#implementation AppDelegate
Location *geoData;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
///...
if (geoData == nil) {
geoData = [Location sharedInstance];
}
///...
}
- (void)applicationWillTerminate:(UIApplication *)application{
geoData = nil;
}
Location.h
#property (nonatomic, retain) CLLocationManager *locationManager;
Location.m
_locationManager = [[CLLocationManager alloc] init];
[_locationManager setDelegate:self];
if ([_locationManager respondsToSelector:#selector(requestAlwaysAuthorization)])
{
[_locationManager requestAlwaysAuthorization];
}
if ([_locationManager respondsToSelector:#selector(allowsBackgroundLocationUpdates)]) {
_locationManager.allowsBackgroundLocationUpdates = YES;
}
_locationManager.pausesLocationUpdatesAutomatically = NO
_locationManager.desiredAccuracy = kCLLocationAccuracyKilometer
_locationManager.activityType = CLActivityTypeAutomotiveNavigation;
[_locationManager startUpdatingLocation];
We receive the updates through the didUpdateLocations where we send the data to an external API server.
The app is configured with Background fetch and Location updates background modes.
Related
I have a location app that needs to get accurate location periodically. Currently I am getting constantly getting location in didUpdateLocation but I only ever log the location every 5 seconds. I am interested in a solution that gets accurate location periodically or on signification change. I would like either or both of these scenarios:
(by very accurate, I need 10m of desired accuracy)
Get a very accurate location every 5 seconds
Notify/callback if user moves a threshold ( eg moves 5 - 10 meters)
The app needs to work when backgrounded as well and location must still be logged if user switches to another app.
I was considering turning on/off location every 5 seconds but was not sure if that is the best practice. I also know there is also allowDeferredLocationUpdatesUntilTraveled but I believe that only applied to backgrounded mode. I would appreciate a solution that saves battery when the app is in use and in background mode. Please share your solutions and best practices for my use case.
I did write an app using Location services, app must send location every 10s. And it worked very well.
Just use the "allowDeferredLocationUpdatesUntilTraveled:timeout" method, following Apple's doc.
Steps are as follows:
Required: Register background mode for update Location.
Create LocationManger and startUpdatingLocation, with accuracy and filteredDistance as whatever you want:
-(void) initLocationManager
{
// Create the manager object
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
_locationManager.delegate = self;
// This is the most important property to set for the manager. It ultimately determines how the manager will
// attempt to acquire location and thus, the amount of power that will be consumed.
_locationManager.desiredAccuracy = 45;
_locationManager.distanceFilter = 100;
// Once configured, the location manager must be "started".
[_locationManager startUpdatingLocation];
}
To keep app run forever using "allowDeferredLocationUpdatesUntilTraveled:timeout" method in background, you must restart updatingLocation with new parameter when app moves to background, like this:
- (void)applicationWillResignActive:(UIApplication *)application {
_isBackgroundMode = YES;
[_locationManager stopUpdatingLocation];
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[_locationManager setDistanceFilter:kCLDistanceFilterNone];
_locationManager.pausesLocationUpdatesAutomatically = NO;
_locationManager.activityType = CLActivityTypeAutomotiveNavigation;
[_locationManager startUpdatingLocation];
}
App gets updatedLocations as normal with "locationManager:didUpdateLocations:" callback:
-(void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
// store data
CLLocation *newLocation = [locations lastObject];
self.userLocation = newLocation;
//tell the centralManager that you want to deferred this updatedLocation
if (_isBackgroundMode && !_deferringUpdates)
{
_deferringUpdates = YES;
[self.locationManager allowDeferredLocationUpdatesUntilTraveled:CLLocationDistanceMax timeout:10];
}
}
But you should handle the data in then "locationManager:didFinishDeferredUpdatesWithError:" callback for your purpose
- (void) locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error {
_deferringUpdates = NO;
//do something
}
NOTE: I think we should reset parameters of LocationManager each time app switches between background/forgeround mode.
Hopefully this should help
I have gone through so many links, even after that I haven't found a proper solution for getting latitude and longitude.
Periodic iOS background location updates
iOS long-running background timer with "location" background mode
I tried from some links and forums but it is working for only 3 mins, then app is not at all updating the user location.
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
//create new uiBackgroundTask
__block UIBackgroundTaskIdentifier bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
//and create new timer with async call:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
[locationManager startUpdatingLocation];
NSTimer* t = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:#selector(startTrackingBg) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:t forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
});
}
-(void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
// store data
CLLocation *newLocation = [locations lastObject];
//tell the centralManager that you want to deferred this updatedLocation
if (_isBackgroundMode && !_deferringUpdates)
{
_deferringUpdates = YES;
[locationManager allowDeferredLocationUpdatesUntilTraveled:CLLocationDistanceMax timeout:10];
}
}
Ok.
After struggling for 3days, it is working for me for sending latitude and longitude when app is in background even after 3 mins.
I checked my app, continuously sending lat long for more than a hour in background.
It can help some one at least.
First Please add below two keys in your pList.
1.NSLocationAlwaysUsageDescription
2.NSLocationWhenInUseUsageDescription
Bothe are strings and you can give any value.
Then please turn on background fetch and check location updates under capabilities in project section.
Then import Corelocation framework and add this below code.
locationManager is a global variable.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
//create CLLocationManager variable
locationManager = [[CLLocationManager alloc] init];
//set delegate
locationManager.delegate = self;
app = [UIApplication sharedApplication];
// This is the most important property to set for the manager. It ultimately determines how the manager will
// attempt to acquire location and thus, the amount of power that will be consumed.
if ([locationManager respondsToSelector:#selector(setAllowsBackgroundLocationUpdates:)]) {
[locationManager setAllowsBackgroundLocationUpdates:YES];
}
locationManager.desiredAccuracy = 45;
locationManager.distanceFilter = 100;
// Once configured, the location manager must be "started".
[locationManager startUpdatingLocation];
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
[locationManager stopUpdatingLocation];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[locationManager setDistanceFilter:kCLDistanceFilterNone];
locationManager.pausesLocationUpdatesAutomatically = NO;
locationManager.activityType = CLActivityTypeAutomotiveNavigation;
[locationManager startUpdatingLocation];
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
[locationManager stopUpdatingLocation];
__block UIBackgroundTaskIdentifier bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
bgTask = UIBackgroundTaskInvalid;
}];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:10.0
target:self
selector:#selector(startTrackingBg)
userInfo:nil
repeats:YES];
}
-(void)startTrackingBg {
[locationManager startUpdatingLocation];
NSLog(#"App is running in background");
}
//starts automatically with locationManager
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
latitude=newLocation.coordinate.latitude;
longitude=newLocation.coordinate.longitude;
NSLog(#"Location: %f, %f",newLocation.coordinate.longitude, newLocation.coordinate.latitude);
}
You need to refer this apple documentation handling location events in the background
You need to enable location updates in background modes in capabilities of your Xcode project.
The Standard location service wont work in background mode so you have to use either Significant-change location service or Visits service .
Use this code to
locationManager.delegate = self
locationManager.startMonitoringSignificantLocationChanges()
enable Significant-change location service.
Building on Santos answer which has most of the important steps to make background positioning work, I have clarified and corrected some details.
Project settings
You should add these keys to your Xcode Target Info property list. Make sure to add a valid description to each of them, or your app might fail approval.
NSLocationAlwaysUsageDescription
NSLocationWhenInUseUsageDescription
NSLocationAlwaysAndWhenInUseUsageDescription
Next, in Target Capabilities, Turn on Background Modes and check Location updates and Background fetch. Location updates will enable locations in the background and background fetch will allow you to use the network in the background.
Start monitoring
Start by creating an instance of CLLocationManager, configure it and turn on background updates, then start it. Although the code below uses the most common function startUpdatingLocation to get locations, there are several other services to use. It is important to choose the most suitable service as this impacts greatly on battery usage and if the app will be re-launched or not by iOS. See below for more info on this.
// Declare as properties in your class
#property (strong, nonatomic) CLLocationManager *locationManager;
#property (strong, nonatomic) CLLocation *lastLocation;
// Call to start
- (void)initializeAndStartLocationService {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// Must be set for background operation
self.locationManager.allowsBackgroundLocationUpdates = YES;
// Optional configuration
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.pausesLocationUpdatesAutomatically = YES;
self.locationManager.showsBackgroundLocationIndicator = YES;
// Authorize - the lazy way
[self.locationManager requestAlwaysAuthorization];
// Start the standard location service, there are others
[self.locationManager startUpdatingLocation];
}
// Delegate method that will receive location updates
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
// Keep the last received location
self.lastLocation = [locations lastObject];
NSLog(#"New position %f, %f", self.lastLocation.coordinate.latitude, self.lastLocation.coordinate.longitude);
// Do something with the location or retrieve the location later
// :
}
Stop monitoring
Don't forget to stop monitoring to conserve battery. You can start and stop several times on a single instance of CLLocationManager.
- (void)dealloc {
[self.locationManager stopUpdatingLocation];
}
Automatic app re-launch considerations
When your app is running in the background it can (and actually frequently will after some time) be terminated by iOS. Depending on the type of location updates you are using, iOS will or will not re-launch your app automatically for you. In cases where iOS do not re-launch, the user must start your app again to continue background processing.
Read more on this page.
Read more
CLLocationManager - Core Location | Apple Documentation
Handling Location Events in the Background | Apple Documentation
I am in the process of testing location updates via the background APIs that relaunch an app. I have successfully tested visits and regions and am using this same app to also test significantLocationChanges (SLC). I run my app, press home twice then swipe it off to kill it. Then I drive around. I can observe the app background activity without touching the phone via a server where (see code below) the singleton method sendBackgroundTestRecord uploads simple status messages to the server.
When I test visits and regions I have no problems. However when I test SLC, nothing happens until I turn the phone's screen on (pressing the power or home button once -- not re-running the app, or even unlocking the phone). I can drive a far distance without anything happening. I suspect the app has received an SLC event sometime during that drive because as soon as I turn the phone on for a about 2 seconds, the code below executes and I can observe the messages on the server.
I believe this is not just a network connectivity delay because the sendBackgrounTestRecord method uses a time stamp. The records on the server show a time stamp of when I turned the screen on, not when the SLC event is suspected to have fired.
I never have this problem with visits or regions, only SLC. By the way, the code has gone through many changes trying to chase this down. The latest attempt (code below) was to put everything in the appDelegate.
Any ideas?
Thanks in advance for any ideas whatsoever!
EDIT: I added beginBackgroundTaskWithExpirationHandler, which was in my original tests too.
// AppDelegate.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate, CLLocationManagerDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
// AppDelegate.m
#import "AppDelegate.h"
#import "clsCommon.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//Ask iOS for more time to process - before we do anything else
[clsCommon sharedInstance].backgroundTaskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{}];
[[clsCommon sharedInstance] sendBackgroundTestRecord:#"didFinishLaunchingWithOptions"];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
if([self.locationManager respondsToSelector:#selector(setAllowsBackgroundLocationUpdates:)]) {
[self.locationManager setAllowsBackgroundLocationUpdates:YES];
}
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.activityType = CLActivityTypeAutomotiveNavigation;
self.locationManager.allowsBackgroundLocationUpdates = YES;
self.locationManager.pausesLocationUpdatesAutomatically = NO;
if([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[self.locationManager requestAlwaysAuthorization];
}
[self.locationManager startMonitoringSignificantLocationChanges];
return YES;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
[[clsCommon sharedInstance] sendBackgroundTestRecord:#"didUpdateLocations"];
CLLocation * currentLocation = [locations objectAtIndex:0];
if(currentLocation !=nil) {
[[clsCommon sharedInstance] sendBackgroundTestRecord:#"didUpdateLocations curLoc not nill"];
}
}
#end
Well, knowing how aggressively iOS resolves all tradeoffs in favor of battery life I would not be surprised very much. For example, behavior of "breadcrumbs" app (set 100m geofence at your current location, move that geofence to new location on exit event) is very different depending on whether iPhone sleeps all the time in your pocket, or you check lock screen occasionally.
However, running an app very similar to yours while traveling back home yesterday did generate location updates for me.
Distances between SLC readings were in 4 to 14 km range, the smallest time gap between two consequent readings - 14 minutes. The app is very similar to yours, it does not include any networking part, just logging events to a local file (NSLog via stderr redirection). Also, I do not configure properties, which are irrelevant for SLC in location manager, like desiredAccuracy, distanceFIlter, activityType. I suggest you start from barebone app and watch for the improvement, which breaks it.
One thing to check is if your app crashes when handling location updates. If it happens in background you will not notice this unless you run logging or check crash logs via Settings.app.
Put some distance in self.locationManager.distanceFilterand is better for battery change self.locationManager.pausesLocationUpdatesAutomatically=YES;
Start Location Manager in iOS 7 from background task
On early 2014, Apple has updated the iOS 7.0 to 7.1 in order to allow location updates even when the app is not active on foreground and not in the background. How do we do that?
I have read some articles like Apple's iOS 7.1 will fix a geolocation bug. But Apple didn't provide much communication related to that nor any sample code on how to get the location update even when the app is killed/terminated/suspended.
I have read the Release Notes for iOS 7.1. I couldn't find anything related to that as well.
So, how do we actually get the location update for iOS 7 and 8 even when the app is suspended?
After months of trials and errors by experimenting the Core Location Framework, I have found the solution to get location update even when the app is killed/suspended. It works well for both iOS 7 and 8.
Here is the solution:-
If your app is a location based mobile application that needs to monitor the location of the device when it has significant changes, the iOS will return you some location coordinates when the device has moved more than 500 meters from the last known location. Yes, even when the app is killed/suspended either by the user or iOS itself, you still can get the location updates.
So in order for a locationManager to get location update even when the app is killed/suspended, you must use the method startMonitoringSignificantLocationChanges, you can not use startUpdatingLocation.
When iOS wants to return the location update to the app, it will help you to relaunch the app and return a key UIApplicationLaunchOptionsLocationKey to the app delegate method didFinishLaunchingWithOptions.
The key UIApplicationLaunchOptionsLocationKey is very important and you must know how to handle it. You must create a new locationManager instance when you receive the key and you will get the location update on the locationManager delegate method didUpdateLocations.
Here is the sample code:-
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
self.shareModel = [LocationShareModel sharedModel];
if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) {
self.shareModel.anotherLocationManager = [[CLLocationManager alloc]init];
self.shareModel.anotherLocationManager.delegate = self;
self.shareModel.anotherLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.shareModel.anotherLocationManager.activityType = CLActivityTypeOtherNavigation;
if(IS_OS_8_OR_LATER) {
[self.shareModel.anotherLocationManager requestAlwaysAuthorization];
}
[self.shareModel.anotherLocationManager startMonitoringSignificantLocationChanges];
}
return YES;
}
In addition to the didFinishLaunchingWithOptions method, I have created the locationManager instance when the app is active. Here are some code examples:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[self.shareModel.anotherLocationManager stopMonitoringSignificantLocationChanges];
if(IS_OS_8_OR_LATER) {
[self.shareModel.anotherLocationManager requestAlwaysAuthorization];
}
[self.shareModel.anotherLocationManager startMonitoringSignificantLocationChanges];
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
if(self.shareModel.anotherLocationManager)
[self.shareModel.anotherLocationManager stopMonitoringSignificantLocationChanges];
self.shareModel.anotherLocationManager = [[CLLocationManager alloc]init];
self.shareModel.anotherLocationManager.delegate = self;
self.shareModel.anotherLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.shareModel.anotherLocationManager.activityType = CLActivityTypeOtherNavigation;
if(IS_OS_8_OR_LATER) {
[self.shareModel.anotherLocationManager requestAlwaysAuthorization];
}
[self.shareModel.anotherLocationManager startMonitoringSignificantLocationChanges];
}
I have written an article explaining on the details on how to get the location update for iOS 7 and 8 even when the app is killed/suspended. I have also uploaded the complete source code on GitHub with the steps on how to test this solution.
Please visit the following URLs for more information:-
Getting Location Updates for iOS 7 and 8 when the App is Killed/Terminated/Suspended
Source Code on GitHub - Get the Location Updates Even when the iOS mobile apps is Suspended/Terminated/Killed
locationManager = [[CLLocationManager alloc] init];
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
if(IS_OS_8_OR_LATER)
{
[locationManager requestWhenInUseAuthorization];
}
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; //whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
[locationManager startUpdatingLocation];
that code user location update only forground app running but not background run
[locationManager requestWhenInUseAuthorization];
I am trying to fetch user locations in foreground & background. I have to call api after I got a locaion update. To work in background I want to use Deferred method. I followed the same process as described in Apple WWDC. I am checking app on iPhone 5 (iOS 7). It is working fine when I am in foreground but did not give me update after I send the app into background. Below is the code which I am using to get location in background.
#import "AppDelegate.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.locationArray = [[NSMutableArray alloc] init];
self.locationErrorArray = [[NSMutableArray alloc] init];
self.manager_loc = [[CLLocationManager alloc] init];
self.manager_loc.activityType = CLActivityTypeFitness;
self.manager_loc.delegate = self;
[self.manager_loc setDesiredAccuracy:kCLLocationAccuracyBest];
[self.manager_loc startUpdatingLocation];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
#pragma mark - Location Manager Delgate
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"update failed");
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
[self.locationArray addObject:locations];
NSLog(#"udate locations %f %f", manager.location.coordinate.latitude, manager.location.coordinate.longitude);
if (!self.deferredStatus)
{
self.deferredStatus = YES;
[self.manager_loc allowDeferredLocationUpdatesUntilTraveled:100 timeout:30];
}
[self.manager_loc stopUpdatingLocation];
}
-(void)locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error
{if (manager.location != nil)
{ [self.locationArray addObject:manager.location];
}
if (error != nil)
{
[self.locationErrorArray addObject:error.description];
}
self.deferredStatus = NO;
NSLog(#"deffered success %f %f", manager.location.coordinate.latitude, manager.location.coordinate.longitude);
}
#end
If I do not stop the location update in didUpdateToLocations Delegate then the location arrow (on status bar) do not go. In that case it gives me locations contionusly. I want location update after a particular time or particualar distance travelled, so that I can hit server with the user locations. Please help me on this.
Use LocationManger distanceFilter Property for update location at particualar distance travelled.
self.manager_loc.distanceFilter= 100;// In meters
If you want location updated in Backggriound then register your for background updates. Youca can do it in plist.
Set location manager to :
if ([self.locationManager respondsToSelector:#selector(pausesLocationUpdatesAutomatically)]) {
self.locationManager.pausesLocationUpdatesAutomatically = NO;
}
Then If you want to location updated after some time or distance then use:
- (void)allowDeferredLocationUpdatesUntilTraveled:(CLLocationDistance)distance
timeout:(NSTimeInterval)timeout // No guaranty it will work exactly or not
If you want location updated based on distance the you can use
Desired accuracty and distanceFilter property.
self.locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;// Use other accurarcy as your need
self.locationManager.distanceFilter = 3000; //100, 200, etc
If you set activity type to CLActivityTypeFitness all above setting will overrided, And location manager updated according to this activity, which is as per my knowledge will eat Battery.
While using CLLocation Manager one thing you should accept it will not give all updartes 100% accurate.
See my answer for this post: StartUpdateLocations in Background, didUpdatingToLocation only called 10-20 times
If you need location updates in the background under iOS 7, you must call startUpdatingLocation while your App is in the foreground. You can no longer do this while your App is in the background, so you can no longer register for location updates only when you need them and while you need them. You are forced to register for them for the whole time your App is running (in the foreground and the background) and so you’re forced to waste a lot of energy.
You can reduce the battery usage a little bit by setting the accuracy to kCLLocationAccuracyThreeKilometers when you do not need the location updates and set them to kCLLocationAccuracyBest only when you need the updates. But this will nevertheless drain the battery faster than expected.
Please write a bug report to Apple and ask for the „old" behavior of iOS 4,5 and 6, where you could call „startUpdatingLocation“ in the background as well to get location updates in the background. If Apple gets enough requests to change this behavior back to the way it was implemented in iOS 5/6, the more likely it is that Apple will change this back.
The currents situation is really bad. Bad for developers, which are forced to waste energy, or to abandon their Apps, bad for the user, whose device needs to be plugged to a power source much earlier, or who can no longer use certain Apps.