Update Location in Background

Update location in Background

Couple of things to be changed.

Step 1:

Make sure you have enabled location updates background mode in capabilities section of your project as shown below

Sample Image

Step 2:

And when I'm killing the app location update against stoped.

Quoting from apple docs

If you start this service and your app is subsequently terminated, the
system automatically relaunches the app into the background if a new
event arrives. In such a case, the options dictionary passed to the
application(:willFinishLaunchingWithOptions:) and
application(
:didFinishLaunchingWithOptions:) methods of your app
delegate contains the key location to indicate that your app was
launched because of a location event. Upon relaunch, you must still
configure a location manager object and call this method to continue
receiving location events. When you restart location services, the
current event is delivered to your delegate immediately. In addition,
the location property of your location manager object is populated
with the most recent location object even before you start location
services.

link : https://developer.apple.com/documentation/corelocation/cllocationmanager/1423531-startmonitoringsignificantlocati

important thing to notice in above statement is

Upon relaunch, you must still, configure a location manager object and
call this method to continue receiving location events.

Meaning, your current location manager will not be of much use and you should create a new one and configure the new instance and call startMonitorSignificantLocationChanges again.

So iOS will send location updates to terminated apps only when you use startMonitoringSignificantLocationChanges.

All that are applicable only if your app was terminated and iOS relaunched it on receiving location update. But if your app is simply in background you need not do any thing on using startMonitorSignificantLocationChanges

on the other hand startUpdatingLocation will work only when app is in background/foreground mode. iOS will stop updating location if your app gets suspended or killed.

If you start this service and your app is suspended, the system stops
the delivery of events until your app starts running again (either in
the foreground or background). If your app is terminated, the delivery
of new location events stops altogether. Therefore, if your app needs
to receive location events while in the background, it must include
the UIBackgroundModes key (with the location value) in its Info.plist
file.

link: https://developer.apple.com/documentation/corelocation/cllocationmanager/1423750-startupdatinglocation

So modify your code

 locationManager.startMonitoringSignificantLocationChange()

Ok that was about proper usage of startMonitoringSignificantLocationChanges and startupdatinglocation. Now timer for mistakes in your code.

Mistake 1:

self.bgtimer = Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(self.bgtimer(timer:)), userInfo: nil, repeats: true)

Using timer to get timely updates on location. Thats not how it works!!! You cant run Timer forever. Timer stops as soon as your app suspends or gets terminated. Location Manager informs the app when location changes and you should rely on that only. You cant run timer to timely check location updates. It won't run in suspended or terminated state.

Mistake 2:

  func updateLocation() {
locationManager.startUpdatingLocation()
locationManager.stopUpdatingLocation()

Why start and stopping update locations in subsequent statements? That does not make much sense.

Mistake 3:

func StartupdateLocation() {
locationManager.delegate = self
locationManager.startUpdatingLocation()

Your StartupdateLocation gets called multiple time and every time you called this method you are repeatedly calling startUpdatingLocation on same instance of location manager. You need not do that! You can call startUpdatingLocation or startMonitoringSignificantLocationChange only once.

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!

What is the best way to receive location updates in background?

It comes out for Android 5 Lollipop it's better (much more stable) to use third-party library for bacground location receiving, namely io.nlopez.smartlocation.SmartLocation from 'io.nlopez.smartlocation:library:3.3.3', as decribed here, along with a foreground service, as Rudrik Patel mentioned. Works like a charm.

Update location in background?

You have to call the call the code inside the updateUserLoc() directly inside the callbackDispatcher. Just make the callbackDispatcher async function.

Background Service for update location in background

It's because of Android Oreo behaviour changes for background execution. Suggested alternatives are

1) Foreground service.

Use this if you are ok displaying notification to the user when you are trying to retrieve the location using Location API. This would be reliable and is suggested in the documentation.

Sample app from the documentation :
LocationUpdatesForegroundService project on GitHub

An example of an app that allows the app to continue a user-initiated
action without requesting all-the-time access to background location.

References
https://developer.android.com/training/location/receive-location-updates

2) Work Manager

This approach would be less reliable as you will not be able to control when exactly this would be called but can be used if you don't want to show notification to the user at all.

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


Related Topics



Leave a reply



Submit