I want to get user location even when the user does not use the app.now i can get location after press home button and application goes to background state, but after a few second location update stoped. And when I'm killing the app location update against stoped. this is my code in app delegate.
let locationManager = CLLocationManager()
var LatitudeGPS = String()
var LongitudeGPS = String()
var speedGPS = String()
var Course = String()
var Altitude = String()
var bgtimer = Timer()
func applicationDidEnterBackground(_ application: UIApplication) {
self.doBackgroundTask()
}
func beginBackgroundUpdateTask() {
backgroundUpdateTask = UIApplication.shared.beginBackgroundTask(expirationHandler: {
self.endBackgroundUpdateTask()
})
}
func endBackgroundUpdateTask() {
UIApplication.shared.endBackgroundTask(self.backgroundUpdateTask)
self.backgroundUpdateTask = UIBackgroundTaskInvalid
}
func doBackgroundTask() {
DispatchQueue.global(qos: .background).async {
self.beginBackgroundUpdateTask()
self.StartupdateLocation()
self.bgtimer = Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(self.bgtimer(timer:)), userInfo: nil, repeats: true)
RunLoop.current.add(self.bgtimer, forMode: RunLoopMode.defaultRunLoopMode)
RunLoop.current.run()
self.endBackgroundUpdateTask()
}
}
func bgtimer(timer:Timer!){
print("Fired from Background ************************************")
updateLocation()
}
func StartupdateLocation() {
locationManager.delegate = self
locationManager.startUpdatingLocation()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.requestAlwaysAuthorization()
locationManager.allowsBackgroundLocationUpdates = true
locationManager.pausesLocationUpdatesAutomatically = false
}
func updateLocation() {
locationManager.startUpdatingLocation()
locationManager.stopUpdatingLocation()
print("Latitude: \(LatitudeGPS)")
print("Longitude: \(LongitudeGPS)")
print("Speed: \(speedGPS)")
print("Heading: \(Course)")
print("Altitude BG: \(Altitude)")
DispatchQueue.main.async {
print(UIApplication.shared.backgroundTimeRemaining)
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
LatitudeGPS = String(format: "%.10f", manager.location!.coordinate.latitude)
LongitudeGPS = String(format: "%.10f", manager.location!.coordinate.longitude)
speedGPS = String(format: "%.3f", manager.location!.speed)
Altitude = String(format: "%.3f", manager.location!.altitude)
Course = String(format: "%.3f", manager.location!.course)
}
}
i think after a few second my application terminated and location update stoped. I want to after 20 min that application terminated (os or user) stop updating location to keep the battery charge. where is my problem in location update.
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
Step 2:
Quoting from apple docs
link : https://developer.apple.com/documentation/corelocation/cllocationmanager/1423531-startmonitoringsignificantlocati
important thing to notice in above statement is
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
startMonitorSignificantLocationChangesagain.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
startMonitorSignificantLocationChangeson the other hand
startUpdatingLocationwill work only when app is in background/foreground mode. iOS will stop updating location if your app gets suspended or killed.link: https://developer.apple.com/documentation/corelocation/cllocationmanager/1423750-startupdatinglocation
So modify your code
Ok that was about proper usage of
startMonitoringSignificantLocationChangesandstartupdatinglocation. Now timer for mistakes in your code.Mistake 1:
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:
Why start and stopping update locations in subsequent statements? That does not make much sense.
Mistake 3:
Your
StartupdateLocationgets called multiple time and every time you called this method you are repeatedly callingstartUpdatingLocationon same instance of location manager. You need not do that! You can callstartUpdatingLocationorstartMonitoringSignificantLocationChangeonly once.