Отслеживание местоположений прекращается через некоторое время, когда приложение находится в фоновом режиме

Я создал простое приложение, которое отслеживает местоположение пользователя и создает локальное уведомление для каждого временного местоположения.

Я включил фоновые режимы ниже,

введите описание изображения здесь

let locationManager = CLLocationManager()

open override func viewDidLoad() {
       locationManager.delegate = self;
       locationManager.desiredAccuracy = kCLLocationAccuracyBest;
       locationManager.distanceFilter = 10
       locationManager.allowsBackgroundLocationUpdates = true
       locationManager.startUpdatingLocation()
}

open func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
       let notification = UILocalNotification()
       notification.alertBody = "location updated"
       notification.fireDate = Date()
       UIApplication.shared.scheduleLocalNotification(notification)
}

Я устанавливаю строку для NSLocationAlwaysUsageDescription и запрашиваю разрешение. Предоставление разрешения пользователя для использования всегда, когда приложение загружается в первый раз.


Это хорошо работает, когда приложение находится на переднем плане, когда оно идет в фоновом режиме все еще работает, по крайней мере, в 5-40 минутном диапазоне времени, который изменяется батареей или другими открытыми приложениями.

Проблема в том, почему она перестает работать, не ожидается ли она работать?

Я никогда не видел ограничения по времени в документах Apple.

Ответ 1

Переключитесь на значительные обновления местоположения, когда приложение переместится на задний план. iOS выгрузит приложение, если оно будет оставаться в фоновом режиме на неопределенный срок.

locationManager.pausesLocationUpdatesAutomatically = false

Ответ 2

Уменьшить Точность

Установите свойство desiredAccuracy объекта диспетчера местоположения

self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation

Вы можете использовать одну из констант CLLocationAccuracy

ВАЖНЫЙ

По умолчанию стандартные обновления местоположения на устройствах iOS выполняются с наилучшей точностью. Измените эти настройки в соответствии с требованиями ваших приложений. В противном случае ваше приложение будет излишне тратить энергию.


Авто-пауза

Установите для свойства pausesLocationUpdatesAutomatically объекта диспетчера местоположения значение true

self.locationManager.pausesLocationUpdatesAutomatically = true

ВАЖНЫЙ

Для приложений, имеющих авторизацию в использовании, приостановка обновлений местоположения прекращает доступ к изменениям местоположения до тех пор, пока приложение не будет запущено снова и не сможет перезапустить эти обновления. Если вы не хотите, чтобы обновления местоположений полностью прекращались, рассмотрите возможность отключения этого свойства и изменения точности местоположения на kCLLocationAccuracyThreeKilometers когда ваше приложение перемещается в фоновый режим. Это позволяет вам продолжать получать обновления информации о местоположении энергосберегающим способом.


Разрешить фоновые обновления

Установите для свойства allowsBackgroundLocationUpdates объекта диспетчера местоположения значение true

self.locationManager.allowsBackgroundLocationUpdates = true

Приложения, которые хотят получать обновления местоположения в случае приостановки, должны включить ключ UIBackgroundModes (со значением местоположения) в свой файл Info.plist своих приложений и установить для этого свойства значение true. Наличие фонового ключа UIBackgroundModes со значением местоположения требуется для фоновых обновлений


Укажите вид деятельности

Установите свойство activityType чтобы сообщить Core Location, какой тип активности местоположения выполняет ваше приложение в данный момент времени.

self.locationManager.activityType = .automotiveNavigation 

Вы можете использовать один из случаев CLActivityType


Обновление отложенного местоположения

На поддерживаемых устройствах с оборудованием GPS вы можете позволить менеджеру местоположения откладывать доставку обновлений местоположения, когда ваше приложение находится в фоновом режиме. Например, фитнес-приложение, которое отслеживает местоположение пользователя на туристической тропе, может откладывать обновления до тех пор, пока пользователь не переместится на определенное расстояние или не пройдет определенный период времени.


Ответ 3

После поиска ссылок (говоря о каких-либо ограничениях), я полагаю, что полезной оказалась видеозапись Apple Core Location Best Practices. при 06:53 говорить о стандартном местоположении в фоновом режиме:

