首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >后台定位服务在一段时间内停止工作

后台定位服务在一段时间内停止工作
EN

Stack Overflow用户
提问于 2018-09-28 16:41:25
回答 1查看 204关注 0票数 1

我正在开发一个iOS应用程序,用户可以将他们的旅行路线保存到服务器上(通过API发布他们的位置)。我正在努力解决的问题是,几个用户报告说,他们保存的路线在旅途中中断了。具体地,当用户在地图上查看他们保存的路线时,有一部分路线仅仅是一条直线,因为不知何故该路线段的位置不被发送到服务器,或者仅仅是因为设备当时不能接收位置。奇怪的是,剩下的路线是正常记录的,所以看起来定位服务停止了一段时间,但在那之后它又启动了,所以我的应用程序可以很好地记录下来。

最令人沮丧的是,我不能重现这个问题。

以下是用户报告的问题的情况:

  • 用户启动了应用程序,然后锁定设备屏幕并将其放入口袋,他们在整个过程中都没有触摸到它。未发生电池耗尽或崩溃。
  • 在行驶了大约8-9公里后,一切正常,路线记录在接下来的~65公里处中断,然后在剩下的~80公里处再次记录良好。

下面是我的项目设置:

  • 背景模式开启位置更新功能。从位置服务接收到的
  • 位置将根据时间戳和准确性进行过滤,并保存到核心数据中,并使用isSent标志来标记位置是否成功发送到服务器。通过这种方式,我的应用程序可以覆盖网络连接中断时的情况。标记了错误“isSent”标志的
  • 位置将每隔30秒发送到服务器。

我的LocationManager代码:

代码语言:javascript
复制
class LocationManager: NSObject, CLLocationManagerDelegate {

    var locationManager: CLLocationManager = {
        var _locationManager = CLLocationManager()
        _locationManager.delegate = self
        _locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
        _locationManager.activityType = .automotiveNavigation
        _locationManager.allowsBackgroundLocationUpdates = true
        _locationManager.pausesLocationUpdatesAutomatically = false

        return _locationManager
    }()


    func startLocationService() {
        locationManager.startUpdatingLocation()
        locationManager.allowsBackgroundLocationUpdates = true
        locationManager.pausesLocationUpdatesAutomatically = false
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        var positionsToSavedToDb: [DbPositionModel] = []

        for location in locations {
            let howRecent = location.timestamp.timeIntervalSinceNow

            guard abs(location.timestamp.timeIntervalSinceNow) < 10 && location.horizontalAccuracy > 0 && location.horizontalAccuracy < 33 else {
                continue
            }

            if self.locations.count > 0 {
                let distanceSinceLastLocation = location.distance(from: self.locations.last!)
                let timeSinceLastLocation = location.timestamp.timeIntervalSince(self.locations.last!.timestamp)
                if (distanceSinceLastLocation < 5 && abs(timeSinceLastLocation) < 10) {
                    continue
                }
            }

            // Create DbPositionModel from location and append to positionsToSavedToDb
        }

        // Save positionsToSavedToDb to core data
    }

    @objc func each30Seconds(_ timer: Timer) {
        // Select in database DbPositionModel objects with false “isSent” flag to send to server
    }
}

你们能帮我找出代码中的黑洞吗?或者我可以做些什么来重现/修复这个问题?非常感谢!

EN

回答 1

Stack Overflow用户

发布于 2018-10-01 13:18:13

你的设置在我看来很好。只有一个问题。当你说它在60公里时不能工作,然后它开始工作在80公里时,这一切都在后台吗?我的意思是,用户不需要进入前台就可以重新开始工作,不是吗?

您对location.horizontalAccuracy的限制是33。你会认为它会非常准确。我不确定,也许设备/城市是一个糟糕的组合,然后你就提前回来了。我建议你记录下你提前退出的原因。他们的城市可能和你的不同。我还听说iPhoneX的GPS即使位置正确,它的horizontalAccuracy也会返回一个很高的数字。这种情况主要发生在iPhoneX用户身上吗?

代码语言:javascript
复制
enum LocationAccuracyError: Error {
    case stale(secondsOld: Double)
    case invalid
    case lowAccuracy(metersOff: Double)
}

extension LocationAccuracyError: LocalizedError{
    var errorDescription: String? {
        switch self {
        case .stale(let seconds):
            return NSLocalizedString("location was stale by: \(seconds) seconds", comment: "")
        case .invalid:
            return NSLocalizedString("location was invalid)", comment: "")
        case .lowAccuracy(let metersOff):
            return NSLocalizedString("location's horizontal Accuracy was off by likely more than: \(metersOff) meters" , comment: "")
        }
    }
}

然后有一个像这样的函数来检查每个位置。

代码语言:javascript
复制
private func checkLocationAccuracy(from location: CLLocation) throws {

    let ageOfLocation = -location.timestamp.timeIntervalSinceNow

    if ageOfLocation >= maximumAcceptedStale {
        throw LocationAccuracyError.stale(secondsOld: ageOfLocation)
    }

    if location.horizontalAccuracy <= 0 {
        throw LocationAccuracyError.invalid
    }

    if location.horizontalAccuracy > MaximumAcceptedHorizontalAccuracy{
        throw LocationAccuracyError.lowAccuracy(metersOff: location.horizontalAccuracy)
    }
}

您的最终用途如下:

代码语言:javascript
复制
do {
       try checkLocationAccuracy(from: location)

   } catch let error {
       writelog("Bad Location: \(error.localizedDescription)")
   }

我也会添加关于你的应用程序状态的日志,例如添加一个日志来捕获didEnterBackground

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52551494

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档