简体   繁体   English

在后台 Swift 中发送用户的位置

[英]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.我正在构建一个应用程序,用户点击一个按钮,然后我们通过将他们的位置上传到服务器来跟踪他们 60 分钟(或任何时间)。 Currently we are using 'Did Update Locations' function to send the users location to firebase in real-time.目前我们正在使用“Did Update Locations”功能将用户位置实时发送到 Firebase。

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.这是太多的数据,我们只需要每 10-30 秒将用户位置发送到服务器一次。

What can we do send the users location once every 10-30 seconds?我们可以做些什么每 10-30 秒发送一次用户位置?

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.如果您只需要后台进程,请从 didFinishLaunchingWithOptions 中删除或注释函数 self.doBackgroundTask() 并在 applicationdidEnterBackground 中删除 self.doBackgroundTask() 的注释。 And then remove the comment in the function bgtimer(), since the background process has to stop once the app comes to active state.然后删除函数 bgtimer() 中的注释,因为一旦应用程序进入活动状态,后台进程就必须停止。

Apps normally get suspended (no longer get CPU time) a moment after being moved to the background.应用程序在移至后台后通常会暂停(不再获得 CPU 时间)。 You can ask for extra background time, but the system only gives you 3 minutes.您可以要求额外的后台时间,但系统只给您 3 分钟。

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.地图/GPS 应用程序是这些类别之一。 However, your app is not a mapping/GPS application, so I doubt if Apple would approve it.但是,您的应用程序不是地图/GPS 应用程序,因此我怀疑 Apple 是否会批准它。

Bottom line: I think you might be out of luck running your location queries for more than 3 minutes.底线:我认为您运行位置查询超过 3 分钟可能不走运。

EDIT:编辑:

As Paulw11 points out, you can use the significant location change service to get location updates when the device moves by large distances.正如 Paulw11 指出的那样,当设备移动很远的距离时,您可以使用重要的位置更改服务来获取位置更新。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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