Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get periodicaly new location when app is in background or killed

I want to get new location every 1min when my app is in background or killed. Here is my code :

Location Service:

class LocationService: NSObject, CLLocationManagerDelegate {

    static let shared = LocationService()
    var locationManager = CLLocationManager()
    var significatLocationManager = CLLocationManager()
    var currentLocation: CLLocation!
    var timer = Timer()
    var bgTask = UIBackgroundTaskInvalid

    func startUpdatingLocation() {
        locationManager.requestAlwaysAuthorization()
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.distanceFilter = kCLDistanceFilterNone
        if #available(iOS 9.0, *) {
            locationManager.allowsBackgroundLocationUpdates = true
        }
        locationManager.delegate = self
        locationManager.startUpdatingLocation()
    }

    func stopUpdatingLocation() {
        locationManager.stopUpdatingLocation()
        timer.invalidate()
    }

    func restartUpdatingLocation() {
        locationManager.stopMonitoringSignificantLocationChanges()
        timer.invalidate()
        startUpdatingLocation()
    }

    func startMonitoringLocation() {
        locationManager.stopUpdatingLocation()
        locationManager.startMonitoringSignificantLocationChanges()
        timer.invalidate()
    }

    func changeLocationAccuracy(){
        switch locationManager.desiredAccuracy {
        case kCLLocationAccuracyBest:
            locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
            locationManager.distanceFilter = 99999
        case kCLLocationAccuracyThreeKilometers:
            locationManager.desiredAccuracy = kCLLocationAccuracyBest
            locationManager.distanceFilter = kCLDistanceFilterNone
        default: break
        }
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        bgTask = UIApplication.shared.beginBackgroundTask(expirationHandler: {
            UIApplication.shared.endBackgroundTask(self.bgTask)
            self.bgTask = UIBackgroundTaskInvalid
        })

        currentLocation = locations.last!

        let interval = currentLocation.timestamp.timeIntervalSinceNow
        let accuracy = self.locationManager.desiredAccuracy

        if abs(interval) < 60 && accuracy != kCLLocationAccuracyThreeKilometers {        
            timer = Timer.scheduledTimer(timeInterval: 60, target: self, selector: #selector(LocationService.changeLocationAccuracy), userInfo: nil, repeats: false)
            changeLocationAccuracy()
        }
    } 
}

App delegate:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
     if launchOptions?[UIApplicationLaunchOptionsKey.location] != nil {
          LocationService.shared.restartUpdatingLocation()
     }
}

func applicationDidEnterBackground(_ application: UIApplication) {
     LocationService.shared.restartUpdatingLocation()
}

func applicationWillTerminate(_ application: UIApplication) {
     LocationService.shared.startMonitoringLocation()
}

View controller:

override func viewDidLoad() {
    LocationService.shared.startUpdatingLocation()
}

But my code is not working, i'm not getting new location after a few minutes when my app is in background. and same when my app is suspended or killed. Is there any solution for that ? please not that i'm using Swift 3 & xcode 8.1.

Thank's in advance

like image 861
YouSS Avatar asked Jan 07 '17 18:01

YouSS


1 Answers

  • If you call startUpdatingLocation when your app is already in the background, then you will only receive location updates for a few minutes.

  • If you call startUpdatingLocation while your app is in the foreground and then your app moves to the background, you will continue to receive location updates indefinitely.

  • If you call startMonitoringSignificantLocationChanges in the foreground and leave it enabled then you can call startUpdatingLocation in the background and receive updates indefinitely.

  • If the user terminates your app (by swiping up in the app switcher) then you will no longer receive location updates until the user re-launches your app.

Since your code stops and starts location monitoring when it moves to the background of only get location updates for a few minutes. If you start location monitoring foreground and do nothing when the app moves to the background then you will continue to receive location updates.

like image 94
Paulw11 Avatar answered Oct 04 '22 15:10

Paulw11