Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting location for an iOS app when it is in the background and even killed

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.

like image 546
Stacky Avatar asked May 22 '15 12:05

Stacky


People also ask

What is background fetch in iOS?

The Background Fetch API provides a method for managing downloads that may take a significant amount of time such as movies, audio files, and software.

What does it mean when an app uses your location in the background?

Access to location is considered in the foreground if it happens while the app is open and visible to the user. If the user closes the app, or hits the home button to return to their main screen, then the app's access to location is considered in the background.

How do I get a background location update every n minutes in my iOS application?

You can use an NSTimer to request a location every minute with this method now and don't have to work with startUpdatingLocation and stopUpdatingLocation methods.


1 Answers

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.

- (void)applicationDidEnterBackground:(UIApplication *)application {

    if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]) { //Check if our iOS version supports multitasking I.E iOS 4

        if ([[UIDevice currentDevice] isMultitaskingSupported]) { //Check if device supports mulitasking
            UIApplication *application = [UIApplication sharedApplication]; //Get the shared application instance

            __block UIBackgroundTaskIdentifier background_task; //Create a task object

            background_task = [application beginBackgroundTaskWithExpirationHandler: ^{
                [application endBackgroundTask:background_task]; //Tell the system that we are done with the tasks
                background_task = UIBackgroundTaskInvalid; //Set the task to be invalid
                //System will be shutting down the app at any point in time now
            }];
        }
    }
}
like image 120
Utsav Parikh Avatar answered Oct 26 '22 23:10

Utsav Parikh