在后台更新位置 [英] Update location in Background

查看:108
本文介绍了在后台更新位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

即使用户不使用该应用程序,我也想获取用户位置.现在,按下主屏幕按钮并且应用程序进入后台状态后,我可以获取位置信息,但是在停止位置更新几秒钟之后.而当我杀死应用程序位置时,停止针对的更新.这是我在应用程序委托中的代码.

I want to get user location even when the user does not use the app.now i can get location after press home button and application goes to background state, but after a few second location update stoped. And when I'm killing the app location update against stoped. this is my code in app delegate.

 let locationManager = CLLocationManager()
  var LatitudeGPS = String()
  var LongitudeGPS = String()
  var speedGPS = String()
  var Course = String()
  var Altitude = String()
  var bgtimer = Timer()

func applicationDidEnterBackground(_ application: UIApplication) {

    self.doBackgroundTask()
  }

  func beginBackgroundUpdateTask() {

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

  }

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

  DispatchQueue.global(qos: .background).async {

    self.beginBackgroundUpdateTask()
    self.StartupdateLocation()
    self.bgtimer = Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(self.bgtimer(timer:)), userInfo: nil, repeats: true)
    RunLoop.current.add(self.bgtimer, forMode: RunLoopMode.defaultRunLoopMode)
    RunLoop.current.run()
    self.endBackgroundUpdateTask()

  }


}


func bgtimer(timer:Timer!){
  print("Fired from Background ************************************")
  updateLocation()
}
  func StartupdateLocation() {
    locationManager.delegate = self
    locationManager.startUpdatingLocation()
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.distanceFilter = kCLDistanceFilterNone
    locationManager.requestAlwaysAuthorization()
    locationManager.allowsBackgroundLocationUpdates = true
    locationManager.pausesLocationUpdatesAutomatically = false
  }

  func updateLocation() {
locationManager.startUpdatingLocation()
    locationManager.stopUpdatingLocation()
    print("Latitude: \(LatitudeGPS)")
    print("Longitude: \(LongitudeGPS)")
    print("Speed: \(speedGPS)")
    print("Heading: \(Course)")
    print("Altitude BG: \(Altitude)")
    DispatchQueue.main.async {
      print(UIApplication.shared.backgroundTimeRemaining)

    }
  }

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

    LatitudeGPS = String(format: "%.10f", manager.location!.coordinate.latitude)
    LongitudeGPS = String(format: "%.10f", manager.location!.coordinate.longitude)
    speedGPS = String(format: "%.3f", manager.location!.speed)
    Altitude = String(format: "%.3f", manager.location!.altitude)
    Course = String(format: "%.3f", manager.location!.course)

  }
}

我认为几秒钟后我的应用程序终止了,并且位置更新也停止了. 我希望20分钟后终止的应用程序(操作系统或用户)停止更新位置以保持电池电量. 我的位置更新问题在哪里?

i think after a few second my application terminated and location update stoped. I want to after 20 min that application terminated (os or user) stop updating location to keep the battery charge. where is my problem in location update.

推荐答案

要更改的事物.

第1步:

确保在项目的功能部分启用了位置更新后台模式,如下所示

Make sure you have enabled location updates background mode in capabilities section of your project as shown below

第2步:

而当我终止应用位置更新时,就停止了.

And when I'm killing the app location update against stoped.

引用苹果文档

如果您启动此服务而您的应用随后被终止,则 新的系统会自动将应用重新启动到后台 事件到了.在这种情况下,选项字典将传递给 application(:willFinishLaunchingWithOptions :)和 应用程序的application(:didFinishLaunchingWithOptions :)方法 委托包含关键位置,以指示您的应用程序是 因位置事件而启动.重新启动后,您仍然必须 配置位置管理器对象并调用此方法以继续 接收位置事件.当您重新启动位置服务时, 当前事件将立即传递给您的代表.此外, 填充了位置管理器对象的location属性 甚至在您开始定位之前使用最新的定位对象 服务.

If you start this service and your app is subsequently terminated, the system automatically relaunches the app into the background if a new event arrives. In such a case, the options dictionary passed to the application(:willFinishLaunchingWithOptions:) and application(:didFinishLaunchingWithOptions:) methods of your app delegate contains the key location to indicate that your app was launched because of a location event. Upon relaunch, you must still configure a location manager object and call this method to continue receiving location events. When you restart location services, the current event is delivered to your delegate immediately. In addition, the location property of your location manager object is populated with the most recent location object even before you start location services.

