J'écris une application qui nécessite des mises à jour de l'emplacement en arrière-plan avec une grande précision et une faible fréquence . La solution semble être une tâche NSTimer en arrière-plan qui démarre les mises à jour du gestionnaire d'emplacement, qui s'arrête immédiatement. Cette question a déjà été posée:
iOS Pas le problème typique du minuteur de suivi de l'emplacement en arrière-plan
Minuterie d'arrière-plan iOS de longue durée avec mode d'arrière-plan "emplacement"
Service d'arrière-plan iOS à plein temps basé sur le suivi de l'emplacement
mais je n'ai pas encore fait fonctionner un exemple minimum . Après avoir essayé toutes les permutations des réponses acceptées ci-dessus, j'ai établi un point de départ. Entrer en arrière-plan:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
self.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"ending background task");
[[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
self.bgTask = UIBackgroundTaskInvalid;
}];
self.timer = [NSTimer scheduledTimerWithTimeInterval:60
target:self.locationManager
selector:@selector(startUpdatingLocation)
userInfo:nil
repeats:YES];
}
et la méthode des délégués:
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
NSLog(@"%@", newLocation);
NSLog(@"background time: %f", [UIApplication sharedApplication].backgroundTimeRemaining);
[self.locationManager stopUpdatingLocation];
}
Le comportement actuel est que les backgroundTimeRemaining
décrémentations de 180 secondes à zéro (lors de la journalisation de l'emplacement), puis le gestionnaire d'expiration s'exécute et aucune autre mise à jour d'emplacement n'est générée. Comment puis-je modifier le code ci-dessus afin de recevoir des mises à jour périodiques de l'emplacement en arrière-plan indéfiniment ?
Mise à jour : je cible iOS 7 et il semble y avoir des preuves que les tâches d'arrière-plan se comportent différemment:
Démarrez Location Manager dans iOS 7 à partir de la tâche en arrière-plan
la source
Réponses:
Il semble que
stopUpdatingLocation
ce soit ce qui déclenche la minuterie du chien de garde en arrière-plan, alors je l'ai remplacédidUpdateLocation
par:qui semble éteindre efficacement le GPS. Le sélecteur du fond
NSTimer
devient alors:Tout ce que je fais est de basculer périodiquement la précision pour obtenir une coordonnée de haute précision toutes les quelques minutes et, comme le
locationManager
n'a pas été arrêté,backgroundTimeRemaining
reste à sa valeur maximale. Cela a réduit la consommation de la batterie d'environ 10% par heure (avec une constantekCLLocationAccuracyBest
en arrière-plan) à ~ 2% par heure sur mon appareil.la source
J'ai écrit une application en utilisant les services de localisation, l'application doit envoyer l'emplacement toutes les 10 secondes. Et cela a très bien fonctionné.
Utilisez simplement la méthode " allowDeferredLocationUpdatesUntilTraveled: timeout ", en suivant la doc d'Apple.
Les étapes sont les suivantes:
Requis: enregistrez le mode d'arrière-plan pour l'emplacement de mise à jour.
1. Créez LocationManger et startUpdatingLocation, avec précision et filteredDistance comme vous le souhaitez:
2. Pour que l'application continue de fonctionner pour toujours à l'aide de la méthode "allowDeferredLocationUpdatesUntilTraveled: timeout" en arrière-plan, vous devez redémarrer updateLocation avec un nouveau paramètre lorsque l'application passe en arrière-plan, comme ceci:
3. L' application est mise à jourLocations normalement avec le rappel "locationManager: didUpdateLocations:":
4. Mais vous devez gérer les données dans le callback "locationManager: didFinishDeferredUpdatesWithError:" pour vos besoins
5. REMARQUE: je pense que nous devrions réinitialiser les paramètres de LocationManager chaque fois que l'application bascule entre le mode arrière-plan / avant-plan.
la source
allowsBackgroundLocationUpdates = YES
etrequestAlwaysAuthorization
ourequestWhenInUseAuthorization
. Par exemple: `CLLocationManager * locationManager = [[CLLocationManager alloc] init]; locationManager.delegate = soi; locationManager.allowsBackgroundLocationUpdates = OUI; [locationManager requestAlwaysAuthorization]; [locationManager startUpdatingLocation]; `Si vous avez le
UIBackgroundModes
dans votre plist aveclocation
clé, vous n'avez pas besoin d'utiliser labeginBackgroundTaskWithExpirationHandler
méthode. C'est redondant. De plus, vous ne l'utilisez pas correctement (voir ici ), mais c'est sans intérêt puisque votre plist est défini.Avec
UIBackgroundModes location
dans le plist, l'application continuera à s'exécuter en arrière-plan indéfiniment tant qu'elleCLLocationManger
est en cours d'exécution. Si vous appelezstopUpdatingLocation
en arrière-plan, l'application s'arrêtera et ne redémarrera pas.Vous pourriez peut-être appeler
beginBackgroundTaskWithExpirationHandler
juste avant d'appelerstopUpdatingLocation
, puis après avoir appelé,startUpdatingLocation
vous pouvez appeler leendBackgroundTask
pour le garder en arrière-plan pendant que le GPS est arrêté, mais je n'ai jamais essayé cela - c'est juste une idée.Une autre option (que je n'ai pas essayée) est de faire fonctionner le gestionnaire de localisation en arrière-plan, mais une fois que vous obtenez un emplacement précis, changez la
desiredAccuracy
propriété à 1000 m ou plus pour permettre à la puce GPS de s'éteindre (pour économiser la batterie). Puis 10 minutes plus tard, lorsque vous avez besoin d'une autre mise à jour de l'emplacement, changez ledesiredAccuracy
dos à 100m pour allumer le GPS jusqu'à ce que vous obteniez un emplacement précis, répétez.Lorsque vous appelez
startUpdatingLocation
le gestionnaire de l'emplacement, vous devez lui donner le temps d'obtenir un poste. Vous ne devez pas appeler immédiatementstopUpdatingLocation
. Nous le laissons fonctionner pendant un maximum de 10 secondes ou jusqu'à ce que nous obtenions un emplacement de haute précision non mis en cache.Vous devez filtrer les emplacements mis en cache et vérifier l'exactitude de l'emplacement que vous obtenez pour vous assurer qu'il répond à votre précision minimale requise (voir ici ). La première mise à jour que vous recevez peut dater de 10 minutes ou 10 jours. La première précision que vous obtenez peut être de 3000 m.
Pensez plutôt à utiliser les API de changement d'emplacement importantes. Une fois que vous avez reçu la notification de changement significatif, vous pouvez commencer
CLLocationManager
pendant quelques secondes pour obtenir une position de haute précision. Je ne suis pas certain, je n'ai jamais utilisé les services de changement de lieu importants.la source
CoreLocation
référence Apple semble recommander l'utilisation debeginBackgroundTaskWithExpirationHandler
lors du traitement des données de localisation en arrière-plan: "Si une application iOS a besoin de plus de temps pour traiter les données de localisation, elle peut demander plus de temps d'exécution en arrière-plan en utilisant la méthode beginBackgroundTaskWithName: expirationHandler: de la classe UIApplication." - developer.apple.com/library/ios/documentation/UserExperience/…locationManagerDidPauseLocationUpdates
. J'ai vérifié ce comportement 10 fois!Lorsqu'il est temps de démarrer le service de localisation et d'arrêter la tâche d'arrière-plan, la tâche d'arrière-plan doit être arrêtée avec un délai (1 seconde devrait suffire). Sinon, le service de localisation ne démarrera pas. Le service de localisation doit également rester activé pendant quelques secondes (par exemple, 3 secondes).
Il existe un APScheduledLocationManager cocoapod qui permet d'obtenir des mises à jour de localisation en arrière-plan toutes les n secondes avec la précision de localisation souhaitée.
Le référentiel contient également un exemple d'application écrite en Swift 3.
la source
Pourquoi ne pas essayer avec l'
startMonitoringSignificantLocationChanges:
API? Il se déclenche définitivement avec moins de fréquence et la précision est raisonnablement bonne. De plus, il présente beaucoup plus d'avantages que l'utilisation d'autreslocationManager
API.Beaucoup plus concernant cette API ont déjà été discutés sur ce lien
la source
This interface delivers new events only when it detects changes to the device’s associated cell towers
Vous devez ajouter le mode de mise à jour de l'emplacement dans votre application en ajoutant la clé suivante dans votre info.plist.
didUpdateToLocation
sera appelée (même lorsque votre application est en arrière-plan). Vous pouvez effectuer n'importe quoi sur les bases de cet appel de méthodela source
Après iOS 8, il y a plusieurs changements dans la récupération en arrière-plan du framework CoreLocation et les mises à jour effectuées par Apple.
1) Apple introduit la demande AlwaysAuthorization pour récupérer la mise à jour de l'emplacement dans l'application.
2) Apple introduit backgroundLocationupdates pour récupérer l'emplacement à partir de l'arrière-plan dans iOS.
Pour récupérer l'emplacement en arrière-plan, vous devez activer la mise à jour de l'emplacement dans Capabilities of Xcode.
la source
Pour utiliser les services de localisation standard lorsque l'application est en arrière-plan, vous devez d'abord activer les modes d'arrière-plan dans l'onglet Capacités des paramètres Cible, puis sélectionner Mises à jour de l'emplacement.
Ou ajoutez-le directement à Info.plist .
Ensuite, vous devez configurer le CLLocationManager
Objectif c
Rapide
Réf: https://medium.com/@javedmultani16/location-service-in-the-background-ios-942c89cd99ba
la source
la source