N分钟后持续追踪ios位置

问题描述 投票:0回答:1

有人在 iOS 中实现了后台位置更新吗?下面是我的场景,任何帮助都会很棒

问题陈述

  • 我想每 N 分钟跟踪一次用户位置并将其发送到服务器(后台和终止状态)

到目前为止我尝试过的是

  • 启用后台模式、位置更新、后台获取和后台处理

  • 创建了一个用于位置跟踪的单例,检查下面的代码并调用此类

didFinishLaunchingWithOptions - AppDelegate

现在我也探索了 BakcgroundTasks,但后台任务已注册,但在给定的时间间隔后没有执行,请检查下面的代码

   class EmployeeAttendanceTracker: NSObject,CLLocationManagerDelegate {

    
   static let shared = EmployeeAttendanceTracker()

    private let locationManager = CLLocationManager()
    private var lastLocationDate = Date()
    static let LOCATION_INTERVAL = 1
    
    var locationUpdate: (() -> Void)?

    private override init() {
        super.init()
        setupLocationManager()
    }
    
    private func setupLocationManager() {
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.activityType = .other
        locationManager.distanceFilter = kCLDistanceFilterNone
        locationManager.allowsBackgroundLocationUpdates = true
        locationManager.pausesLocationUpdatesAutomatically = false
        locationManager.showsBackgroundLocationIndicator = true
        
        
        if #available(iOS 9.0, *) {
          locationManager.requestAlwaysAuthorization()
        } else {
          locationManager.requestWhenInUseAuthorization()
        }
    }
      //    
    //
    //    // MARK: - CLLocationManagerDelegate
    //    
        func locationManager(_ manager: CLLocationManager, didChangeAuthorization      status: CLAuthorizationStatus) {
            switch status {
            case .restricted:
                //showLocationPermissionAlert()
                Logger.s("Location access restricted.")
            case .denied:
                //showLocationPermissionAlert()
                Logger.s("User denied location access.")
            case .notDetermined:
               // showLocationPermissionAlert()
                Logger.s("Location access not determined.")
            case .authorizedAlways:
                if #available(iOS 9, *) {
                    locationManager.requestLocation()
                } else {
                    locationManager.startUpdatingLocation()
                    locationManager.startMonitoringSignificantLocationChanges()
                }
            default:
               // showLocationPermissionAlert()
                break
            }
        }


    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    guard let location = locations.last else { return }
    
    Logger.s("User latitude: \(location.coordinate.latitude), longitude: \(location.coordinate.longitude)")
    locationManager.stopUpdatingLocation()
    
    let now = Date()
    if isItTime(now: now as NSDate) {
        if shouldSendLocationToServer() {
            self.sendLocationToServer(location: location,completion: {
                self.locationUpdate?()
            })
        }else{
            self.locationUpdate?()
        }
        Logger.s(now)
        Logger.s(location)
    }else{
        self.locationUpdate?()
    }
    
}

AppDelegate.swift

      func scheduleAppRefresh() {
      let request = BGAppRefreshTaskRequest(identifier: "com.example.location_update")
      request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) // 15 minutes from now
      
      do {
          try BGTaskScheduler.shared.submit(request)
          Logger.s("BG TASK REQUEST SUBMITTED")
      } catch {
          print("Unable to submit task request: \(error)")
      }
  }

func handleAppRefresh(task: BGAppRefreshTask) {
     task.expirationHandler = {
         // Handle expiration if needed
         Logger.s("BG TASK EXPIRED")
         task.setTaskCompleted(success: false)
     }
   Logger.s("HANDLE BG TASK REQUEST")
    EmployeeAttendanceTracker.shared.locationUpdate = {
         task.setTaskCompleted(success: true)
     }
 }

 func registerBackGroundTasks()  {
    // Register for background tasks
    BGTaskScheduler.shared.register(
        forTaskWithIdentifier: "com.example.location_update",
        using: DispatchQueue.global()
    ) { task in
        // Your task handler logic
        //task.setTaskCompleted(success: true)
        self.handleAppRefresh(task: task as! BGAppRefreshTask)
    }
}
ios swift gps core-location
1个回答
0
投票

你做不到。至少没有后台刷新任务。应用程序刷新任务将在 iOS 选择时执行。

earliestBeginDate
正是如此;任务最早运行的时间。它可能会在该日期后运行几分钟、几小时或几天。

您可以采取以下几种策略:

  1. 在“始终”权限下使用

    startUpdatingLocation
    。这将大约每秒提供一次位置更新。然后,您可以每“n”分钟向服务器报告一次位置。这将对电池产生重大影响,并且如果终止,将不会重新启动您的应用程序。

  2. 使用显着位置变化监控。仅当用户移动了约 500m 时,才会提供位置更新。如果用户正在步行或停下来一段时间,则这可能比“n”分钟长,或者如果用户快速移动(例如在汽车或火车中),则可能比“n”分钟更频繁。重要的位置监控使用的电量要少得多,并且允许您的应用程序在终止时重新启动(仅在检测到重大位置更改时)。

  3. 使用组合;定期位置进行频繁更新,重要位置更新在终止时重新启动。

您使用哪种方法取决于您的应用程序的用例。

对于 Uber 风格的“司机”应用程序,您希望持续更新,并且可以合理地期望设备连接到外部电源。

对于 Uber 风格的“乘客”应用程序,您希望持续更新,但只需要很短的时间(从预订过程开始到接载),因此电力消耗可能不是问题。

对于其他用例,请考虑仅进行重大位置更改是否就足够了。

© www.soinside.com 2019 - 2024. All rights reserved.