20

I'm looking for an open source app or library to track user location in the background. Now I'm trying to do it with CLLocation and background tasks, but accuracy is not enough for my case. Could you explain, how apps, like "moves", "runkeeper", "endmondo", creates my route? Should I use Accelerometer or/and compass to create a route between CLLocation background points?

Some code:

//location manager init
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.delegate = self;


#pragma mark - CLLocationManager Delegate

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {

    if ([self isInBackground]) {
        if (self.locationUpdatedInBackground) {
            bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^{
                [[UIApplication sharedApplication] endBackgroundTask:bgTask];
            }];

            self.locationUpdatedInBackground(newLocation);
            [self endBackgroundTask];
        }
    } else {
        if (self.locationUpdatedInForeground) {
            self.locationUpdatedInForeground(newLocation);
        }
    }
}

UPD: Justed tested my app with next properties

self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.activityType = CLActivityTypeFitness;
self.locationManager.pausesLocationUpdatesAutomatically=NO;

In this case I have about 10 fired events during 1,5 hour trip

madLokesh
  • 1,860
  • 23
  • 49
Alexey Sidorov
  • 846
  • 1
  • 9
  • 17

8 Answers8

7

Use

kCLLocationAccuracyBestForNavigation

check this.

Community
  • 1
  • 1
6

You need to add in your "Info.plist" file the key UIBackgroundModes (array) with the value "location" (app registers for location updates). You can check all background modes here.

djromero
  • 19,551
  • 4
  • 71
  • 68
4

So your app uses location services. Then please read the Location Awareness Programming Guide.

You need to make some changes to your Info.plist:

  • If your app relies on location services to function properly, add location-services to UIRequiredDeviceCapabilities
  • if your app requires GPS hardware, add gps to UIRequiredDeviceCapabilities
  • if you need to run your app longer then 10 minutes in the background, add location to UIBackgroundModes. Then your location manager will deliver locations beyond the 10-minute-limit.
  • you should also set NSLocationUsageDescription (can also be localized)

Getting Location Events in the Background

If your app needs location updates delivered whether the app is in the foreground or background, there are multiple options for doing so. The preferred option is to use the significant location change service to wake your app at appropriate times to handle new events. However, if your app needs to use the standard location service, you can declare your app as needing background location services.

An app should request background location services only if the absence of those services would impair its ability to operate. In addition, any app that requests background location services should use those services to provide a tangible benefit to the user. For example, a turn-by-turn navigation app would be a likely candidate for background location services because of its need to track the user’s position and report when it is time to make the next turn.

Ravi_Parmar
  • 12,319
  • 3
  • 25
  • 36
3

Your problem is the background handler. Remove it and enable gps background mode in plist file. then you should get full power gps all the time.

Set property pausesLocationUpdatesAutomatically=NO

This is new in ios6.

From CLLocationManager:

Allowing the location manager to pause updates can improve battery life on the target device without sacrificing location data. When this property is set to YES, the location manager pauses updates (and powers down the appropriate hardware) at times when the location data is unlikely to change. For example, if the user stops for food while using a navigation app, the location manager might pause updates for a period of time. You can help the determination of when to pause location updates by assigning a value to the activityType property.

The default value of this property is YES.

For analysis add these methods to your LocationManager delegate:

- (void)locationManagerDidPauseLocationUpdates:(CLLocationManager *)manager {
     NSLog(@"locMan: locationManagerDidPauseLocationUpdates");
}

- (void)locationManagerDidResumeLocationUpdates:(CLLocationManager *)manager {
    NSLog(@"locMan: locationManagerDidResumeLocationUpdates");
}
AlexWien
  • 28,470
  • 6
  • 53
  • 83
  • Justed tested my app with next properties `self.locationManager.distanceFilter = kCLDistanceFilterNone; self.locationManager.desiredAccuracy = kCLLocationAccuracyBest; self.locationManager.activityType = CLActivityTypeFitness; self.locationManager.pausesLocationUpdatesAutomatically=NO; ` In this case I have about 10 fired events during 1,5 hour trip. – Alexey Sidorov Jul 05 '13 at 09:19
  • i tested yesterday mine work. try accuracyBestForNavigation. if hat stil does not work try compliling to target ios 5 – AlexWien Jul 06 '13 at 08:57
2

You can set up monitoring location stuff in you VC as below

in viewDidLoad method do as below

CLLocationManager locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;(Accuracy according to your need)
[locationManager startUpdatingLocation];

than you have to overrite below two optional delegate methods of CLLocationManagerDelegate protocol

for iOS6+

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{}

and for iOS 2 to 6

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation

in these methods you will get updated location. use it as you want. every time location updated these method get calls.

