后台位置服务会在一段时间内停止工作 [英] Background location service stops working in a period of time

查看:143
本文介绍了后台位置服务会在一段时间内停止工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个iOS应用程序,用户可以将其行进路线保存到服务器(通过API发布其位置).我正在努力解决的问题是,有几位用户报告说他们保存的路线在旅途中途中断.详细地,当用户在地图上查看其保存的路线时,路线的一部分只是一条直线,这是因为该路线部分的某个位置没有以某种方式发送到服务器,或者仅仅是因为该设备当时无法接收位置. 奇怪的是,其余路线均正常记录,因此位置服务似乎停止了一段时间,但之后又重新启动,因此我的应用程序可以很好地记录它.

I'm developing an iOS application that users can save their traveling route to server (by posting their locations through API). The issue I am struggling with is several users reported that the route they saved is interrupted in the middle of the trip. In detail, when users review their saved route on map, there is a part of route being just a straight line because somehow locations of that route section are not sent to server or just because the device can not receive locations at that time. The weird thing is that the rest of route was recorded normally so seems like the location service stopped working for a period of time but after that it started again so my app could record it fine.

最令人沮丧的是,我无法重现此问题.

And the most frustrating thing is that I can not reproduce this issue.

以下是用户报告的问题的情况:
-用户启动了该应用程序,然后锁定了设备屏幕并将其放在口袋中,他们在整个旅程中都没有触摸它.没有电池耗尽或崩溃发生.
-行驶了大约8-9公里,并且一切正常后,在接下来的〜65公里处中断了路线记录,然后在其余的80公里处再次进行了很好的记录.

Here are circumstances of the issue that user reported:
- User started the app then locked device screen and put it in their pocket, they did not touch it in the whole journey. No battery drain or crash happened.
- After driving about 8-9km and everything worked fine, route recording was interrupted in the next ~ 65km, then well-recorded again in the rest ~ 80km.

以下是我的项目设置:
-具有位置"更新的功能中开启"的背景模式.
-从位置服务接收到的位置会根据时间戳和准确性进行过滤,如果位置成功发送到服务器,则会使用"isSent"标记将其保存到核心数据中.这样,我的应用程序可以覆盖网络连接断开时的情况.
-标有错误"isSent"标志的位置将每30秒发送到服务器一次.

Below is my project setup:
- Background Modes in ON in Capabilities with Location updates.
- Locations received from location service are filtered based on timestamp and accuracy and saved to core data with a "isSent" flag marking if a location is sent successfully to server. This way my app can cover the case when network connection is down.
- Locations marked with false "isSent" flag will be sent to server every 30 seconds.

我的LocationManager代码:

My LocationManager code:

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
    }
}

你们能帮助我找出代码中的黑洞吗,或者我可以做些什么来重现/解决此问题?非常感谢!!!

Can you guys help me find out black holes in my code or anything I can do to reproduce / fix this issue? Thanks a lot!!!

推荐答案

您的设置对我来说很好.只是一个问题.当您说它不在60公里处工作然后又开始在80公里处工作时,那是不是一直在后台?我的意思是用户不需要输入前台即可重新开始工作,对吗?

Your setup looks fine to me. Just one question. When you say it didn't work for 60km and then it started working for 80km, was that all while in background? I mean the user didn't need to enter foreground for it to start working again did they?

您对location.horizontalAccuracy的限制为33.您认为这将是非常准确的.我不确定,也许设备/城市组合不好,然后您早点回来了.我建议您记录为什么要早退的原因.他们的城市可能与您的城市不同.我也听说过iPhoneX的GPS即使位置正确,它也会为其horizontalAccuracy返回一个很高的数字.这种情况主要发生在iPhoneX用户身上吗?

Your limit for location.horizontalAccuracy is 33. You're thinking that it's going to be very accurate. I'm not sure, maybe the device/city are a bad combination, and then you're returning early. I suggest that you log the reason why you exit early. Their city might be different from yours. Also I've heard that the GPS of the iPhoneX even though has the correct location, it returns a high number for its horizontalAccuracy. Is this happening mostly for iPhoneX users?

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: "")
        }
    }
}

然后具有类似这样的功能来检查每个位置.

And then have a function like this to check each location.

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)
    }
}

您的最终用途将是:

do {
       try checkLocationAccuracy(from: location)

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

我还将在您的应用状态周围添加日志,例如添加日志以捕获didEnterBackground

I'd also add logs around your app state as well e.g. add a log to capture didEnterBackground

这篇关于后台位置服务会在一段时间内停止工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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