32

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?

jscs
  • 63,694
  • 13
  • 151
  • 195
Ricky
  • 10,485
  • 6
  • 36
  • 49

2 Answers2

80

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:-

  1. Getting Location Updates for iOS 7 and 8 when the App is Killed/Terminated/Suspended
  2. Source Code on GitHub - Get the Location Updates Even when the iOS mobile apps is Suspended/Terminated/Killed
Ricky
  • 10,485
  • 6
  • 36
  • 49
  • 1
    "You must create a new locationManager instance when you receive the key" - sounds a bit confusing, do you mean exactly "NEW locationManager instance" ? I have a shared instance of locationManager in my project - can I just reuse it ? – n0_quarter Feb 24 '15 at 09:24
  • 7
    Good question. When the app is suspended, the shared locationManager that you have created earlier will be flushed out from the memory as well. How do you reuse an instance that does not exist in the memory? So, creating a new instance is the only way. – Ricky Feb 24 '15 at 13:00
  • Hi Ricky, great answer. Just one question: Can the same method be applied to the standard location manager as opposed to just the significant change location manager? – Pacemaker May 31 '15 at 15:29
  • 2
    Is it possible to save locations and logs with core data when app is terminated or only in .plist file? – gellezzz Oct 27 '15 at 20:45
  • Does this work when the distance filter is relatively small? Say 50 meters? – Eggman87 Mar 24 '16 at 22:18
  • @Ricky... please see this....http://stackoverflow.com/questions/37338466/sending-current-location-to-server-in-background-as-well-as-in-running-app-using – Suraj Sukale May 21 '16 at 06:31
  • @Ricky Im not getting Accurate location if I use "startMonitoringSignificantLocationChanges" Where as getting Accurate one if I use "startUpdatingLocation". – siva krishna Jun 01 '16 at 07:22
  • @Ricky, I want to use both "startUpdatingLocation" "startMonitoringSignificantLocationChanges". Will this work in suspended state. – siva krishna Jun 01 '16 at 07:36
  • 1
    @Ricky, thanks for the explanation. This part is poorly documented. However, I don't understand why you stop and start again significant location changes when the app enters background, and why do you recreate it when the app becomes active again. Is it mandatory, a just a double precaution? – Martin Nov 22 '16 at 09:31
  • Hi, I have tried but its not working, I tried with iOS 11, is this working only in iOS 7&8 or 7 and above lates version. – Vinayak Aug 27 '19 at 05:18
0
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];
Jayesh Miruliya
  • 3,279
  • 2
  • 25
  • 22