Suryakant Sharma
  • 3,852
  • 1
  • 25
  • 47
  • thx for your response, but I`m looking for a solution to track location in the background mode, like "moves", "runkeeper" does. I have tried to use `CLLocation` with `kCLLocationAccuracyBest` in the background mode, but the event fires only evry 500 meters, that is not enough for me. – Alexey Sidorov Jul 04 '13 at 12:40
  • @AlexeySidorov the fix fires nearly evry second, or evry second depening on your speed. read his answer again, does your app work in ios5? – AlexWien Jul 04 '13 at 14:13
  • @AlexWien it works in ios6. The event, in background mode, fires no often than 500 meters, depends on cellular towers. I just tested it. – Alexey Sidorov Jul 04 '13 at 17:47
  • Take a look at https://github.com/sidorov-panda/Record-my-position It works in the same way, and the number of fired events is too small for me – Alexey Sidorov Jul 04 '13 at 17:52
  • @AlexeySidorov I ported my app from ios5 to ios6 last weekend, i will look how it behaves in background mode. – AlexWien Jul 04 '13 at 18:03
1

you don't ask for code. You ask for: "I'm looking for an open source app or library"

It may help you to visit this website.

hope it helps you,

Also a tutorial.

Jagat Dave
  • 1,643
  • 3
  • 23
  • 30
  • I`m looking for an app or for explanation of method, how apps like "moves" does the same – Alexey Sidorov Jul 17 '13 at 08:31
  • It's a very nice app i use it too. You can make this coding in html5 and using the cordova framework to finish you app, and add to android and apple store. – Marc Millet Jul 17 '13 at 08:58
  • I need to track walking in background, the accuracy of that app is not enough for me – Alexey Sidorov Jul 17 '13 at 10:39
  • RunKeeper app it's similar app like "moves" you can have the source code on github https://github.com/brierwood/RunKeeper-iOS – Marc Millet Jul 17 '13 at 12:59
  • Thx for your link, it was helpful, but The RunKeeper will automatically create a correctly timestamped path for you if you post notifications. RunKeeperPathPoint *point = [[[RunKeeperPathPoint alloc] initWithLocation:newLocation ofType:kRKGPSPoint] autorelease]; [[NSNotificationCenter defaultCenter] postNotificationName:kRunKeeperNewPointNotification object:point]; – Alexey Sidorov Jul 17 '13 at 14:25
  • Alexey i'm not an ios pro coder, and i can't help you with the code, my skills are html5 & css3, my ios knowledge is on medium level. – Marc Millet Jul 17 '13 at 18:46
0

Here was my solution to this,

Declare the instance variable:

CLLocationManager *locationManager;

Be sure to include the delegate

<CLLocationManagerDelegate>

In viewDidLoad:

locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move, location is updated
locationManager.desiredAccuracy = kCLLocationAccuracyBest; // get best current locaton coords
locationManager.headingFilter = 1;
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];

Implement the delegate method:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    int degrees = newLocation.coordinate.latitude;
    double decimal = fabs(newLocation.coordinate.latitude - degrees);
    int minutes = decimal * 60;
    double seconds = decimal * 3600 - minutes * 60;
    NSString *lat = [NSString stringWithFormat:@"%d° %d' %1.4f\"",
                     degrees, minutes, seconds];
    NSLog(@" Current Latitude : %@",lat);
    latitudeLocation.text = lat;
    degrees = newLocation.coordinate.longitude;
    decimal = fabs(newLocation.coordinate.longitude - degrees);
    minutes = decimal * 60;
    seconds = decimal * 3600 - minutes * 60;
    NSString *longt = [NSString stringWithFormat:@"%d° %d' %1.4f\"",
                       degrees, minutes, seconds];
    NSLog(@" Current Longitude : %@",longt);
    longitudeLocation.text = longt;
}
jsetting32
  • 1,632
  • 2
  • 20
  • 45
  • The didUpdateToLocation method has been deprecated and replaced with didUpdateLocations: in iOS6. – Kheldar Dec 01 '14 at 10:42
-3

Disclaimer: I work for Cintric

We also wanted to be able to accurately track a users location in background (even after the app had been killed). We spent a long time solving the problem, especially focusing on battery drain.

We posted a great blog post on how we solved it. And also are providing a drag and drop SDK solution. It's not open source but you can integrate it for free:

You can download the .framework file, drag it into your project and initialize with one line of code: [CintricFind initWithApiKey:@"YOUR_API_KEY_HERE" andSecret:@"YOUR_SECRET_HERE"];

You can get an API key for free. There are docs explaining everything here.

Jagat Dave
  • 1,643
  • 3
  • 23
  • 30
Joel Green
  • 920
  • 9
  • 18