web-dev-qa-db-fra.com

Le suivi de la position s'arrête après un certain temps lorsque l'application est en arrière-plan

J'ai créé une application simple qui suit l'emplacement de l'utilisateur et crée une notification locale pour chaque mise à jour de l'emplacement.

J'ai activé les modes d'arrière-plan ci-dessous,

enter image description here

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

J'ai mis la chaîne pour NSLocationAlwaysUsageDescription et demande la permission. L'utilisateur accorde une autorisation pour toujours l'utiliser lors du premier chargement de l'application.


Cela fonctionne bien lorsque l'application est au premier plan, lorsqu'elle passe en arrière-plan fonctionne toujours au moins dans une plage de temps de 5-40 minutes qui peut être modifiée par la batterie ou autre applications ouvertes.

Le problème est pourquoi il cesse de fonctionner, ne devrait-il pas continuer à fonctionner?

Je n'ai jamais vu de limite de temps dans Apple docs.

23
ocanal

Passez à des mises à jour de localisation importantes lorsque l'application passe en arrière-plan. iOS déchargera l'application si elle reste en vie indéfiniment en arrière-plan.

locationManager.pausesLocationUpdatesAutomatically = false
23
Vimal Saifudin

Réduisez la précision

Définissez la propriété desiredAccuracy de l'objet gestionnaire d'emplacement

self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation

Vous pouvez utiliser l'une des constantes CLLocationAccuracy

IMPORTANT

Par défaut, les mises à jour d'emplacement standard sur les appareils iOS s'exécutent avec un niveau de précision optimal. Modifiez ces paramètres en fonction des besoins de votre application. Sinon, votre application gaspillera inutilement de l'énergie.


Pause automatique

Définissez la propriété pausesLocationUpdatesAutomatically de l'objet gestionnaire d'emplacement sur true

self.locationManager.pausesLocationUpdatesAutomatically = true

IMPORTANT

Pour les applications qui ont une autorisation d'utilisation, une pause dans les mises à jour d'emplacement met fin à l'accès aux changements d'emplacement jusqu'à ce que l'application soit relancée et puisse redémarrer ces mises à jour. Si vous ne souhaitez pas que les mises à jour de localisation s'arrêtent complètement, envisagez de désactiver cette propriété et de modifier la précision de la localisation sur kCLLocationAccuracyThreeKilometers lorsque votre application passe en arrière-plan. Cela vous permet de continuer à recevoir les mises à jour de position d'une manière économe en énergie.


Autoriser les mises à jour en arrière-plan

Définissez la propriété allowsBackgroundLocationUpdates de l'objet gestionnaire d'emplacement sur true

self.locationManager.allowsBackgroundLocationUpdates = true

