web-dev-qa-db-fra.com

Les services de localisation en arrière-plan ne fonctionnent pas sous iOS 7

J'ai récemment mis à niveau mes appareils iOS pour qu'ils utilisent iOS 7. L'une des applications que nous développons utilise des services de localisation en arrière-plan pour suivre l'emplacement de l'appareil et tous nos testeurs ont signalé que l'application ne semble plus suivre en arrière-plan sous iOS. 7. 

Nous avons vérifié que l’arrière-plan de l’application est activé dans les paramètres de l’appareil et que la construction précédente fonctionnait parfaitement sous iOS 6. Même si l’appareil était réinitialisé, l’application redémarrerait après une mise à jour de la localisation. 

Y a-t-il autre chose à faire pour que cela fonctionne sous iOS 7? 

34
Alan Samet

Voici la solution que j’utilisais pour obtenir un emplacement continu à partir d’appareils iOS 7, qu’il soit au premier plan ou en arrière-plan.

Vous pouvez trouver la solution complète et les explications sur le blog et également sur github: -

  1. Programmation de mise à jour d'emplacement en arrière-plan pour iOS 7 et 8

  2. Projet Github: Programmation de mise à jour d'emplacement en arrière-plan pour iOS 7 et 8

Méthodes et explications: -

  1. Je redémarre le gestionnaire d'emplacement toutes les minutes dans la fonction didUpdateLocations

  2. J'autorise le gestionnaire d'emplacement à obtenir les emplacements de l'appareil pendant 10 secondes avant de l'éteindre (pour économiser la batterie).

Code partiel ci-dessous: -

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{

for(int i=0;i<locations.count;i++){
    CLLocation * newLocation = [locations objectAtIndex:i];
    CLLocationCoordinate2D theLocation = newLocation.coordinate;
    CLLocationAccuracy theAccuracy = newLocation.horizontalAccuracy;
    NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];

    if (locationAge > 30.0)
        continue;

    //Select only valid location and also location with good accuracy
    if(newLocation!=nil&&theAccuracy>0
       &&theAccuracy<2000
       &&(!(theLocation.latitude==0.0&&theLocation.longitude==0.0))){
        self.myLastLocation = theLocation;
        self.myLastLocationAccuracy= theAccuracy;
        NSMutableDictionary * dict = [[NSMutableDictionary alloc]init];
        [dict setObject:[NSNumber numberWithFloat:theLocation.latitude] forKey:@"latitude"];
        [dict setObject:[NSNumber numberWithFloat:theLocation.longitude] forKey:@"longitude"];
        [dict setObject:[NSNumber numberWithFloat:theAccuracy] forKey:@"theAccuracy"];
        //Add the vallid location with good accuracy into an array
        //Every 1 minute, I will select the best location based on accuracy and send to server
        [self.shareModel.myLocationArray addObject:dict];
    }
}

//If the timer still valid, return it (Will not run the code below)
if (self.shareModel.timer)
    return;

self.shareModel.bgTask = [BackgroundTaskManager sharedBackgroundTaskManager];
[self.shareModel.bgTask beginNewBackgroundTask];

//Restart the locationMaanger after 1 minute
self.shareModel.timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self
                                                       selector:@selector(restartLocationUpdates)
                                                       userInfo:nil
                                                        repeats:NO];

//Will only stop the locationManager after 10 seconds, so that we can get some accurate locations
//The location manager will only operate for 10 seconds to save battery
NSTimer * delay10Seconds;
delay10Seconds = [NSTimer scheduledTimerWithTimeInterval:10 target:self
                                                selector:@selector(stopLocationDelayBy10Seconds)
                                                userInfo:nil
                                                 repeats:NO];
 }

Mise à jour en mai 2014: J'ai reçu quelques demandes d'ajout d'échantillons de codes lors de l'envoi de l'emplacement au serveur pendant un certain intervalle de temps. J'ai ajouté les exemples de codes et combiné un correctif pour BackgroundTaskManager afin de résoudre un problème lié à l'arrière-plan s'exécutant sur une longue période. Si vous avez des questions, n'hésitez pas à vous joindre à nous pour une discussion ici: Programmation de la mise à jour de l'emplacement en arrière-plan pour iOS 7 avec mise à jour de l'emplacement sur le serveur

Mise à jour janvier 2015: si vous souhaitez obtenir la mise à jour de la localisation même lorsque l'application est suspendue, veuillez consulter: Obtenir les mises à jour de la localisation pour l'application iOS même après suspension

47
Ricky

Si vous regardez la vidéo WWDC 2013 Session n ° 204 - Nouveautés du multitâche PDF, la page 15 indique clairement que les applications ne se lancent pas en arrière-plan si l'utilisateur le supprime depuis le commutateur d'applications. S'il vous plaît voir l'image,

enter image description here

18
Obj-Swift

Je pense qu'ils ont fait une optimisation (probablement à l'aide de capteurs de mouvement), pour détecter un positionnement "relativement" stationnaire du téléphone et arrêter les mises à jour de localisation. Ce n'est qu'une spéculation, mais mes tests montrent actuellement:

  1. Mises à jour de l'emplacement de départ; (testé avec une précision de 10 et 100 mètres, 3 fois chacun)
  2. Éteignez l'écran de l'appareil pour mettre l'application en arrière-plan.
  3. Laissez l’appareil immobile (par exemple sur un bureau) pendant 30 min.

Les données que j’enregistre montrent que les mises à jour géographiques cessent d’apparaître après environ 15m et 30s. Tous les autres traitements en arrière-plan sont également terminés.

Mon appareil est un iPhone 5 avec iOS 7.

