Mike Mike - 24 days ago 14
iOS Question

Location and accelerometer updates in the background under iOS 10

My app collects location and accelerometer information, and continues to do so in the background if the user requests it. The accelerometer information is collected at about 100 Hz, and it is critical that it be collected at a high rate. The app has worked fine under older versions of iOS, but is failing under iOS 10. I'm looking for a way to continue collecting accelerometer information while in the background.

The method used is similar to that in Receive accelerometer updates in background using CoreMotion framework. I start the location manager:

latitude = 0.0;
longitude = 0.0;
altitude = 0.0;
horizontalAccuracy = -1.0;
verticalAccuracy = -1.0;
if (locationManager == nil && [CLLocationManager locationServicesEnabled]) {
self.locationManager = [[CLLocationManager alloc] init];

CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
if (status == kCLAuthorizationStatusNotDetermined) {
[locationManager requestWhenInUseAuthorization];
}

locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.pausesLocationUpdatesAutomatically = NO;
[locationManager startUpdatingLocation];
}


I implement locationManager:didUpdateLocations:

- (void) locationManager: (CLLocationManager *) manager didUpdateLocations: (NSArray *) locations {
printf("locationManager:didUpdateLocations:\n");
CLLocation *location = locations.lastObject;
latitude = location.coordinate.latitude;
longitude = location.coordinate.longitude;
altitude = location.altitude;
horizontalAccuracy = location.horizontalAccuracy;
verticalAccuracy = location.verticalAccuracy;
}


I start the motion manager:

motionManager = [[CMMotionManager alloc] init];
motionManager.accelerometerUpdateInterval = 1.f/trialFrequency;
[[NSOperationQueue mainQueue] setMaxConcurrentOperationCount: 10];
[motionManager startAccelerometerUpdatesToQueue: [NSOperationQueue mainQueue]
withHandler: ^(CMAccelerometerData *accelerometerData, NSError *error) {
// Flag any error.
if (error) {
NSLog(@"error getting accelerometer update: %@", error);
}
<<<process data>>>
}
];


TARGETS, Capabilities, Background Modes, Location updates is checked.

Under iOS 9 and previous, the motion information is recorded at a rate of around 100 Hz with no problem, but under iOS 10, the motion information stops as soon as the app enters the background.

Is there any way to get the motion information to continue in the background under iOS 10?

Answer

Beginning with iOS 9, there is a new call required to enable background processing of location events. It can be used to turn background processing on and off, but defaults to off, so it must be set manually to restore background processing in iOS 8 and prior code.

Add this line when setting up the location manager to allow background processing:

    locationManager.allowsBackgroundLocationUpdates = YES;