My app needs to get the user's location when app is active and when it's inactive and killed. When the user's location is near to a store the app has to send a local notification.
I'm not sure what exactly is happening, but I'm not able to make my app get the location in the background and wakes it up when is killed.
I have a location manager (singleton, used for boths cases whenInUse and Always), and I have both NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription defined in .plist
What I'm doing is:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//The app has been killed/terminated (not in background) by iOS or the user.
if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]){
_locationManager = [CoreLocationManager sharedInstance];
_locationManager.isAppActive = NO;
_locationManager.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
_locationManager.locationManager.activityType = CLActivityTypeOtherNavigation;
if ([_locationManager.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
[_locationManager.locationManager requestAlwaysAuthorization];
}
[_locationManager addLocationManagerDelegate:self];
}
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
if (_locationManager.locationManager){
_locationManager.isAppActive = YES;
[_locationManager.locationManager stopMonitoringSignificantLocationChanges];
}
_locationManager = [CoreLocationManager sharedInstance];
if ([_locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
[_locationManager.locationManager requestAlwaysAuthorization];
}
if ([_locationManager.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
[_locationManager.locationManager requestWhenInUseAuthorization];
}
[_locationManager addLocationManagerDelegate:self];
[_locationManager.locationManager startUpdatingLocation];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
_locationManager.isAppActive = NO;
if (_locationManager.locationManager){
[_locationManager.locationManager stopUpdatingLocation];
[_locationManager.locationManager stopMonitoringSignificantLocationChanges];
}
if ([_locationManager.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
[_locationManager.locationManager requestAlwaysAuthorization];
}
[_locationManager.locationManager startMonitoringSignificantLocationChanges];
}
Do I make something wrong? I'm not sure if it's strictly necessary to use geofencing, but for the things I've read with startMonitoringSignificantLocationChanges is enough.
To get a location in the background, use the following code. It will make your app run in the background for a long time by restarting the background task everytime.
To use this, you need to turn on Background Mode in Capabilities in project settings with Background Fetch and Location Updates turned on.