24

I am trying to make an app to track the user GPS all the time, this app is a kind of car GPS tracker to get the location of driver all the time and send it to server.

I have tried to add "location updates" to the "background modes" but the app will automatically suspends after 10 mins when going into background.

Is there a way to make this app run all the time and get the GPS location?

Ronan Boiteau
  • 9,608
  • 6
  • 34
  • 56
TMMDev
  • 473
  • 1
  • 5
  • 10

4 Answers4

17

You have two options here:

1) Regular location tracking.
This type of tracking works with kCLAuthorizationStatusAuthorizedWhenInUse and kCLAuthorizationStatusAuthorizedAlways authorizations. When CLLocationManager started tracking location once it will receive location updates in delegate method locationManager:didUpdateLocations:. App can go to suspended state, but when location manager receive new location app goes to background state and handles new location in delegate method. How to setup location manager:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.locationManager = [[CLLocationManager alloc] init];

    // Setup location tracker accuracy
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;

    // Distance filter
    self.locationManager.distanceFilter = 50.f;

    // Assign location tracker delegate
    self.locationManager.delegate = self;

    // This setup pauses location manager if location wasn't changed
    [self.locationManager setPausesLocationUpdatesAutomatically:YES];

    // For iOS9 we have to call this method if we want to receive location updates in background mode
    if([self.locationManager respondsToSelector:@selector(allowsBackgroundLocationUpdates)]){
        [self.locationManager setAllowsBackgroundLocationUpdates:YES];
    }

    [self.locationManager startUpdatingLocation];
}


2) Signification location changes tracking.
This type of tracking works only with kCLAuthorizationStatusAuthorizedAlways authorization. It receives new location only each 500 meters, so distance filter and desiredAccuracy don't work here. App can go to suspended state, and even can be terminated by system, but when location updates app goes to background state and receives location in delegate method locationManager:didUpdateLocations:.
If app was terminated by system, it will be relaunched in background with UIApplicationLaunchOptionsLocationKey key in launch options in didFinishLaunchingWithOptions app delegate method. How to setup this type on tracking:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.locationManager = [[CLLocationManager alloc] init];

    // Assign location tracker delegate
    self.locationManager.delegate = self;

    // For iOS9 we have to call this method if we want to receive location updates in background mode
    if([self.locationManager respondsToSelector:@selector(allowsBackgroundLocationUpdates)]){
        [self.locationManager setAllowsBackgroundLocationUpdates:YES];
    }

    [self.locationManager startMonitoringSignificantLocationChanges];
}


You should notice that both of these methods does not guarantee that your application does not go to suspended state.
Also, if app was terminated by user (for example from app switcher by swipe) location tracking in background will not work.


UPDATE (corresponding to comments)

Here is my code examples that work for me:
For Regular tracking. Run the example, provide access to user location, tap Start button to start location updates. To test locations in simulator choose in simulator menu Debug > Location > Freeway Drive. Now you can push app to background by home button (Command+Shift+H). Leave simulator for more than 10 minutes, and all this time app will receive locations. When you return to app you will see red pins on the map.
For Significant changes. Run the app and test by the same way as for previous example.
Monitoring Significant changes can be started only by method [self.locationManager startMonitoringSignificantLocationChanges];

UPDATE (iOS 11)

Changes to location tracking in iOS 11

iOS 11 also makes some major changes to existing APIs. One of the affected areas is location tracking. If your app only uses location while the app is in the foreground, as most apps do, you might not have to change anything at all; however, if it’s one of those apps that continuously track user’s location throughout the day, you should probably book some time this summer for making some changes in how you do the tracking and testing possible usage scenarios.

follow this link: https://mackuba.eu/2017/07/13/changes-to-location-tracking-in-ios-11/

BuLB JoBs
  • 841
  • 4
  • 20
shpasta
  • 1,913
  • 15
  • 21
  • Thank you for the answer, for option 1, you said that when new location is received, the state goes from suspended to background, i have been testing for days and this case never happened with me, the app comes back to life again ONLY when running the app manually, and then suspends after 10 mins, why??? – TMMDev Feb 20 '16 at 06:39
  • For option 2, is there a way to make startMonitoringSignificantLocationChanges runs the [self.locationManager startUpdatingLocation] somehow? this will make it at least run every 500 meters at least – TMMDev Feb 20 '16 at 06:41
  • 1
    Updated answer for your comments. I don't see your code, so I provided links to my code examples here for both options 1 and 2. – shpasta Feb 20 '16 at 08:42
  • 1
    I have marked your post as answer because you wrote exactly what i was looking for "You should notice that both of these methods does not guarantee that your application does not go to suspended state" – TMMDev Feb 21 '16 at 03:08
  • "App can go to suspended state, but when location manager receive new location app goes to background state" this doesn't seem to be the case. My app stopped sending location update after it got suspended (which typically happens after a few hours/days). – Avery235 Dec 28 '18 at 06:36
  • @shpasta Please have a look https://github.com/IMHitesh/HSLocationManager – Hitesh Surani Jun 04 '19 at 07:19
7

I am sure it is useful for the author because the question was asked in Feb 2016 and I am giving an answer in June 2019. This answer maybe is useful for other users.

Recently, I was working with the same requirement. After 2-3 week hard work, I did it. For other users, I create a helper class for it. Which is available in GitHub.

Please use HSLocationManager for your requirement. I have achieved the same requirements in one of my project

Location manager that allows getting background location updates every n seconds with desired location accuracy.

Advantage:

  • OS will never kill our app if the location manager is currently running.

  • Give periodically location update when it required(range is between 2 - 170 seconds (limited by max allowed background task time))

  • Customizable location accuracy and time period.

  • Low memory consumption(Singleton class)

Hitesh Surani
  • 12,733
  • 6
  • 54
  • 65
  • But this does not track location in killed/suspended states. – Jabbar Sep 24 '19 at 07:20
  • It only works for foreground and background mode(I Guaranteed your app will never kill by the OS). We all know tracking is not possible in kill state due to apple limitation. To achieve tracking in kill state you need to implement significant location update. Even by using significant location update continues tracking is not possible in kill state. To overcome this limitation you can go with Apple PushKit but it is a not standard way to do that and also sometime you will face rejection from reviewer due to this so keep it in mind. – Hitesh Surani Sep 24 '19 at 07:34
  • Can you recommend any good tutorial on PushKit to track location even when the app is killed/suspended? – Jabbar Sep 24 '19 at 08:23
  • This for iOS: https://medium.com/ios-expert-series-or-interview-series/voip-push-notifications-using-ios-pushkit-5bc4a8f4d587 and also you need a back-end support – Hitesh Surani Sep 24 '19 at 09:36
3

In reply to comment 1 in the solution (I can't comment anywhere yet): you didn't seem to solve the problem as your app gets suspended and doesn't update the location any more after 10 minutes.

I had the same issue: I had set setAllowsBackgroundLocationUpdates to YES, and I had the NSLocationAlwaysUsageDescription key in my Info.plist, but my App also used to stop tracking location after 10 minutes.

I solved it by adding both NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription to the Info.plist file so it looks like this:

    <key>NSLocationAlwaysUsageDescription</key>
    <string>This app needs to use your location</string>

    <key>NSLocationWhenInUseUsageDescription</key>
    <string>This app needs to use your location</string>
danywarner
  • 928
  • 2
  • 15
  • 28
3

set it.it take power of battery but your application run in Background.OS does not Suspend your App

[self.locationManager setPausesLocationUpdatesAutomatically:NO];
Uma Madhavi
  • 4,851
  • 5
  • 38
  • 73