Ive written a GPS app for iOS 10 a while back. Ive gotten it to the point where its stable and working as expected and now I want to go after battery saving techniques. The app sends GPS locations every 5 minutes right now but I could be flexible on how often I send the GPS locations, as long as they aren't sent too infrequently. My app requires 'best' or '10m' GPS location setting as well which I know uses a lot of power, but I cannot use the 3km setting per my requirements (which I know would save more power).
From what I gather and reading the docs and playing with code to make it work, it seems that there are 2 techniques:
- set pausesLocationUpdatesAutomatically = YES in combination with UNLocationNotificationTrigger
- allowDeferredLocationUpdatesUntilTraveled:timeout:
Number 2 apparently does not work at all based on this article in iOS 10 and 11.
Number 1 gives me sporadic results when I log it to my server. Sometimes it works, sometimes Ill get a single GPS point in the middle of nowhere (without seeing a pause or resume log message) and then later it starts to work, other times it does not seem to work at all.
Sometimes Ill see 2 pauses back to back within the same second.
Other times Ive seen it resume locations back to back (minutes apart) without ever seeing the pause log message. And other times I see the pause log message and minutes later (or a while later) resume GPS sends without seeing a 'resume' log message.
- (void) setGPSBatterySavingTrigger
{
if (IS_IOS_10_OR_LATER && ([g_prefs getGPSAuthStatus] == kCLAuthorizationStatusAuthorizedAlways))
{
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(g_locMgr.getLastLocation.latitude, g_locMgr.getLastLocation.longitude);
CLRegion *region = nil;
float radius_m = 150.0;
region = [[CLCircularRegion alloc] initWithCenter:center radius:radius_m identifier:@"pauseLocationsCenter"];
if (!region) {
[logger log:TSERVLOG :@"pause radius failed at radius <%f>", radius_m];
return;
}
region.notifyOnEntry = NO;
region.notifyOnExit = YES;
UNLocationNotificationTrigger *trigger = [UNLocationNotificationTrigger
triggerWithRegion:region repeats:NO];
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = PROG_NAME;
content.body = @"GPS Restarted";
//content.sound = [UNNotificationSound soundNamed:nil];
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"GPSTextNotify" content:content trigger:trigger];
[[UNUserNotificationCenter currentNotificationCenter] removeAllPendingNotificationRequests];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError *error)
{
if (error.code)
{
[logger log:TSERVLOG :@"UNUserNotificationCenter addRequest FAILED <%@>", error.localizedDescription];
}
}];
}
}
- (void) locationManagerDidPauseLocationUpdates:(CLLocationManager *)manager
{
[logger log:TSERVLOG :@"===== JME GPS PauseLocationUpdates at <%@> <%f, %f>",
[mydate getCurrentDateTimeStr], self.getLastLocation.latitude, self.getLastLocation.longitude];
[self setGPSBatterySavingTrigger];
}
- (void) locationManagerDidResumeLocationUpdates:(CLLocationManager *)manager
{
[logger log:TSERVLOG :@"===== GPS ResumeLocationUpdates at <%@> <%f, %f>",
[mydate getCurrentDateTimeStr], self.getLastLocation.latitude, self.getLastLocation.longitude];
}
Bottom line questions:
- Has anyone been able to use either of these to get battery saving + GPS working reliably in iOS 10+?
- If not, what combination of things did you do to get it to work 100% of the time while saving battery life?
- Am I missing another technique that does work? (NOTE my requirements cannot use the 3km setting)
Thank you for your input!