Фоновая служба определения местоположения перестает работать в течение определенного периода времени.
Я разрабатываю приложение для iOS, в котором пользователи могут сохранять маршрут путешествия на сервер (публикуя информацию о своих местоположениях через API). Проблема, с которой я борюсь, состоит в том, что несколько пользователей сообщили, что маршрут, который они сохранили, прерывается в середине поездки. Подробно, когда пользователи просматривают свой сохраненный маршрут на карте, часть маршрута представляет собой просто прямую линию, потому что местоположения этого участка маршрута не отправляются на сервер или просто потому, что устройство не может получать местоположения в это время. Странно то, что оставшаяся часть маршрута была записана нормально, поэтому похоже, что служба определения местоположения перестала работать на определенный период времени, но после этого она снова запустилась, и мое приложение смогло записать ее нормально.
И самое неприятное, что я не могу воспроизвести эту проблему.
Вот обстоятельства проблемы, о которой сообщил пользователь:
- Пользователь запустил приложение, затем заблокировал экран устройства и положил его в карман, они не трогали его за всю поездку. Не произошло разряда батареи или сбоя.
- Проехав 8-9 км и все заработало нормально, запись маршрута была прервана в следующие ~ 65 км, а затем снова хорошо записана в оставшиеся ~ 80 км.
Ниже приведены настройки моего проекта:
- Фоновые режимы в ON в возможностях с обновлениями местоположения.
- Местоположения, полученные от службы определения местоположения, фильтруются на основе метки времени и точности и сохраняются в базовых данных с пометкой "isSent", если местоположение успешно отправляется на сервер. Таким образом, мое приложение может покрыть случай, когда сетевое соединение не работает.
- Места, отмеченные ложным флагом "isSent", будут отправляться на сервер каждые 30 секунд.
Мой код LocationManager:
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
}
}
Ребята, можете ли вы помочь мне обнаружить черные дыры в моем коде или что-нибудь, что я могу сделать, чтобы воспроизвести / исправить эту проблему? Большое спасибо!!!
1 ответ
Ваша установка выглядит хорошо для меня. Всего один вопрос. Когда вы говорите, что он не работал на 60 км, а затем он начал работать на 80 км, это все было в фоновом режиме? Я имею в виду, что пользователю не нужно было вводить передний план, чтобы он снова начал работать, не так ли?
Ваш лимит для location.horizontalAccuracy
33. Вы думаете, что это будет очень точно. Я не уверен, возможно, устройство / город - плохая комбинация, и вы возвращаетесь рано. Я предлагаю вам записать причину, по которой вы выходите рано. Их город может отличаться от вашего. Также я слышал, что GPS iPhoneX, хотя и имеет правильное местоположение, он возвращает большое число для его horizontalAccuracy
, Это происходит в основном для пользователей iPhoneX?
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: "")
}
}
}
И затем есть такая функция, чтобы проверить каждое местоположение.
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