简体   繁体   中英

Send Location of User in Background Swift

I am building an app where the user clicks a button and for 60mins (or any amount of time) we keep track of them by uploading their location to a server. Currently we are using 'Did Update Locations' function to send the users location to firebase in real-time.

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

}

This system works but it spams the server sending the location of the user to the server once every second.

This is too much data and we would only need to send the users location to the server once every 10-30 seconds.

What can we do send the users location once every 10-30 seconds?

class ViewController: UIViewController, CLLocationManagerDelegate {
    private var locman = CLLocationManager()
    private var startTime: Date? //An instance variable, will be used as a previous location time.

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

    guard let loc = locations.last else { return }

    let time = loc.timestamp

    guard var startTime = startTime else {
        self.startTime = time // Saving time of first location, so we could use it to compare later with second location time.
        return //Returning from this function, as at this moment we don't have second location. 
    }

    let elapsed = time.timeIntervalSince(startTime) // Calculating time interval between first and second (previously saved) locations timestamps.

    if elapsed > 30 { //If time interval is more than 30 seconds
        print("Upload updated location to server")
        updateUser(location: loc) //user function which uploads user location or coordinate to server.

        startTime = time //Changing our timestamp of previous location to timestamp of location we already uploaded.

    }
}
import UIKit
import CoreLocation
@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate,CLLocationManagerDelegate {
var window: UIWindow?
var locationManager = CLLocationManager()
var backgroundUpdateTask: UIBackgroundTaskIdentifier!
var bgtimer = Timer()
var latitude: Double = 0.0
var longitude: Double = 0.0
var current_time = NSDate().timeIntervalSince1970
var timer = Timer()
var f = 0
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    self.doBackgroundTask()
    return true
}


func applicationWillResignActive(_ application: UIApplication) {
}

func applicationWillEnterForeground(_ application: UIApplication) {
    print("Entering foreBackground")
}

func applicationDidBecomeActive(_ application: UIApplication) {
}

func applicationWillTerminate(_ application: UIApplication) {
}

func applicationDidEnterBackground(_ application: UIApplication) {
    print("Entering Background")
   // self.doBackgroundTask()
}

func doBackgroundTask() {

    DispatchQueue.main.async {

        self.beginBackgroundUpdateTask()

        self.StartupdateLocation()


        self.bgtimer = Timer.scheduledTimer(timeInterval:-1, target: self, selector: #selector(AppDelegate.bgtimer(_:)), userInfo: nil, repeats: true)
        RunLoop.current.add(self.bgtimer, forMode: RunLoopMode.defaultRunLoopMode)
        RunLoop.current.run()

        self.endBackgroundUpdateTask()

    }
}

func beginBackgroundUpdateTask() {
    self.backgroundUpdateTask = UIApplication.shared.beginBackgroundTask(expirationHandler: {
        self.endBackgroundUpdateTask()
    })
}

func endBackgroundUpdateTask() {
    UIApplication.shared.endBackgroundTask(self.backgroundUpdateTask)
    self.backgroundUpdateTask = UIBackgroundTaskInvalid
}

func StartupdateLocation() {
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.distanceFilter = kCLDistanceFilterNone
    locationManager.requestAlwaysAuthorization()
    locationManager.allowsBackgroundLocationUpdates = true
    locationManager.pausesLocationUpdatesAutomatically = false
    locationManager.startUpdatingLocation()
}

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
    print("Error while requesting new coordinates")
}

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

    let locValue:CLLocationCoordinate2D = manager.location!.coordinate

    self.latitude = locValue.latitude
    self.longitude = locValue.longitude
    f+=1
    print("New Coordinates: \(f) ")
    print(self.latitude)
    print(self.longitude)
}

@objc func bgtimer(_ timer:Timer!){
    sleep(2)
  /*  if UIApplication.shared.applicationState == .active {
         timer.invalidate()
    }*/
    self.updateLocation()
}

func updateLocation() {
    self.locationManager.startUpdatingLocation()
    self.locationManager.stopUpdatingLocation()
}}

I added the sleep function to delay of calling the location and send the information to server

Since this is running in both the app is active and goes to background. If you want only background process, remove or comment the function self.doBackgroundTask() from didFinishLaunchingWithOptions and remove the comment for self.doBackgroundTask() in the applicationdidEnterBackground. And then remove the comment in the function bgtimer(), since the background process has to stop once the app comes to active state.

Apps normally get suspended (no longer get CPU time) a moment after being moved to the background. You can ask for extra background time, but the system only gives you 3 minutes.

Only a very limited class of apps are allowed to run in the background for longer than that. Mapping/GPS applications are one of those categories. However, your app is not a mapping/GPS application, so I doubt if Apple would approve it.

Bottom line: I think you might be out of luck running your location queries for more than 3 minutes.

EDIT:

As Paulw11 points out, you can use the significant location change service to get location updates when the device moves by large distances.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM