2

I'm building an application that checks if the user is near a store of my client, if it does, it sends him a notification.

I want the app to check it in the background as well.

I've added this lines to my info.plist file:

image

and here is my code:

AppDelegate.m:

-(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self configureLocationManager];
[self.locationManager startUpdatingLocation];

return YES;
}
-(void)configureLocationManager
{
    //Initializing locationManager
    self.locationManager=[[CLLocationManager alloc] init];
    //setting "locationManager"'s(CLLocationManager) delegate to "self"
    self.locationManager.delegate=self.monitorLocationVC;
    //Setting "locationManager"'s(CLLocationManager)'s distance filter to none
    //self.locationManager.distanceFilter=kCLDistanceFilterNone;
    //Setting "locationManager"'s(CLLocationManager)'s activityType to navigation
    self.locationManager.activityType=CLActivityTypeAutomotiveNavigation;
    //setting "locationManager"'s(CLLocationManager) desiredAccuracy to "best"
    self.locationManager.desiredAccuracy=kCLLocationAccuracyBestForNavigation;
    //If OS version is 9 or above - setting "allowsBackgroundLocationUpdates" to YES
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) {
        self.locationManager.allowsBackgroundLocationUpdates = YES;
    }
}

MonitorLocationViewController.m:

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
    [self checkIfNearStore]; //Not being called in background
}

-(void)checkIfNearStore
{
    for (Store *currentStore in self.allStores) {
        if ([currentStore.circularRegion containsCoordinate:self.locationManager.location.coordinate]&&currentStore.alreadySendNotification==NO) {
            NSLog(@"Entered: %@",[[self storeForRegion:currentStore.circularRegion] address]);
            currentStore.alreadySendNotification=YES;
            [self.storesAlreadySentNotifications addObject:currentStore];
        }
    }

    for (Store *currentStore in self.storesAlreadySentNotifications) {
        if (![currentStore.circularRegion containsCoordinate:self.locationManager.location.coordinate]) {
            currentStore.alreadySendNotification=NO;
        }
    }
}

Anybody have an idea? Thanks!

