Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS periodic background location updates which depends not only on significant location change

I have an app which must report user location even if it backgrounded or even killed (terminated). The issue is that the app should report the location not rare than 1 hour interval.

I'm using significant location change (SLC) to track all movements which is quite enough when user is on the go but once user stops no further updates is raised and the app has no opportunity to submit new location (while user stays in the same area but without SLC).

To cover this case I start to use Background fetches to periodically send updates location in background even without SLC). The issue here is that background fetches used to work quite often (every 20-30 min since I used then in another iOS 7.x app) but now with iOS8 / iOS9 I can get it only once a day or so which is not acceptable in my case. I have executed ton of tests, developed simple background fetch app which add a local notification on fetch. No luck to force it to work more often.

Here is my AppDelegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
    [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
    return YES;
}

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{    
    [[UIApplication sharedApplication] cancelAllLocalNotifications];
    UILocalNotification *localNotification = [[UILocalNotification alloc] init];
    NSDate *now = [NSDate date];
    localNotification.fireDate = now;
    localNotification.alertBody = [NSString stringWithFormat:@"Background fetch!"];
    localNotification.soundName = UILocalNotificationDefaultSoundName;
    NSInteger number = [UIApplication sharedApplication].applicationIconBadgeNumber;
    number++;
    localNotification.applicationIconBadgeNumber = number;
    [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];

    completionHandler(UIBackgroundFetchResultNewData);
}

All what is done here is to add local notification on every background fetch. I always finalize the background execution with UIBackgroundFetchResultNewData.

Do you have any suggestions on how to force background fetches to work more often (or prove links that it is not possible any more)? Any alternative solutions to meet my requirement are also welcomed!

like image 401
Alexey Strakh Avatar asked Sep 20 '15 21:09

Alexey Strakh


People also ask

How often does location history update on Iphone?

Significant-change location updates wake the system and your app once every 15 minutes, at minimum, even if no location changes have occurred.

What is background location?

Android 10 features a background access location reminder, which increases transparency into how much access apps have to a device's location and helps users maintain control over such access. In Android 9 and lower, an app can track a device's location while running in the background without the user's knowledge.

How do I change the background location in Swift?

Select your project using the project navigator, then find your app's target and choose the Capabilities tab. You need to enable Background Modes, then check the box marked “Location updates”.


2 Answers

It turned out that background fetches in iOS depend a lot on what you are doing within the handler, especially network activity. Here the list of dependencies which you should consider trying to understand if and how often iOS will execute your fetch:

  • time you spend in handler
  • result (NoData, NewData)
  • error handling (you will be launched less likely if you code crashes
  • timeouts (your code execution could be interrupted by iOS)
  • power usage
  • network activity related to result (you MUST do a network request when saying that you have NewData, otherwise your fetch could be executed next time in a day or so never.

Apps that download small amounts of content quickly, and accurately reflect when they had content available to download, are more likely to receive execution time in the future than apps that take a long time to download their content or that claim content was available but then do not download anything.

The last item turned out to be crucial in my case, because for testing purposes I declared fetches and never tried to download anything. Once I started to use network in the handler, background fetches continue to work as expected every 15-30 minutes.

Apple docs: https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html

like image 59
Alexey Strakh Avatar answered Oct 19 '22 01:10

Alexey Strakh


I worked on a similar project. After trying various solutions, the only way I've found is the solution proposed here: https://github.com/voyage11/Location

Here is the tutorial corresponding to the git: http://mobileoop.com/getting-location-updates-for-ios-7-and-8-when-the-app-is-killedterminatedsuspended

All credits to https://stackoverflow.com/users/1995940/ricky

It's saved me a lot of time!

like image 22
Alban Avatar answered Oct 19 '22 00:10

Alban