web-dev-qa-db-fra.com

Comportement pour l'API de changement de lieu significatif en cas de résiliation / suspension?

Il s'agit de la section de la documentation CLLocationManager décrivant le comportement de l'application avec startMonitoringSignificantLocationChanges :

Si vous démarrez ce service et que votre application est par la suite terminée, le système relance automatiquement l'application en arrière-plan si un nouvel événement arrive. Dans un tel cas, le dictionnaire d'options passé à l'application: didFinishLaunchingWithOptions: la méthode de votre délégué d'application contient la clé UIApplicationLaunchOptionsLocationKey pour indiquer que votre application a été lancée en raison d'un événement de localisation. Lors de la relance, vous devez toujours configurer un objet de gestionnaire d'emplacement et appeler cette méthode pour continuer à recevoir des événements d'emplacement. Lorsque vous redémarrez les services de localisation, l'événement en cours est immédiatement remis à votre délégué. En outre, la propriété d'emplacement de votre objet de gestionnaire d'emplacement est remplie avec l'objet d'emplacement le plus récent avant même de démarrer les services de localisation.

Donc, je comprends que si votre application se termine (et je suppose que si vous n'appelez pas stopMonitoringSignificantLocationChanges de applicationWillTerminate ) vous serez réveillé avec un IApplicationLaunchOptionsLocationKey paramètre à application: didFinishLaunchingWithOptions . À ce stade, vous créez votre CLLocationManager , appelez startMonitoringSignificantLocationChanges et effectuez votre traitement d'emplacement en arrière-plan pendant durée limitée . Je suis donc d'accord avec ce morceau.

Le paragraphe précédent ne parle que de ce qui se passe lorsque l'application est fermée, il ne suggère pas ce que vous faites lorsque l'application est suspendue. La documentation pour didFinishLaunchingWithOptions dit:

L'application suit les mises à jour de l'emplacement en arrière-plan, a été purgée et a maintenant été relancée. Dans ce cas, le dictionnaire contient une clé indiquant que l'application a été relancée en raison d'un nouvel événement de localisation.

Suggérant que vous ne recevrez cet appel que lorsque votre application sera lancée (en raison d'un changement de lieu) après votre résiliation.

Cependant, le paragraphe sur le Service de changement significatif dans le Guide de programmation de la localisation a ce qui suit:

Si vous laissez ce service en cours d'exécution et que votre application est par la suite suspendue ou terminée, le service réveille automatiquement votre application lorsque de nouvelles données de localisation arrivent. Au moment du réveil, votre application est mise en arrière-plan et dispose d'un peu de temps pour traiter les données de localisation. Étant donné que votre application est en arrière-plan, elle doit effectuer un travail minimal et éviter toute tâche (telle que l'interrogation du réseau) qui pourrait l'empêcher de revenir avant l'expiration du délai alloué. Si ce n'est pas le cas, votre demande peut être résiliée.

Cela suggère que vous êtes réveillé avec les données de localisation si votre application a été suspendue, mais ne mentionne pas comment vous êtes réveillé:

  • Est-ce que IApplicationDelegate reçoit un rappel me disant que je reprends un état suspendu dans un état d'arrière-plan?
  • Le gestionnaire d'emplacement (qui a été lyophilisé lorsque l'application a été suspendue) commence-t-il à recevoir locationManager: didUpdateToLocation: fromLocation rappels?
  • Dois-je simplement implémenter du code dans mon didUpdateToLocation message qui vérifie l'état de l'application et effectue un traitement minimal en mode arrière-plan?

En train de rédiger ceci, je pense que je viens de répondre à ma propre question, mais ce serait formidable que ma compréhension de cela soit confirmée par quelqu'un de plus compétent.

109
RedBlueThing

Depuis que j'ai posé cette question, j'ai fait pas mal de tests (principalement dans le train entre la maison et le travail) et j'ai confirmé que le comportement des applications suspendues était comme je le soupçonnais à la fin de la question.

Autrement dit, votre application suspendue est réveillée, vous ne recevez aucun rappel de votre délégué d'application, mais vous recevez vos mises à jour de localisation via votre --- CLLocationManagerDelegate . Vous pouvez détecter que vous exécutez en arrière-plan en vérifiant applicationState, et effectuer un travail limité dans le cas où vous êtes réveillé d'un état suspendu pour effectuer le traitement de l'emplacement.

[UIApplication sharedApplication].applicationState == UIApplicationStateBackground

Je suis arrivé à cette conclusion avec un faisceau de test de localisation que vous êtes invités à télécharger et à essayer. Il s'agit d'une application assez simple qui vous permet d'activer les API de modification importante et de modification GPS via l'interface utilisateur et d'enregistrer toutes les réponses que vous obtenez.

N.B. Le point six de la réponse précédente n'est pas correct. Lyophilisé les applications suspendues reçoivent CLLocationManagerDelegate des rappels lorsqu'elles sont réveillées d'un état suspendu.

80
RedBlueThing

Ma compréhension est la suivante (je suis en train d'écrire une application qui s'appuie sur cette API, mais je n'ai pas suffisamment terminé ce composant pour commencer les tests):

  1. Votre application est exécutée pour la première fois, vous vous inscrivez à startMonitoringSignificantLocationChanges, et fournissez une fonction de rappel. Pendant que votre application est en cours d'exécution, elle appellera ce rappel chaque fois qu'elle recevra un changement significatif.
  2. Si votre application est mise en arrière-plan, UIApplication recevra applicationWillResignActive, suivi de applicationDidEnterBackground.
  3. Si votre application est supprimée alors qu'elle est suspendue en arrière-plan, vous ne serez pas averti; cependant, si votre application est tuée pendant son exécution (premier plan ou arrière-plan à ma connaissance), vous aurez un moment avec applicationWillTerminate. Vous ne pouvez pas demander de temps d'arrière-plan supplémentaire à cette fonction.
  4. En dépit d'être tué en arrière-plan, le système d'exploitation relancera votre application. Si votre application est simplement lancée par le système d'exploitation pour une modification, vous recevrez un appel à application didFinishLaunchingWithOptions:

    if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey])
    

    vous aidera à déterminer si vous revenez d'un changement d'emplacement en arrière-plan.

  5. Si, à la place, vous exécutiez actuellement en arrière-plan et que votre application est relancée manuellement par l'utilisateur, vous recevrez un applicationWillEnterForeground suivi de applicationDidBecomeActive.
  6. Quelle que soit la façon dont cela s'est produit, lorsque votre application est relancée (à moins qu'elle ne s'exécute toujours en arrière-plan à la suite d'une tâche en arrière-plan et que ladite tâche ait commencé à surveiller les modifications), vous devez le dire explicitement à startMonitoringSignificantLocationChanges = à nouveau car le rappel n'est plus attaché après "lyophilisation". Et oui, il vous suffit d'implémenter du code dans didUpdateToLocation une fois que vous avez re-attaché un gestionnaire d'emplacement d'une sorte qui revient une fois revenu de l'état suspendu.

C'est ce que je fais avec mon développement de code en ce moment. Comme je l'ai mentionné précédemment, je ne suis pas tout à fait prêt à tester cela sur un appareil, donc je ne peux pas dire si j'ai tout interprété correctement, alors commentateurs, n'hésitez pas à me corriger (même si j'ai fait une lecture substantielle sujet).

Oh, et si par malchance, vous sortez une application qui fait ce que je veux que je fasse, je pourrais pleurer :)

Bonne chance!

25
Aaron

Si l'application est évoquée à partir de l'état suspendu à la suite d'un changement d'emplacement, l'application se lancera en arrière-plan.

Tous les objets seront actifs et vous recevrez la mise à jour de l'emplacement dans le délégué existant.

1
Anshu