FS.O
  • 403
  • 6
  • 24
  • Idea about what? Do you get authorisation from the user to track their location? – trojanfoe Feb 03 '16 at 08:27
  • @trojanfoe Yes, the user has allowed "always authorization" for locationManager. – FS.O Feb 03 '16 at 08:30
  • Did you enabled the background modes in project capabilities as location? As well in your info.plist also. – RJV Kumar Feb 03 '16 at 08:54
  • @RJVKumar Maybe no, can you please how can I do that? – FS.O Feb 03 '16 at 08:56
  • select your project target (name) in Xcode. then click capabilities tab->background modes-> location updates..enable this. – RJV Kumar Feb 03 '16 at 08:59
  • And add a key "Required background modes" in your info.plst. Select a values as location – RJV Kumar Feb 03 '16 at 09:00
  • @RJVKumar Yes, I have already done this, any other idea maybe? – FS.O Feb 03 '16 at 09:01
  • @FS.O sorry...I didn't work on background updates. – RJV Kumar Feb 03 '16 at 10:20
  • try setting `pausesLocationUpdatesAutomatically` property of `CLLocationManager` to `NO` – stonycis Feb 03 '16 at 10:23
  • @stonycis Still not working, when I kill the app from the multitasking xcode stops the run of the app – FS.O Feb 03 '16 at 10:30
  • try logging each new location you get `didUpdateLocations` into a file, run the app, unplug the phone from your computer, go for a walk and then check that file to see if there's something in it. Also, turn on energy diagnostics in your phone and analyse if the gps was used during your walk... or schedule a local notification every time a new location is received. that way you'll know for sure if it works or not. – stonycis Feb 03 '16 at 10:34
  • @stonycis checked it now, it don't – FS.O Feb 03 '16 at 10:43
  • @stonycis I've just returned from another walk and it is working it the background, but not all the time. It sometimes send me the notification for didUpdateLocations but not often. Do you know why? – FS.O Feb 03 '16 at 12:30
  • how often do you receive location updates? – stonycis Feb 03 '16 at 12:31
  • @stonycis when the app open - every second. On background - I get few notifications every 15-20 minutes or something like that. – FS.O Feb 03 '16 at 12:34
  • here's an idea...you actually don't need to monitor location in background for your purpose...it drains the battery very fast and users won't be ok with it...as an alternative, why don't you use region monitoring (geofencing) to alert the user when he/she is near a store? – stonycis Feb 03 '16 at 12:36
  • @stonycis I've tried it but it don't work for me (I have more than 20 stores and when I replace the monitored regions it don't send a notification), I've tried to fix it for a week but it don't work, maybe this option is not for this kind of app. – FS.O Feb 03 '16 at 12:40
  • I'm using geofencing for about 3000 locations in an app that I have...you have to tweak it a bit to make it work, apart from the traditional monitoring...you have to enable significant location changes and reload regions every time an SLC is fired...also, reload regions when a fence border is crossed..and lastly, when you get an SLC check to see if the user is inside a region..you also have to take into account that if the user is inside a region when you start monitoring it, you won't be notified for that region until you go out and in again. (unfortunately I can't post the code I use - NDA). – stonycis Feb 03 '16 at 12:44
  • @stonycis Would it be possible for you to share with me your code, I've tried to do what you done for a whole week and it didn't work. Can we continue this conversation via email? :) – FS.O Feb 03 '16 at 12:50

2 Answers2

1

Background Location Updates

I recommend you give a close re-read of the discussion related to the startMonitoringSignificantLocationChanges method (You must use this method to resolve the issue). Note that you can force new updates by calling stopMonitoringSignificantLocationChanges and then calling the start... method again. You'll also need to monitor the timestamps in your locationManager:didUpdateLocations method.

Apple details the steps that you need to get the updates when the app is in the background. Basically you will have to intercept a key in your app delegate method. This SO question has Sample CODE.

But before you jump to the code, please review the discussion as recommended since it will give you a much clearer idea of how to master this behavior. As always you will also always want to monitor the failure delegate method mentioned in the discussion.

Apple Documentation

significantlocationchanges

Nota Bene

Apple has posted this very important note on limitations for how often location updates are sent to the device. For battery conservation they try to limit the number of updates until the device moves 500 meters. Your testing should consider these limits.

500meters

Resources

For more complementary info please note the following answers to these SO questions:

#1 #2

Community
  • 1
  • 1
Tommie C.
  • 12,895
  • 5
  • 82
  • 100
  • 1
    I need the real-time location, not every 500m so I can't use significantLocationChanges, I need the regular monitoring. – FS.O Feb 03 '16 at 12:28
0

Unfortunately, I can't post the code I use for geofencing due to NDA, but this article could help you achieve what you want: https://corgitoergosum.net/2013/01/12/geo-fencing-in-timetraveler-v2-part-i-of-3/

stonycis
  • 466
  • 4
  • 16
  • 1
    you enable SLC and every time a new location is received in `- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations` you reload the regions – stonycis Feb 03 '16 at 12:57
  • 1
    also, you may wanna do the same for `-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region` – stonycis Feb 03 '16 at 12:57
  • is the tutorial covers it? – FS.O Feb 03 '16 at 12:58
  • BTW, I need the real-time location, not every 500m so I can't use significantLocationChanges, I need the regular monitoring, or maybe I'm wrong? – FS.O Feb 03 '16 at 12:59
  • that's what I'm trying to tell you. You don't need real time monitoring. SLC is enough to reload the regions...and if it's not, supposing you have more than 20 regions in a 500m radius, reload the regions every time one of the current fences is triggered. – stonycis Feb 03 '16 at 13:01
  • this is not 100% accurate, but using real-time location updates with the purpose to alert users when they are near a place will most likely bring you a rejection from Apple. I had a discussion with their engineers and they strongly recommend to use region monitoring for this kind of stuff – stonycis Feb 03 '16 at 13:04
  • I tried to do something tricky, to update location one per minute when the user is in background, to conserve battery and have accuracy, and alert the user when he is near a location...and Apple rejected the app telling me that the behaviour I want should be reached using region monitoring, not using background location updates. – stonycis Feb 03 '16 at 13:07
  • read the article...it covers a lot of good info on geofencing. – stonycis Feb 03 '16 at 13:07
  • OK, I'll take a look. Thanks – FS.O Feb 03 '16 at 13:08
  • also, here tells you something about how to monitor more than 20 regions: http://www.plotprojects.com/how-to-monitor-more-than-20-regions-in-your-ios-app/ – stonycis Feb 03 '16 at 13:08