Je suis sûr à 95% que ce n'était pas le cas sur iOS 6/6.1. Où obtenir des mises à jour géographiques avec une précision de 100 m était utilisé pour vous offrir un fonctionnement pratiquement continu en arrière-plan.

Mettre à jour

Si vous redémarrez le gestionnaire d'emplacement toutes les 8 minutes, il devrait être exécuté en permanence.

Mise à jour # 2

Je n'ai pas encore testé cela, mais voici comment je l'ai redémarré lorsque j'ai écrit le message. J'espère que ceci est utile.

- (void)tryRestartLocationManager
{
    NSTimeInterval now = [[NSDate date] timeIntervalSince1970];

    int seconds = round(floor(now - locationManagerStartTimestamp));

    if ( seconds > (60 * 8) ) {
        [locationManager stopUpdatingLocation];
        [locationManager startUpdatingLocation];
        locationManagerStartTimestamp = now;
    }
}
16
Nikolay Tsenkov

Une de mes applications iOS doit envoyer la mise à jour de la localisation au serveur à intervalles réguliers et l'approche suivante a fonctionné pour nous ....

À partir de iOS 7:

  • une application doit déjà avoir déjà utilisé les services de localisation (startUpdatingLocation) AVANT d'avoir été mis à l'arrière-plan pour que soit éligible pour l'exécution en arrière-plan
  • le délai de grâce en arrière-plan a été réduit de 10 minutes à 3 minutes
  • l’arrêt des mises à jour d’emplacement (via stopUpdatingLocation) lancera le compte à rebours de 3 minute backgroundTimeRemaining.
  • les mises à jour d'emplacement de départ alors que vous êtes déjà en arrière-plan ne seront pas réinitialisez le paramètre backgroundTimeRemaining.

Donc, NE PAS ARRÊTER les mises à jour d'emplacement à tout moment ... Au lieu de cela, préférez utiliser la précision nécessaire (emplacement précis par rapport à l'emplacement approximatif). Emplacement grossier ne consomme pas beaucoup de batterie ... donc cette solution résout votre problème.

Après de nombreuses recherches en ligne, nous avons trouvé un lien offrant une solution viable pour iOS 7. La solution est la suivante:

  • Alors que l'application est toujours au premier plan, démarrez les mises à jour d'emplacement .__ (startUpdatingLocation), mais définissez les filtres de précision et de distance sur Des mises à jour très détaillées (par exemple 3 km). Il est important de le faireau premier plan (dans applicationDidEnterBackground, il est trop tard).
  • Lorsqu'une résolution fine est requise, définissez temporairement les filtres de précision Et de distance pour obtenir le meilleur emplacement possible, puis redéfinissez-les sur les valeurs définies pour le parcours, sans arrêter les mises à jour de l'emplacement
  • Étant donné que les mises à jour d'emplacement sont toujours activées, l'application ne sera pas suspendue lorsqu'elle sera en arrière-plan.

Et assurez-vous d’ajouter ce qui suit à votre Info.plist «Lieu» de votre application, à la clé UIBackgroundModes «Services de localisation» et à votre «GPS» à la clé UIRequiredDeviceCapabilities.

Crédits: http://gooddevbaddev.wordpress.com/2013/10/22/ios-7-running-location-based-apps-in-the-background/

7
androidExplorer

J'ai trouvé un autre fil Démarrer Location Manager dans iOS 7 à partir de la tâche en arrière-plan Sash a mentionné que 

J'ai trouvé le problème/solution. Lorsqu'il est temps de démarrer le service de localisation et d'arrêter la tâche en arrière-plan, celle-ci doit être arrêtée avec un délai (défini à 1 seconde). Sinon, le service de localisation ne démarrera pas.

Quelqu'un peut-il essayer et vérifier? 

Nikolay, pouvez-vous coller votre code ici? J'ai essayé de redémarrer le gestionnaire d'emplacement toutes les 8 minutes, mais celui-ci ne fonctionne pas en continu.

Mettre à jour:

Après avoir cherché haut et bas, j'ai trouvé la solution du forum Apple!

Dans iOS 7, vous ne pouvez pas démarrer le service de localisation en arrière-plan. Si vous souhaitez que le service de localisation continue à fonctionner en arrière-plan, vous devez le démarrer au premier plan et continuer à s'exécuter en arrière-plan. 

Si vous étiez comme moi, arrêtez le service de localisation et utilisez la minuterie pour le redémarrer en arrière-plan, cela ne fonctionnera PAS. 

Pour plus d'informations, vous pouvez regarder les 8 premières minutes de la vidéo 307 de WWDC 2013: https://developer.Apple.com/wwdc/videos/

Mise à jour de février 2014: Je peux obtenir l'emplacement en continu depuis un appareil utilisant iOS 7 après plusieurs mois d'essai. Vous trouverez la réponse complète ici: Les services de localisation en arrière-plan ne fonctionnent pas sous iOS 7

5
Ricky

L'icône de la barre d'état est-elle allumée? C’est un comportement étrange que j’avais eu aussi . Vérifiez ma question: startMonitoringSignificantLocationChanges mais après un certain temps, didUpdateLocations n’est plus appelé

J'ai découvert que les changements d'emplacement importants étaient activés mais que simplement arrêter et redémarrer le service (pour les changements importants) ne déclenchait pas de nouveaux emplacements.

1
Mr. Cobblepot

Vous devez définir la propriété pausesLocationUpdatesAutomatically de CLLocationManagerclass sur false pour empêcher le système de suspendre les mises à jour d'emplacement.

0
Tibin Thomas