I'm currently working on an app and am encountering a problem. The purpose of my app is to see when someone leaves work. For that to work 100% of the time the app should be able to get the user's location while the app is open, in the background or terminated (killed). My understanding is that you have to use the significant location change functionality for this. However, it's not working as expected.
AppDelegate:
//handle location changes when app is terminated and waken up by the OS
if launchOptions?[UIApplicationLaunchOptionsKey.location] != nil {
print("Restarted app due to a location update")
request = Locator.subscribeSignificantLocations(onUpdate: { newLoc in
let db: FirebaseDB = FirebaseDB.shared
db.postCoordinates(coordinates: CLLocation(latitude: 9.99, longitude: 9.99))
print("new loc found -> \(newLoc)")
}, onFail: {(err, lastLoc) in
print("failed to get loc, -> \(err)")
})
//send new post to DB
}
//subscribeSignificantLocations -> power efficient
request = Locator.subscribeSignificantLocations(onUpdate: { newLoc in
print("new loc found -> \(newLoc)")
}, onFail: {(err, lastLoc) in
print("failed to get new loc, -> \(err)")
})
Everything works except for getting the location when the app is terminated...
Thanks in advance!
After hours of searching and reading for the solution, I found a working solution for me. (NOTE: I am working on geofencing where I need to notify/call API the user when he leaves certain area)
The first and most important step is to have "always" authorization by the user for location access.
Second, we need to use startMonitoringSignificantLocationChanges()
for location update even after the app termination.
locationManager.requestAlwaysAuthorization()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
locationManager.allowsBackgroundLocationUpdates = true
locationManager.startUpdatingLocation()
locationManager.startMonitoringSignificantLocationChanges() //THIS IS WHERE THE MAGIC HAPPENS
Below is the code for getting the local notifications for location update.
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var window: UIWindow?
let locationManager = CLLocationManager()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
locationManager.requestAlwaysAuthorization()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
locationManager.allowsBackgroundLocationUpdates = true
locationManager.startUpdatingLocation()
locationManager.startMonitoringSignificantLocationChanges()
application.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert, .badge], categories: nil))
UIApplication.shared.cancelAllLocalNotifications()
return true
}
func alertUserOnLeaving(region:CLRegion){
if UIApplication.shared.applicationState == .active {
let alert = UIAlertController(title: "Alert Title", message: "Alert Message", style = .Alert
window?.rootViewController?.present(alert, animated: true, completion: nil)
}
else{
let notification = UILocalNotification()
notification.alertBody = "You forgot to checkout"
notification.soundName = "Default"
UIApplication.shared.presentLocalNotificationNow(notification)
}
}
func alertUserOnArrival(region:CLRegion){
if UIApplication.shared.applicationState == .active {
let alert = UIAlertController(title: "Alert Title", message: "Alert Message", style = .Alert
window?.rootViewController?.present(alert, animated: true, completion: nil)
}
else{
let notification = UILocalNotification()
notification.alertBody = "Welcome Please checkin"
notification.soundName = "Default"
UIApplication.shared.presentLocalNotificationNow(notification)
}
}
func setUpGeofenceForJob() {
let geofenceRegionCenter = CLLocationCoordinate2DMake(-33.7513580322265, 151.242416381836)
let geofenceRegion = CLCircularRegion(center: geofenceRegionCenter, radius: 100, identifier: "GeoFence")
geofenceRegion.notifyOnExit = true
geofenceRegion.notifyOnEntry = true
self.locationManager.startMonitoring(for: geofenceRegion)
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if (status == CLAuthorizationStatus.authorizedAlways) {
self.setUpGeofenceForJob()
}
}
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
alertUserOnArrival(region: region)
}
func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
alertUserOnLeaving(region: region)
}
Hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With