Periodic iOS Background Location Updates

Periodic iOS background location updates

It seems that stopUpdatingLocation is what triggers the background watchdog timer, so I replaced it in didUpdateLocation with:

[self.locationManager setDesiredAccuracy:kCLLocationAccuracyThreeKilometers];
[self.locationManager setDistanceFilter:99999];

which appears to effectively power down the GPS. The selector for the background NSTimer then becomes:

- (void) changeAccuracy {
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager setDistanceFilter:kCLDistanceFilterNone];
}

All I'm doing is periodically toggling the accuracy to get a high-accuracy coordinate every few minutes and because the locationManager hasn't been stopped, backgroundTimeRemaining stays at its maximum value. This reduced battery consumption from ~10% per hour (with constant kCLLocationAccuracyBest in the background) to ~2% per hour on my device.

continuous iOS location updates in background

You have to add this in your plist :

<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>

add this

locationManager.allowsBackgroundLocationUpdates = true

Background Location Updates

@onurgenes, If you add a real code from your project, first of all, how you can start any location updates from here?

    if let _ = launchOptions?[.location] {
locationManager = LocationManager()
locationManager?.delegate = self
locationManager?.getCurrentLocation()
return true
}

When app start at for the first time launchOptions will be nil, and your LocationManager() even not started, so your any location monitoring and updates will not work (maybe you have the some code at app.start() but now it looks like an error).

The second thing - at your sample, you are using bought of locating monitoring:

    locationManager.startUpdatingLocation()
locationManager.startMonitoringSignificantLocationChanges()

so here your location manager handles only significantLocationChanges(). If you want to use both of them - you should toggle it (at didBecomeActiveNotification and didEnterBackgroundNotification) or create different instances of the location manager as Apple recommend.

The third - your problem. Let's look for this part more detailed:

locationManager = LocationManager()
locationManager?.delegate = self
locationManager?.getCurrentLocation()

As I mention up - at LocationManager() you start monitoring location:

locationManager.startUpdatingLocation()
locationManager.startMonitoringSignificantLocationChanges()

and this is what you need - significant location changes. But after you call getCurrentLocation() with locationManager.startUpdatingLocation() so you 'rewrite' your monitoring, and that's the reason why you did not get any updates from it.

Also, take in mind:

  1. Significant locations deliver updates only when there has been a
    significant change in the device’s location, (experimentally
    established 500 meters or more)
  2. Significant locations very inaccurate (for me sometimes it up to 900 meters). Very often significant location use just for wake up an application and restart
    location service.
  3. After your app wake up from location changes
    notification, you are given a small amount of time (around 10
    seconds), so if you need more time to send location to the server
    you should request more time with
    beginBackgroundTask(withName:expirationHandler:)

Hope my answer was helpful. Happy coding!

ios - background location getting and sending periodically, silent push (Flutter)

For getting location updates when the app is active, in background or
killed

I have used this package (background_locator) and it works as expected, you could also specify your own intervals as to when you want to receive the location updates (in your case 15 minutes)

You can check the example folder and documentation on the usage of the package

background_locator

How much time update location in background mode

If you have background location updates enabled and "always" location permission and you have enabled location updates prior to your app entering the background then your app will continue to receive location updates indefinitely.

You only have a few seconds to process each update, but that should be plenty of time to send a short transaction to your server.

Best way to use background location updates in iOS (Swift)

that sends the user's location via API every 3 or 5 minutes, while the
app is backgrounded

Does not make much sense. What if user stands in same location for 5 minutes? you will make same location entry in your server multiple times? Isn't it better rather than updating location at certain interval, if you could update your server with user location once user's location changes??

So use locationManager, set its delegates and start updating your server via API when user location changes rather than at regular interval.

I don't know which is the best way to do this, or if it's even
possible because of Apple's strict background rules

Its absolutely possible. All you have to do is to opt for Location Updates capability in Xcode.

Now whats the best way? Its a relative term. This depends on how your app will use the users location info. If you unnecessarily start observing users location, you will unnecessarily drain the users iPhone battery, hence apple will reject your app.

How apple process's app using location update capability?

Its pretty simple. Location updates capability comes with the cost, that if your app observes user location updates accurately in background, it will drain out the device battery. Because its a costly trade off, apple expects you to use this only if its necessary for your app.

For example : If you are making a map app or an app that tracks the users location changes and then later plots on a map or something and lets the user know about his movement (like running apps) its absolutely fine to use location update capability because you are adding value to user.

If you try to think creepy! and try to use the location update just to keep your app alive and do some thing completely unrelated to location update in background app will reject your app. Like few developers try to be over smart and use location updates to keep their app in sync with server or to upload/download files at regular interval or something like that which are no way related to location updates, apple will reject such apps.

So no way to be creepy? And use location updates to do something useful which is not related to location itself?

Yes, you can. Apple is generous enough to allow that. For example : Dropbox uploads your images in background, when you move from one location to another. All it does is, it looks for user location changes, once location changes delegates triggers, creates a upload task with background session and starts uploading files.

How to do that?

You can still use the location manager. All you have to do is to use

locationManager.startMonitoringSignificantLocationChanges()

This will trigger your location delegates only when there is a significant location changes :)

On the other hand, if your app actually makes use of user locations and use

startLocationUpdates()

make sure you dont consume location updates unnecessarily. Make sure u put distance filter properly according to your apps requirements. Dont be greedy and dont waste iOS resources unnecessarily and apple will be happy and will not trouble you :)

Conclusion:

If your app actually makes use of location and adds some value to user (like map app/running apps/travel apps) only then use startLocationUpdates and use distance filters properly (optional, but good to have it).

If you are being creepy always use startMonitoringSignificantLocationChanges else app is bound to get rejected

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

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



Related Topics



Leave a reply



Submit