Search code examples
ioscore-locationbackground-processcore-bluetooth

iOS Location Manager background updates stopped in iOS 10


I have a fitness app that receives location updates and has been working fine in the background since iOS 4. I just noticed that the location updates now stop when the app moves to the background (switching apps or locking the device) in iOS 10. I haven't found any notices of changes to functionality or background privileges; does anyone know what's happening?

My location setup is pretty basic:

if (!self.locationManager) {
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;

    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    self.locationManager.distanceFilter = kCLDistanceFilterNone;

    self.locationManager.activityType = CLActivityTypeFitness;
    self.locationManager.pausesLocationUpdatesAutomatically = TRUE;
}

// request permissions on iOS 8+
if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
    [self.locationManager requestWhenInUseAuthorization];
}

Then this callback receives updates:

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
    DLog(@"didUpdateToLocation");
}

Everything is good when the app is in the foreground. As soon as it moves to the background, this messages appears in the console:

/BuildRoot/Library/Caches/com.apple.xbs/Sources/ExternalAccessory/ExternalAccessory-353.22.1/EAAccessoryManager.m:__52-[EAAccessoryManager _checkForConnectedAccessories:]_block_invoke-785 ending background task

Then updates stop. When I bring the app to the foreground, they resume again.

I'm not directly using EAAccessoryManager and can only guess what it is. I am using the BluetoothLE framework to receive data from heart rate monitors, but when I disable this functionality (stop instantiating a BluetoothLE object) the problem remains.

My UIBackgroundModes were set to location, external-accessory and bluetooth-central because I also have Pebble watch connectivity. I tried adding bluetooth-peripheral but that didn't help. I also have NSLocationWhenInUseUsageDescription and NSBluetoothPeripheralUsageDescription set and those are working.


Solution

  • A new property was added to CLLocationManager in iOS 9 - allowsBackgroundUpdates. This property defaults to false and must be explicitly set to true if you want to receive location updates in the background.

    Apps that were built against the iOS 8 SDK received grandfathered functionality and continued to receive background updates even without setting this property.