Procédure pas à pas - Emplacement d’arrière-plan dans Xamarin.iOS
Dans cet exemple, nous allons créer une application d’emplacement iOS qui imprime des informations sur notre emplacement actuel : latitude, longitude et autres paramètres à l’écran. Cette application montre comment effectuer correctement les mises à jour d’emplacement pendant que l’application est active ou en arrière-plan.
Cette procédure pas à pas décrit certains concepts clés d’arrière-plan, notamment l’inscription d’une application en tant qu’application nécessaire en arrière-plan, la suspension des mises à jour de l’interface utilisateur lorsque l’application est en arrière-plan et l’utilisation des méthodes et WillEnterForeground
AppDelegate
des WillEnterBackground
méthodes.
Configuration de l’application
Tout d’abord, créez une application iOS > App > Single View (C#). Appelez-le Emplacement et vérifiez que l’iPad et l’iPhone ont été sélectionnés.
Une application d’emplacement se qualifie comme une application nécessaire en arrière-plan dans iOS. Inscrivez l’application en tant qu’application Emplacement en modifiant le fichier Info.plist pour le projet.
Sous Explorateur de solutions, double-cliquez sur le fichier Info.plist pour l’ouvrir, puis faites défiler vers le bas de la liste. Placez une vérification à la fois par les cases Activer les modes d’arrière-plan et les cases Mises à jour d’emplacement.
Dans Visual Studio pour Mac, il se présente comme suit :
Dans Visual Studio, Info.plist doit être mis à jour manuellement en ajoutant la paire clé/valeur suivante :
<key>UIBackgroundModes</key> <array> <string>location</string> </array>
Maintenant que l’application est inscrite, elle peut obtenir des données d’emplacement à partir de l’appareil. Dans iOS, la
CLLocationManager
classe est utilisée pour accéder aux informations d’emplacement et peut déclencher des événements qui fournissent des mises à jour d’emplacement.Dans le code, créez une classe appelée
LocationManager
qui fournit un emplacement unique pour différents écrans et code pour s’abonner aux mises à jour d’emplacement. Dans laLocationManager
classe, créez une instance de l’appeléCLLocationManager
LocMgr
:public class LocationManager { protected CLLocationManager locMgr; public LocationManager () { this.locMgr = new CLLocationManager(); this.locMgr.PausesLocationUpdatesAutomatically = false; // iOS 8 has additional permissions requirements if (UIDevice.CurrentDevice.CheckSystemVersion (8, 0)) { locMgr.RequestAlwaysAuthorization (); // works in background //locMgr.RequestWhenInUseAuthorization (); // only in foreground } if (UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) { locMgr.AllowsBackgroundLocationUpdates = true; } } public CLLocationManager LocMgr { get { return this.locMgr; } } }
Le code ci-dessus définit un certain nombre de propriétés et d’autorisations sur la classe CLLocationManager :
PausesLocationUpdatesAutomatically
: il s’agit d’une valeur booléenne qui peut être définie selon que le système est autorisé à suspendre les mises à jour d’emplacement. Sur un appareil, il atrue
la valeur par défaut , ce qui peut entraîner l’arrêt de l’obtention des mises à jour d’emplacement en arrière-plan après environ 15 minutes.RequestAlwaysAuthorization
- Vous devez passer cette méthode pour permettre à l’utilisateur de l’application d’autoriser l’accès à l’emplacement en arrière-plan.RequestWhenInUseAuthorization
peut également être transmis si vous souhaitez donner à l’utilisateur la possibilité d’autoriser l’accès à l’emplacement uniquement lorsque l’application est au premier plan.AllowsBackgroundLocationUpdates
: il s’agit d’une propriété booléenne, introduite dans iOS 9 qui peut être définie pour permettre à une application de recevoir des mises à jour d’emplacement lorsqu’elle est suspendue.
Important
IOS 8 (et ultérieur) nécessite également une entrée dans le fichier Info.plist pour afficher l’utilisateur dans le cadre de la demande d’autorisation.
Ajoutez des clés Info.plist pour les types d’autorisations requis par l’application avec
NSLocationAlwaysAndWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
NSLocationWhenInUseUsageDescription
une chaîne qui sera affichée à l’utilisateur dans l’alerte qui demande l’accès aux données d’emplacement.IOS 9 nécessite que lors de l’utilisation
AllowsBackgroundLocationUpdates
de Info.plist inclut la cléUIBackgroundModes
avec la valeurlocation
. Si vous avez terminé l’étape 2 de cette procédure pas à pas, celle-ci doit déjà se trouver dans votre fichier Info.plist.À l’intérieur de la
LocationManager
classe, créez une méthode appeléeStartLocationUpdates
avec le code suivant. Ce code montre comment commencer à recevoir des mises à jour d’emplacement à partir desCLLocationManager
éléments suivants :if (CLLocationManager.LocationServicesEnabled) { //set the desired accuracy, in meters LocMgr.DesiredAccuracy = 1; LocMgr.LocationsUpdated += (object sender, CLLocationsUpdatedEventArgs e) => { // fire our custom Location Updated event LocationUpdated (this, new LocationUpdatedEventArgs (e.Locations [e.Locations.Length - 1])); }; LocMgr.StartUpdatingLocation(); }
Il y a plusieurs choses importantes qui se produisent dans cette méthode. Tout d’abord, nous effectuons une vérification pour voir si l’application a accès aux données d’emplacement sur l’appareil. Nous vérifions cela en appelant
LocationServicesEnabled
leCLLocationManager
. Cette méthode retourne false si l’utilisateur a refusé l’accès de l’application aux informations d’emplacement.Ensuite, indiquez au gestionnaire de localisation la fréquence à mettre à jour.
CLLocationManager
fournit de nombreuses options pour filtrer et configurer des données d’emplacement, notamment la fréquence des mises à jour. Dans cet exemple, définissez laDesiredAccuracy
valeur à mettre à jour chaque fois que l’emplacement change d’un compteur. Pour plus d’informations sur la configuration de la fréquence de mise à jour de l’emplacement et d’autres préférences, reportez-vous à la référence de la classe CLLocationManager dans la documentation Apple.Enfin, appelez
StartUpdatingLocation
l’instanceCLLocationManager
. Cela indique au gestionnaire d’emplacements d’obtenir un correctif initial sur l’emplacement actuel et de commencer à envoyer des mises à jour
Jusqu’à présent, le gestionnaire d’emplacements a été créé, configuré avec les types de données que nous voulons recevoir et a déterminé l’emplacement initial. À présent, le code doit restituer les données d’emplacement à l’interface utilisateur. Nous pouvons le faire avec un événement personnalisé qui prend un CLLocation
argument :
// event for the location changing
public event EventHandler<LocationUpdatedEventArgs>LocationUpdated = delegate { };
L’étape suivante consiste à s’abonner aux mises à jour d’emplacement à partir du CLLocationManager
, et à déclencher l’événement personnalisé LocationUpdated
lorsque de nouvelles données d’emplacement sont disponibles, en passant l’emplacement en tant qu’argument. Pour ce faire, créez une classe LocationUpdateEventArgs.cs. Ce code est accessible dans l’application principale et retourne l’emplacement de l’appareil lorsque l’événement est déclenché :
public class LocationUpdatedEventArgs : EventArgs
{
CLLocation location;
public LocationUpdatedEventArgs(CLLocation location)
{
this.location = location;
}
public CLLocation Location
{
get { return location; }
}
}
Interface utilisateur
Utilisez le Générateur d’interface Xcode pour générer l’écran qui affiche les informations d’emplacement. Double-cliquez sur le fichier Main.storyboard pour commencer.
Dans le storyboard, faites glisser plusieurs étiquettes sur l’écran pour agir en tant qu’espaces réservés pour les informations d’emplacement. Dans cet exemple, il existe des étiquettes pour la latitude, la longitude, l’altitude, le cours et la vitesse.
Pour plus d’informations, consultez Conception d’interfaces utilisateur avec Xcode.
Dans le Panneau Solution, double-cliquez sur le
ViewController.cs
fichier et modifiez-le pour créer une instance du LocationManager et appelez-leStartLocationUpdates
. Modifiez le code comme suit :#region Computed Properties public static bool UserInterfaceIdiomIsPhone { get { return UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone; } } public static LocationManager Manager { get; set;} #endregion #region Constructors public ViewController (IntPtr handle) : base (handle) { // As soon as the app is done launching, begin generating location updates in the location manager Manager = new LocationManager(); Manager.StartLocationUpdates(); } #endregion
Cela démarre les mises à jour de l’emplacement au démarrage de l’application, bien qu’aucune donnée ne s’affiche.
Maintenant que les mises à jour de l’emplacement sont reçues, mettez à jour l’écran avec les informations d’emplacement. La méthode suivante obtient l’emplacement de notre
LocationUpdated
événement et l’affiche dans l’interface utilisateur :#region Public Methods public void HandleLocationChanged (object sender, LocationUpdatedEventArgs e) { // Handle foreground updates CLLocation location = e.Location; LblAltitude.Text = location.Altitude + " meters"; LblLongitude.Text = location.Coordinate.Longitude.ToString (); LblLatitude.Text = location.Coordinate.Latitude.ToString (); LblCourse.Text = location.Course.ToString (); LblSpeed.Text = location.Speed.ToString (); Console.WriteLine ("foreground updated"); } #endregion
Nous devons toujours nous abonner à l’événement LocationUpdated
dans notre AppDelegate et appeler la nouvelle méthode pour mettre à jour l’interface utilisateur. Ajoutez le code ViewDidLoad,
suivant juste après l’appel StartLocationUpdates
:
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// It is better to handle this with notifications, so that the UI updates
// resume when the application re-enters the foreground!
Manager.LocationUpdated += HandleLocationChanged;
}
À présent, lorsque l’application est exécutée, elle doit ressembler à ceci :
Gestion des états actifs et en arrière-plan
L’application met à jour l’emplacement pendant qu’elle est au premier plan et active. Pour illustrer ce qui se passe lorsque l’application entre en arrière-plan, remplacez les méthodes qui suivent les
AppDelegate
modifications d’état de l’application afin que l’application écrit dans la console lorsqu’elle passe au premier plan et à l’arrière-plan :public override void DidEnterBackground (UIApplication application) { Console.WriteLine ("App entering background state."); } public override void WillEnterForeground (UIApplication application) { Console.WriteLine ("App will enter foreground"); }
Ajoutez le code suivant dans le cadre de l’impression
LocationManager
continue des données d’emplacement mises à jour dans la sortie de l’application pour vérifier que les informations d’emplacement sont toujours disponibles en arrière-plan :public class LocationManager { public LocationManager () { ... LocationUpdated += PrintLocation; } ... //This will keep going in the background and the foreground public void PrintLocation (object sender, LocationUpdatedEventArgs e) { CLLocation location = e.Location; Console.WriteLine ("Altitude: " + location.Altitude + " meters"); Console.WriteLine ("Longitude: " + location.Coordinate.Longitude); Console.WriteLine ("Latitude: " + location.Coordinate.Latitude); Console.WriteLine ("Course: " + location.Course); Console.WriteLine ("Speed: " + location.Speed); } }
Il existe un problème restant avec le code : la tentative de mise à jour de l’interface utilisateur lorsque l’application est en arrière-plan entraîne l’arrêt d’iOS. Lorsque l’application passe en arrière-plan, le code doit se désabonner des mises à jour d’emplacement et arrêter la mise à jour de l’interface utilisateur.
iOS nous fournit des notifications lorsque l’application est sur le point de passer à un autre état d’application. Dans ce cas, nous pouvons nous abonner à la
ObserveDidEnterBackground
notification.L’extrait de code suivant montre comment utiliser une notification pour indiquer à l’affichage quand arrêter les mises à jour de l’interface utilisateur. Cela va aller dans
ViewDidLoad
:UIApplication.Notifications.ObserveDidEnterBackground ((sender, args) => { Manager.LocationUpdated -= HandleLocationChanged; });
Lorsque l’application est en cours d’exécution, la sortie ressemble à ceci :
L’application imprime les mises à jour de l’emplacement à l’écran lors de l’opération au premier plan et continue d’imprimer des données dans la fenêtre de sortie de l’application tout en fonctionnant en arrière-plan.
Un seul problème en suspens reste : l’écran démarre les mises à jour de l’interface utilisateur lorsque l’application est chargée pour la première fois, mais elle n’a aucun moyen de savoir quand l’application a recréé le premier plan. Si l’application en arrière-plan est renvoyée au premier plan, les mises à jour de l’interface utilisateur ne reprendront pas.
Pour résoudre ce problème, imbriquez un appel pour démarrer les mises à jour de l’interface utilisateur à l’intérieur d’une autre notification, qui se déclenche lorsque l’application entre dans l’état Actif :
UIApplication.Notifications.ObserveDidBecomeActive ((sender, args) => {
Manager.LocationUpdated += HandleLocationChanged;
});
À présent, l’interface utilisateur commence à mettre à jour lorsque l’application est démarrée pour la première fois et reprend la mise à jour à tout moment où l’application revient au premier plan.
Dans cette procédure pas à pas, nous avons créé une application iOS prenant en compte les arrière-plans qui imprime les données d’emplacement à la fois à l’écran et à la fenêtre de sortie de l’application.