0

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:

  1. set pausesLocationUpdatesAutomatically = YES in combination with UNLocationNotificationTrigger
  2. 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:

  1. Has anyone been able to use either of these to get battery saving + GPS working reliably in iOS 10+?
  2. If not, what combination of things did you do to get it to work 100% of the time while saving battery life?
  3. Am I missing another technique that does work? (NOTE my requirements cannot use the 3km setting)

Thank you for your input!

Tim
  • 647
  • 1
  • 10
  • 21
  • You only need to update the location if the user changes location are "drastic" or of interest for you. Most part of the battery usage comes from calling your servers, especially on mobile data. https://developer.apple.com/documentation/corelocation/cllocationmanager/1423531-startmonitoringsignificantlocati , have a look through this guide too. https://developer.apple.com/library/content/documentation/Performance/Conceptual/EnergyGuide-iOS/LocationBestPractices.html –  Sep 04 '17 at 20:53
  • "If GPS-level accuracy isn’t critical for your app, you don’t need continuous tracking, and region or visit monitoring isn’t more appropriate for your app, you can use the significant-change location service instead of the standard one." –  Sep 04 '17 at 21:00

0 Answers0