链接: https://developer.apple.com/documentation/corelocation/cllocationmanager/1423531-startmonitoringsignificantlocati

上述声明中要注意的重要事项是

important thing to notice in above statement is

重新启动后,您仍然必须配置位置管理器对象,然后 调用此方法以继续接收位置事件.

Upon relaunch, you must still, configure a location manager object and call this method to continue receiving location events.

意味着,您当前的位置管理器用处不大,您应该创建一个新的位置管理器并配置新实例,然后再次调用startMonitorSignificantLocationChanges.

Meaning, your current location manager will not be of much use and you should create a new one and configure the new instance and call startMonitorSignificantLocationChanges again.

因此,仅当您使用startMonitoringSignificantLocationChanges时,iOS才会将位置更新发送到终止的应用程序.

So iOS will send location updates to terminated apps only when you use startMonitoringSignificantLocationChanges.

仅当您的应用被终止并且iOS在收到位置更新后重新启动时,所有这些都适用.但是,如果您的应用只是在后台运行,则无需使用startMonitorSignificantLocationChanges

All that are applicable only if your app was terminated and iOS relaunched it on receiving location update. But if your app is simply in background you need not do any thing on using startMonitorSignificantLocationChanges

startUpdatingLocation仅在应用程序处于后台/前景模式时才有效.如果您的应用被暂停或终止,iOS将停止更新位置.

on the other hand startUpdatingLocation will work only when app is in background/foreground mode. iOS will stop updating location if your app gets suspended or killed.

如果您启动此服务而您的应用已暂停,则系统将停止 事件的传递,直到您的应用再次开始运行(在 前景或背景).如果您的应用被终止,则交付 的新位置事件完全停止.因此,如果您的应用需要 要在后台接收位置事件,它必须包括 其Info.plist中的UIBackgroundModes键(带有位置值) 文件.

If you start this service and your app is suspended, the system stops the delivery of events until your app starts running again (either in the foreground or background). If your app is terminated, the delivery of new location events stops altogether. Therefore, if your app needs to receive location events while in the background, it must include the UIBackgroundModes key (with the location value) in its Info.plist file.

链接: https://developer.apple.com/documentation/corelocation/cllocationmanager/1423750-startupdatinglocation

因此修改您的代码

 locationManager.startMonitoringSignificantLocationChange()

好,关于正确使用startMonitoringSignificantLocationChangesstartupdatinglocation.现在,计时器会为您的代码中的错误计时.

Ok that was about proper usage of startMonitoringSignificantLocationChanges and startupdatinglocation. Now timer for mistakes in your code.

错误1:

self.bgtimer = Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(self.bgtimer(timer:)), userInfo: nil, repeats: true)

使用计时器及时获取位置更新.那不是怎么工作的!!!您不能永远运行Timer.只要您的应用程序暂停或终止,计时器就会停止.当位置更改时,位置管理器会通知应用程序,您应该仅依靠它.您无法运行计时器来及时检查位置更新.它不会在挂起或终止状态下运行.

Using timer to get timely updates on location. Thats not how it works!!! You cant run Timer forever. Timer stops as soon as your app suspends or gets terminated. Location Manager informs the app when location changes and you should rely on that only. You cant run timer to timely check location updates. It won't run in suspended or terminated state.

错误2:

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

为什么要在后续语句中启动和停止更新位置?那没有多大意义.

Why start and stopping update locations in subsequent statements? That does not make much sense.

错误3:

func StartupdateLocation() {
    locationManager.delegate = self
    locationManager.startUpdatingLocation()

您的StartupdateLocation被多次调用,并且每次调用此方法时,您都在同一位置管理器实例上重复调用startUpdatingLocation.您不必这样做!您只能调用startUpdatingLocationstartMonitoringSignificantLocationChange一次.

Your StartupdateLocation gets called multiple time and every time you called this method you are repeatedly calling startUpdatingLocation on same instance of location manager. You need not do that! You can call startUpdatingLocation or startMonitoringSignificantLocationChange only once.

这篇关于在后台更新位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