2 Replies
      Latest reply on Jan 9, 2020 10:04 AM by fuhrthom
      fuhrthom Level 1 Level 1 (0 points)
        I did search on the internet, found some people who have the same problem but no one did get any solution yet... So I hope anyone here is the G I am searching for..

        1 - I did enable "Location updates" and "background fetch" in Background Modes.

         

        https://i.stack.imgur.com/eNW4K.png

         

        2 - I did call locationManager.startMonitoringSignificantLocationChanges() on the right place, I checked this on the way I write and string into my Firebase Database when the app will be waked up after terminating.

        3 - I am checking on the right way if there is a location key in launchOptions just like Apple on their documentation, see:

        https://developer.apple.com/documentation/uikit/app_and_environment/responding_to_the_launch_of_your_app

         

        https://i.stack.imgur.com/cW3dx.png

         

        So why is my launchOptions nil? I cannot understand why this happens... Because the App is getting waked up, the mistake cannot be on my locationManager handling..

        I found this on stackoverflow but my launchOptions are nil so the code is not getting inside the if...

        https://stackoverflow.com/questions/34527972/location-update-even-when-app-is-killed-terminated

         

        Please help.

         

        When my app launches the first time after installing, I initialize the locationManger. When I use the switchToogle for enable/disable location tracking, I start/stop the locationManger updating location.

        When my app goes in background, I restart the location updating.

        When my app was killed by user, the app wakes up and starts into app delegate method didFinishLaunchWithOptions.

         

        I hope its clear how my code works, if not just tell me!

         

        LocationMangerClass:

         

        import Foundation

        import CoreLocation

        import Firebase

         

         

        class LocationManagerClass : NSObject {

         

            static var locationManager: CLLocationManager!

         

            override init() {

                print("init...")

                LocationManagerClass.locationManager = CLLocationManager()

            }

         

            func getLocationManger() -> CLLocationManager {

                if LocationManagerClass.locationManager == nil {

                    LocationManagerClass.locationManager = CLLocationManager()

                }

                return LocationManagerClass.locationManager

            }

         

            func startLocationTracking() {

                print("start...")

                if LocationManagerClass.locationManager != nil {

                    LocationManagerClass.locationManager.stopMonitoringSignificantLocationChanges()

                    LocationManagerClass.locationManager.stopUpdatingLocation()

                }

                LocationManagerClass.locationManager = CLLocationManager()

                LocationManagerClass.locationManager.delegate = self

                LocationManagerClass.locationManager.desiredAccuracy = kCLLocationAccuracyBest

                LocationManagerClass.locationManager.activityType = .otherNavigation

                LocationManagerClass.locationManager.requestAlwaysAuthorization()

                LocationManagerClass.locationManager.pausesLocationUpdatesAutomatically = false

                LocationManagerClass.locationManager.startMonitoringSignificantLocationChanges()

                LocationManagerClass.locationManager.startUpdatingLocation()

            }

         

            func restartLocationTracking() {

                LocationManagerClass.locationManager.stopMonitoringSignificantLocationChanges()

                LocationManagerClass.locationManager.stopUpdatingLocation()

                LocationManagerClass.locationManager.requestAlwaysAuthorization()

                LocationManagerClass.locationManager.startMonitoringSignificantLocationChanges()

                LocationManagerClass.locationManager.startUpdatingLocation()

            }

         

            func stopLocationTracking() {

                LocationManagerClass.locationManager.stopUpdatingLocation()

                LocationManagerClass.locationManager.stopMonitoringSignificantLocationChanges()

            }

        }

         

         

        extension LocationManagerClass : CLLocationManagerDelegate {

         

            func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

                if let location = locations.last {

               

                    let calender = NSCalendar.current

                    let date = NSDate()

                    let components = calender.dateComponents([.hour, .minute , .second], from: date as Date)

              

                    if components.second! % 14 == 0 || components.second! % 15 == 0 || components.second! % 16 == 0 {

                  

                        let coordinate = location.coordinate

                        let lati: String = String(format:"%f", coordinate.latitude)

                        let longi: String = String(format:"%f", coordinate.longitude)

                  

                        let appState = UIApplication.shared.applicationState

                  

                        if appState == .active {

                           writeToDataBase(appState: "active", lat: lati, long: longi)

                        } else if appState == .background {

                           writeToDataBase(appState: "background", lat: lati, long: longi)

                        } else if appState == .inactive {

                          writeToDataBase(appState: "inactive", lat: lati, long: longi)

                        }

                  

                    }

                }

            }

         

            func writeToDataBase(appState: String, lat: String, long: String) {

          

                let calender = NSCalendar.current

                let date = NSDate()

                let components = calender.dateComponents([.hour, .minute , .second], from: date as Date)

          

                Database.database().reference().child("realDevice").child("locations").child("appStates").child(appState).childByAutoId().setValue("\(components.hour!):\(components.minute!):\(components.second!)Uhr lat: \(lat) : long: \(long)")

          

            }

         

            func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {

        //        checkLocationAuthorization()

            }

        }

         

        Start Tracking Controller:

         

        import UIKit

        import CoreLocation

        import Firebase

         

         

        class TrackingViewController: UIViewController {

         

            @IBOutlet weak var locationTrackingSwitch: UISwitch!

         

            var locationManager: LocationManagerClass!

            var appDelegate = UIApplication.shared.delegate as! AppDelegate

         

            override func viewDidLoad() {

                super.viewDidLoad()

           

                setupView()

           

                locationManager = appDelegate.locationManager

           

                let notificationCenter = NotificationCenter.default

                notificationCenter.addObserver(self, selector: #selector(appMovedToBackground), name: UIApplication.willResignActiveNotification, object: nil)

                notificationCenter.addObserver(self, selector: #selector(appMovedToForeGround), name: UIApplication.willEnterForegroundNotification, object: nil)

         

         

            }

         

            @objc func appMovedToBackground() {

                Database.database().reference().child("realDevice").child("state3").setValue("background")

        guard _ = UserDefaults.standard.value(forKey: "userEnabledLocationTracking") as? Bool else {locationManager.stopLocationTracking(); return}

                locationManager.restartLocationTracking()

            }

         

         

            @objc func appMovedToForeGround() {

                Database.database().reference().child("realDevice").child("state1").setValue("foreground")

            }

         

            @IBAction func locationTrackingSwitchUsed(_ sender: Any) {

                if locationTrackingSwitch.isOn == true {

                    locationManager.startLocationTracking()

                    UserDefaults.standard.set(true, forKey: "userEnabledLocationTracking")

                    UserDefaults.standard.synchronize()

                } else if locationTrackingSwitch.isOn == false {

                    locationManager.stopLocationTracking()

                    UserDefaults.standard.set(false, forKey: "userEnabledLocationTracking")

                    UserDefaults.standard.synchronize()

                }

            }

        }

         

        and my App Delegate:

         

        import UIKit

        import CoreLocation

        import Firebase

         

         

        @UIApplicationMain

        class AppDelegate: UIResponder, UIApplicationDelegate {

         

         

            var window: UIWindow?

            var locationManager = LocationManagerClass()

         

         

            var ref: DatabaseReference!

         

            override init() {

                FirebaseApp.configure()

                ref = Database.database().reference()

            }

         

         

            func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

         

         

                if let keys = launchOptions?.keys {

                    Database.database().reference().child("realDevice").child("state01").setValue("launchOptionsAreNotNil")

                   if keys.contains(.location) {

                    locationManager.startLocationTracking()

                      Database.database().reference().child("realDevice").child("state01").setValue("launchOptionsLocationKeyIsNotNil")

                   }

                    Database.database().reference().child("realDevice").child("state01").setValue("launchOptionsLocationKeyIsNil")

                }

            

        //work around to get locationTracking started because launchOptions are nil

                guard let isLocationEnabled = UserDefaults.standard.value(forKey: "userEnabledLocationTracking") as? Bool else {locationManager.stopLocationTracking(); return true}

                if isLocationEnabled {

                    locationManager.startLocationTracking()

                }

            

                return true

            }

         

            func applicationWillTerminate(_ application: UIApplication) {

                Database.database().reference().child("realDevice").child("state2").setValue("terminating")

            }

         

            // MARK: UISceneSession Lifecycle

         

         

            @available(iOS 13.0, *)

            func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {

                // Called when a new scene session is being created.

                // Use this method to select a configuration to create the new scene with.

                return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)

            }

         

         

            @available(iOS 13.0, *)

            func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {

                // Called when the user discards a scene session.

                // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.

                // Use this method to release any resources that were specific to the discarded scenes, as they will not return.

            }

         

         

         

         

        }