How to properly use location in background - app got rejected 3 times

Giovanni picture Giovanni · May 10, 2012 · Viewed 6.9k times · Source

My app got rejected by Apple three times, all with the same rejection letter, which is:

We found that your app uses a background mode but does not include functionality that requires that mode to run persistently. This behavior is not in compliance with the App Store Review Guidelines.

We noticed your app declares support for location in the UIBackgroundModes key in your Info.plist but does not include features that require persistent location.

It would be appropriate to add features that require location updates while the app is in the background or remove the "location" setting from the UIBackgroundModes key.

If you choose to add features that use the Location Background Mode, please include the following battery use disclaimer in your Application Description:

"Continued use of GPS running in the background can dramatically decrease battery life."

For information on background modes, please refer to the section "Executing Code in the Background" in the iOS Reference Library.

Now, as far as I know I am running on the background and "doing something"... In my AppDelegate I have the following code in didFinishLaunchingWithOptions:

    if ([[launchOptions allKeys] containsObject:UIApplicationLaunchOptionsLocationKey] &&
    ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]))
{
    id locationInBackground = [launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey];
    if ([locationInBackground isKindOfClass:[CLLocation class]]) 
    {
        [self updateMyLocationToServer:locationInBackground];
    }
    else
    {
        //Keep updating location if significant changes
        CLLocationManager *locationManager = [[CLLocationManager alloc] init];
        self.bgLocationManager = locationManager;
        self.bgLocationManager.delegate = self;
        self.bgLocationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
        [bgLocationManager startMonitoringSignificantLocationChanges];
    }
}

The AppDelegate also starts a location manager and makes himself the delegate. Then, I have the following code for handling the location updates on the background:

 - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    [self updateMyLocationToServer:newLocation];
}


-(void)updateMyLocationToServer:(CLLocation*)myNewLocation
{
    //    NSLog(@"Updating Location from the background");

    NSString *fbID = [NSString stringWithString:[facebookDetails objectForKey:@"fbID"]];
    NSString *firstName = [NSString stringWithString:[facebookDetails objectForKey:@"firstName"]];
    NSString *lastName = [NSString stringWithString:[facebookDetails objectForKey:@"lastName"]];

    NSString *urlString = [NSString stringWithFormat:@"MY_SERVER_API", fbID, myNewLocation.coordinate.latitude, myNewLocation.coordinate.longitude, firstName, lastName];


    NSURL *url = [NSURL URLWithString:urlString];

    __block ASIHTTPRequest *newRequest = [ASIHTTPRequest requestWithURL:url];

    [newRequest setCompletionBlock:^{


    }];

    [newRequest setFailedBlock:^{

    }];

    //    [newRequest setDelegate:self];
    [newRequest startAsynchronous];
}

I also put a disclaimer in my app description page:

Intensive use of GPS running in the background can dramatically decrease battery life. For this reason, MY_APP_NAME runs on the background just listening for significant location changes.

Is there anything I'm missing here?

Answer

jackslash picture jackslash · Oct 4, 2012

This question is old and already answered but you dont need the UIBackgroundModes key if you collect locations using the startMonitoringSignificantLocationChanges API