Les applications qui souhaitent recevoir des mises à jour d'emplacement lorsqu'elles sont suspendues doivent inclure la clé UIBackgroundModes (avec la valeur d'emplacement) dans le fichier Info.plist de leur application et définir la valeur de cette propriété sur true. La présence de la clé UIBackgroundModes avec la valeur d'emplacement est requise pour les mises à jour en arrière-plan


Spécifiez un type d'activité

Définissez la propriété activityType pour indiquer à Core Location quel type d'activité de localisation votre application effectue à un moment donné

self.locationManager.activityType = .automotiveNavigation 

Vous pouvez utiliser l'un des cas CLActivityType


Différer la mise à jour de l'emplacement

Sur les appareils pris en charge avec du matériel GPS, vous pouvez laisser le gestionnaire de localisation différer la livraison des mises à jour de localisation lorsque votre application est en arrière-plan. Par exemple, une application de fitness qui suit la position de l'utilisateur sur un sentier de randonnée peut différer les mises à jour jusqu'à ce que l'utilisateur ait parcouru une certaine distance ou une certaine période de temps.


7
Adrian Bobrowski

Après avoir recherché des références (parler de toute limitation), je suppose que Apple Core Location Best Practices session vidéo pourrait être utile! À 06:53 parler de l'emplacement standard en arrière-plan:

en outre, Core Location n'entreprendra aucune action pour garantir que votre application continue de fonctionner, donc si vous avez exécuté en arrière-plan pour une raison quelconque et que vous décidez de démarrer une session de localisation, vous pouvez obtenir des mises à jour, mais vous pouvez également être suspendu avant de recevoir toutes les informations que vous espérez recevoir ...

En fait, j'ai déjà rencontré ce problème, - comme solution de contournement - l'emplacement principal a été utilisé pour garder un suivi de l'emplacement de l'utilisateur pour effectuer des fonctionnalités non liées à son emplacement - qui télécharge des fichiers -, mais cette solution de contournement n'a pas fonctionné depuis iOS 9 est sorti; J'ai même posté une question faisant référence à ce problème.

Cependant, il semble que votre cas ne soit pas identique à celui auquel j'ai été confronté, si vous visez à:

... crée une notification locale pour chaque mise à jour de l'emplacement.

alors vous devrez peut-être suivre l'approche d'intégration avec Framework de notification utilisateur - NLocationNotificationTrigger :

L'emplacement géographique que l'utilisateur doit atteindre pour permettre la remise d'une notification locale.

Il est également mentionné dans la session vidéo (08:59).

Probablement, ce n'est peut-être pas ce que vous recherchez, mais comme nous n'avons aucune garantie que l'exécution en arrière-plan continuera de s'exécuter, vous pourrez peut-être trouver un moyen de l'intégrer dans votre application pour obtenir la fonctionnalité souhaitée.

Mise à jour pour iOS 11:

Vous devrez peut-être vérifier cette réponse pour savoir comment demander l'accès à l'emplacement.

2
Ahmad F

Par le son, l'application est tuée en raison de contraintes de mémoire. Il doit cependant être relancé lorsqu'un nouvel emplacement devient disponible, comme décrit ici: https://developer.Apple.com/documentation/uikit/uiapplicationlaunchoptionskey/1623101-location

Vous devriez voir application(_:didFinishLaunchingWithOptions:) être appelé, et la touche 'location' devrait être présente dans les options de lancement. Vous pourrez ensuite recréer ce qui consomme les emplacements et continuer l'enregistrement.

S'il n'est pas relancé, il pourrait être trop gourmand en mémoire. Vérifiez la consommation de mémoire de l'application et voyez si applicationDidReceiveMemoryWarning(_:) est appelée.

1
Tom Durrant

Je suppose que vous n'avez pas implémenté la tâche d'arrière-plan. Vous pouvez lire ici .

Dans le lien ci-dessus sous la section "Implémentation de tâches de longue durée" point no. 3 est votre situation, il est donc valide que vous pouvez utiliser la mise à jour de l'emplacement en arrière-plan dans votre projet et pour cela, vous devez également implémenter une tâche en arrière-plan.

Il existe trois façons de suivre l'emplacement de l'utilisateur (comme indiqué ci-dessus dans la section "Suivi de l'emplacement de l'utilisateur" ): -

  1. Services de localisation au premier plan uniquement (qui fonctionne dans votre cas)
  2. Le service de localisation à changement significatif ( Recommandé ), mais je pense qu'il n'est pas utilisable dans votre cas car vous souhaitez mettre à jour la position de l'utilisateur par 10 mètres et fonctionne pour ~ 500 mètres, pour plus s'il vous plaît voir ici
  3. Services de localisation en arrière-plan (je pense que vous essayez pour cela) et la solution consiste à ajouter une tâche en arrière-plan.

    Voici un exemple de tâche en arrière-plan et vous pouvez modifier selon vos besoins, cela fonctionne pour moi depuis les 2 dernières heures et mon application met toujours à jour l'emplacement en arrière-plan.

. Dans votre classe AppDelegate, veuillez mettre à jour la fonction ci-dessous, puis exécutez votre application en arrière-plan.

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

Et ci-dessous est ma classe 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()
    }

}
0
Anand Suthar