кроме того, Core Location не предпримет никаких действий для обеспечения вашего приложения продолжает работать, поэтому, если у вас есть фоновый запуск по какой-то причине и вы решили начать сеанс размещения, вы можете получить некоторые обновления, но вы также можете быть заблокированы, прежде чем получать всю информацию, которая вы надеетесь получить...

На самом деле, я столкнулся с этой проблемой раньше, - как обходной путь - основное местоположение использовалось для отслеживания местоположения пользователя для выполнения не связанных функций с его местоположением, которое загружает файлы, но это обходное решение не работает с момента выхода iOS 9; Я даже разместил question, ссылаясь на эту проблему.

Однако, похоже, ваш случай не идентичен тому, с чем я столкнулся, если вы стремитесь:

... создает локальное уведомление для каждого временного местоположения.

тогда вам, возможно, потребуется следовать принципу интеграции с пользовательской системой уведомлений - UNLocationNotificationTrigger:

Географическое местоположение, которое пользователь должен достичь, чтобы включить доставка локального уведомления.

Это также упоминается в видеосеансе (08:59).

Возможно, это может быть не то, что вы ищете, но поскольку у нас нет гарантии, что выполнение фона будет продолжаться, вы можете - как-то - найти способ интегрировать его в свое приложение для достижения желаемой функциональности.

Обновление для iOS 11:

Вам может потребоваться проверить этот ответ для правильного способа запроса доступа к местоположению.

Ответ 4

По звуку его приложение убивается из-за ограничений памяти. Однако он должен быть перезапущен, когда новое место станет доступным, как описано здесь: https://developer.apple.com/documentation/uikit/uiapplicationlaunchoptionskey/1623101-location

Вы должны увидеть application(_:didFinishLaunchingWithOptions:), который вызывается, и ключ "location" должен присутствовать в параметрах запуска. Затем вы сможете воссоздать все, что потребляет места и продолжить запись.

Если он не будет перезапущен, он может быть слишком голоден. Проверьте потребление памяти в приложении и посмотрите, вызывается ли applicationDidReceiveMemoryWarning(_:).

Ответ 5

Я предполагаю, что вы не реализовали фоновую задачу. Вы можете прочитать здесь.

В приведенной выше ссылке в разделе "Реализация долгосрочных задач" указывается №. 3 - это ваша ситуация, поэтому вы можете использовать фоновое обновление местоположения в своем проекте, и для этого вам также необходимо реализовать фоновую задачу.

Существует три способа отслеживания местоположения пользователя (согласно приведенной выше ссылке в разделе "Отслеживание местоположения пользователя"): -

  1. Сервисы определения местоположения только на переднем плане (которые работают в вашем случае)
  2. Служба определения местоположения с существенными изменениями (рекомендуется), но я думаю, что она непригодна для использования в вашем случае, так как вы хотите обновить местоположение пользователя на 10 метров, и она работает на ~ 500 метров, подробнее см. Здесь
  3. Фоновые службы определения местоположения (я думаю, что вы пытаетесь для этого), и решение состоит в том, чтобы добавить фоновую задачу.

    Ниже приведен пример фоновой задачи, и вы можете изменить ее в соответствии с вашими требованиями, она работает для меня с последних 2 часов, и мое приложение по-прежнему обновляет местоположение в фоновом режиме.

В вашем классе AppDelegate обновите функцию ниже, а затем запустите приложение в фоновом режиме.

func applicationDidEnterBackground(_ application: UIApplication) {
    application.beginBackgroundTask(withName: "") {}
}

И ниже мой класс ViewController

import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

    let locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()

        locationManager.delegate = self;
        locationManager.requestAlwaysAuthorization()
        locationManager.desiredAccuracy = kCLLocationAccuracyBest;
        locationManager.allowsBackgroundLocationUpdates = true
        locationManager.distanceFilter = kCLDistanceFilterNone

        Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (timer) in
            self.locationManager.startUpdatingLocation()
        }

    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        print("didUpdateLocations \(Date())")
        self.locationManager.stopUpdatingLocation()
    }

}

Ответ 6

Вам нужно внести некоторые изменения в класс AppDelegate, метод запуска, applicationDidEnterBackground и applicationDidBecomeActive.

Создайте общий интерфейс для менеджера местоположений.

FYI, пожалуйста, пройдите через http://mobileoop.com/getting-location-updates-for-ios-7-and-8-when-the-app-is-killedterminatedsuspended

он может помочь вам. Проверьте комментарии.