How do I get a background location update every n minutes in my iOS application?

后端 未结 14 1170
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-22 02:00

I\'m looking for a way to get a background location update every n minutes in my iOS application. I\'m using iOS 4.3 and the solution should work for non-jailbroken iPhones

14条回答
  •  情话喂你
    2020-11-22 02:11

    Here is what I use:

    import Foundation
    import CoreLocation
    import UIKit
    
    class BackgroundLocationManager :NSObject, CLLocationManagerDelegate {
    
        static let instance = BackgroundLocationManager()
        static let BACKGROUND_TIMER = 150.0 // restart location manager every 150 seconds
        static let UPDATE_SERVER_INTERVAL = 60 * 60 // 1 hour - once every 1 hour send location to server
    
        let locationManager = CLLocationManager()
        var timer:NSTimer?
        var currentBgTaskId : UIBackgroundTaskIdentifier?
        var lastLocationDate : NSDate = NSDate()
    
        private override init(){
            super.init()
            locationManager.delegate = self
            locationManager.desiredAccuracy = kCLLocationAccuracyKilometer
            locationManager.activityType = .Other;
            locationManager.distanceFilter = kCLDistanceFilterNone;
            if #available(iOS 9, *){
                locationManager.allowsBackgroundLocationUpdates = true
            }
    
            NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.applicationEnterBackground), name: UIApplicationDidEnterBackgroundNotification, object: nil)
        }
    
        func applicationEnterBackground(){
            FileLogger.log("applicationEnterBackground")
            start()
        }
    
        func start(){
            if(CLLocationManager.authorizationStatus() == CLAuthorizationStatus.AuthorizedAlways){
                if #available(iOS 9, *){
                    locationManager.requestLocation()
                } else {
                    locationManager.startUpdatingLocation()
                }
            } else {
                    locationManager.requestAlwaysAuthorization()
            }
        }
        func restart (){
            timer?.invalidate()
            timer = nil
            start()
        }
    
        func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
            switch status {
            case CLAuthorizationStatus.Restricted:
                //log("Restricted Access to location")
            case CLAuthorizationStatus.Denied:
                //log("User denied access to location")
            case CLAuthorizationStatus.NotDetermined:
                //log("Status not determined")
            default:
                //log("startUpdatintLocation")
                if #available(iOS 9, *){
                    locationManager.requestLocation()
                } else {
                    locationManager.startUpdatingLocation()
                }
            }
        }
        func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    
            if(timer==nil){
                // The locations array is sorted in chronologically ascending order, so the
                // last element is the most recent
                guard let location = locations.last else {return}
    
                beginNewBackgroundTask()
                locationManager.stopUpdatingLocation()
                let now = NSDate()
                if(isItTime(now)){
                    //TODO: Every n minutes do whatever you want with the new location. Like for example sendLocationToServer(location, now:now)
                }
            }
        }
    
        func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
            CrashReporter.recordError(error)
    
            beginNewBackgroundTask()
            locationManager.stopUpdatingLocation()
        }
    
        func isItTime(now:NSDate) -> Bool {
            let timePast = now.timeIntervalSinceDate(lastLocationDate)
            let intervalExceeded = Int(timePast) > BackgroundLocationManager.UPDATE_SERVER_INTERVAL
            return intervalExceeded;
        }
    
        func sendLocationToServer(location:CLLocation, now:NSDate){
            //TODO
        }
    
        func beginNewBackgroundTask(){
            var previousTaskId = currentBgTaskId;
            currentBgTaskId = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({
                FileLogger.log("task expired: ")
            })
            if let taskId = previousTaskId{
                UIApplication.sharedApplication().endBackgroundTask(taskId)
                previousTaskId = UIBackgroundTaskInvalid
            }
    
            timer = NSTimer.scheduledTimerWithTimeInterval(BackgroundLocationManager.BACKGROUND_TIMER, target: self, selector: #selector(self.restart),userInfo: nil, repeats: false)
        }
    }
    

    I start the tracking in AppDelegate like that:

    BackgroundLocationManager.instance.start()
    

提交回复
热议问题