• Facile

Ce cours est visible gratuitement en ligne.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Mis à jour le 29/04/2014

La géolocalisation

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

De plus en plus de matériels technologiques sont équipés de systèmes de localisation, notamment grâce aux GPS. C’est également le cas des téléphones équipés de Windows Phone dont les spécifications imposent la présence d’un GPS. Mais le système de localisation est un peu plus poussé que le simple GPS, qui a ses limites. En effet, on se trouve souvent à l’intérieur d’un immeuble ou entourés par des gros murs qui peuvent bloquer le signal du GPS… heureusement, la triangulation à base des réseaux WIFI peut prendre la relève pour indiquer la position d’un téléphone.
Nous allons pouvoir exploiter la position de notre utilisateur et réaliser ainsi des applications géolocalisées, nous allons voir dans ce chapitre comment faire.

Avec Windows Phone 7, on utilisait une première version du service de localisation grâce au GeoCoordinateWatcher. Windows 8 a proposé une refonte du service de localisation et c’est tout naturellement que Windows Phone 8 en a profité. Les deux fonctionnent globalement de la même façon, mais celui de Windows Phone 8 supporte par défaut l’asynchronisme avancé avec await et async. C’est celui-ci que nous allons étudier. Sachez quand même que si vous projetez de faire en sorte que votre application fonctionne avec Windows Phone 7.X et 8, vous aurez intérêt à utiliser la première version du service de localisation.

Remarquez que vous devrez indiquer dans votre application un descriptif de votre politique d'utilisation des données géolocalisées, soit directement dans une page, soit en donnant un lien vers cette politique. De même, votre application devra fournir un moyen de désactiver explicitement l'utilisation du service de localisation.

Déterminer sa position

Il est très facile de récupérer sa position, on parle de géolocalisation. Pour ce faire, on pourra utiliser la classe Geolocator qui est le point d’accès au service de localisation. Nous aurons besoin dans un premier temps d’indiquer que notre application utilise le service de localisation en rajoutant la capacité ID_CAP_LOCATION. Il suffit de la sélectionner en double-cliquant sur le fichier WMAppManifest.xml, comme indiqué sur la figure suivante.

Activer la capacité de géolocalisation
Activer la capacité de géolocalisation

Ensuite, il faut avoir une instance de la classe Geolocator et potentiellement indiquer des paramètres comme la précision. Utilisons dans un premier temps ce XAML :

<StackPanel>
    <Button Click="Button_Click_1"  Content="Obtenir la position du téléphone"/>
    <TextBlock x:Name="Latitude"/>
    <TextBlock x:Name="Longitude"/>
</StackPanel>

Et dans le code-behind, nous pouvons obtenir notre position avec :

private async void Button_Click_1(object sender, RoutedEventArgs e)
{
    Geolocator geolocator = new Geolocator();
    geolocator.DesiredAccuracyInMeters = 50;

    try
    {
        Geoposition geoposition = await geolocator.GetGeopositionAsync(TimeSpan.FromMinutes(5), TimeSpan.FromSeconds(10));

        Dispatcher.BeginInvoke(() =>
        {
            Latitude.Text = geoposition.Coordinate.Latitude.ToString();
            Longitude.Text = geoposition.Coordinate.Longitude.ToString();
        });
    }
    catch (UnauthorizedAccessException)
    {
        MessageBox.Show("Le service de location est désactivé dans les paramètres du téléphone");
    }
    catch (Exception ex)
    {
    }
}

Grâce à la méthode GetGeopositionAsync nous obtenons la position du téléphone, et ce, de manière asynchrone (notez l’emploi des mots-clés await et async), ce qui évite de bloquer l’interface utilisateur. Nous pouvons ensuite exploiter l’objet Geoposition obtenu en retour et notamment ses propriétés Latitude et Longitude.
Dans cet objet, nous obtenons également d’autres informations, comme l’altitude (en mètres au-dessus du niveau de la mer), l’orientation (en degrés par rapport au nord), la vitesse (en mètres par secondes) ; cette dernière donnée ayant peu de sens lorsque la géolocalisation est demandée une unique fois.

Sauf qu’une position, ça change au fur et à mesure ! Eh oui, en voiture, dans le train, etc. On peut avoir besoin d’être notifié d’un changement de position ; ce qui peut être très pratique dans une application de navigation ou pour enregistrer un parcours de course à pied. Dans ce cas, il faut s’abonner à l’événement PositionChanged qui nous fournira une nouvelle position à chaque fois. Nous aurons également besoin de nous abonner à l’événement StatusChanged qui nous permettra de connaître les changements de statut du matériel :

public partial class MainPage : PhoneApplicationPage
{
    private Geolocator geolocator;

    public MainPage()
    {
        InitializeComponent();
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        geolocator = new Geolocator { DesiredAccuracy = PositionAccuracy.High, MovementThreshold = 20 };
        geolocator.StatusChanged += geolocator_StatusChanged;
        geolocator.PositionChanged += geolocator_PositionChanged;

        base.OnNavigatedTo(e);
    }

    protected override void OnNavigatedFrom(NavigationEventArgs e)
    {
        geolocator.PositionChanged -= geolocator_PositionChanged;
        geolocator.StatusChanged -= geolocator_StatusChanged;
        geolocator = null;

        base.OnNavigatedFrom(e);
    }

    private void geolocator_StatusChanged(Geolocator sender, StatusChangedEventArgs args)
    {
        string status = "";

        switch (args.Status)
        {
            case PositionStatus.Disabled:
                status = "Le service de localisation est désactivé dans les paramètres";
                break;
            case PositionStatus.Initializing:
                status = "En cours d'initialisation";
                break;
            case PositionStatus.Ready:
                status = "Service de localisation prêt";
                break;
            case PositionStatus.NotAvailable:
            case PositionStatus.NotInitialized:
            case PositionStatus.NoData:
                break;
        }

        Dispatcher.BeginInvoke(() =>
        {
            Statut.Text = status;
        });
    }

    private void geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
    {
        Dispatcher.BeginInvoke(() =>
        {
            Latitude.Text = args.Position.Coordinate.Latitude.ToString();
            Longitude.Text = args.Position.Coordinate.Longitude.ToString();
        });
    }
}

Il faut toujours vérifier la bonne disponibilité du GPS, car il peut arriver que l’utilisateur veuille explicitement le désactiver. C’est le cas par exemple lorsque le statut est égal à Disabled.
Pour afficher le statut, j’ai légèrement modifié mon XAML :

<TextBlock x:Name="Statut"/>
<TextBlock x:Name="Latitude"/>
<TextBlock x:Name="Longitude"/>

Remarque : il n’y a pas de méthode pour démarrer le service de localisation comme il pouvait y avoir la méthode Start() avec le service de localisation de Windows Phone 7. Le démarrage s’effectue lorsqu’on s’abonne à l’événement PositionChanged. Ce qui implique que lorsqu’on n’en aura plus besoin, il sera possible d’arrêter l’utilisation du service de localisation en se désabonnant de ce même événement. Cela permet d’économiser la batterie. C’est ce que j’ai fait dans mon exemple en démarrant le service de navigation lorsque j’arrive sur la page et en le désactivant lorsque je quitte la page.

Et voilà, dans la méthode geolocator_PositionChanged, nous recevons un objet nous fournissant les coordonnées de la position du téléphone, comme vu plus haut, et nous avons des relevés successifs de la position du téléphone.

Remarquons qu’il est possible de définir l'effort que doit faire le service de localisation pour déterminer notre position. Il suffit de créer le Geolocator en affectant sa propriété DesiredAccuracy. Il existe deux modes : précision forte ou précision par défaut. Vous aurez compris que la précision forte s’obtient avec :

DesiredAccuracy = PositionAccuracy.High

Et que la précision par défaut s’obtient avec

DesiredAccuracy = PositionAccuracy.Default

En mode par défaut, le téléphone utilise essentiellement les bornes wifi et les antennes radios pour faire une triangularisation, ce qui est relativement peu consommateur de batterie. En mode de précision forte, le téléphone va utiliser l'ensemble des moyens dont il dispose pour nous géolocaliser en négligeant la consommation de batterie. Il utilisera notamment la puce GPS pour un repérage par satellite.

À noter que l'on peut indiquer à partir de quelle distance (en mètres par rapport à la dernière position trouvée) le service de localisation envoie un événement pour nous indiquer un changement de position. Cela se fait via la propriété MovementThreshold qui est à 0 mètre par défaut, ce qui implique qu'un événement de changement de position est envoyé à chaque changement de position. Nous avons également à notre disposition la propriété DesiredAccuracyInMeters qui permet d’indiquer le niveau de précision souhaité (en mètres) pour les données renvoyées depuis le service de localisation.

Utiliser la géolocalisation dans l'émulateur

Oui mais un GPS, c’est très bien sur un téléphone… mais sur un émulateur ? Comment on fait ? Il peut quand même nous fournir une position ?

Pour le vérifier, démarrons l’émulateur et récupérons la position comme nous l’avons vu. Nous obtenons une latitude de 47,669444 et une longitude de -122,123889, qui correspond à la position… des bâtiments de Microsoft. Hasard ? ;)

En fait, ceci se passe dans les outils supplémentaires de l’émulateur, le dernier bouton en bas de la barre située à droite de l’émulateur. Il est possible de changer les valeurs et même de définir des itinéraires pour simuler des déplacements, cela se passe dans l’onglet Localisation, comme indiqué à la figure suivante.

Simuler la géolocalisation dans les outils de l'émulateur
Simuler la géolocalisation dans les outils de l'émulateur

En quelques clics, je définis ma position et mon tour de France. Il sera alors très facile de faire changer l’émulateur de position pendant son exécution, soit manuellement, soit en jouant un itinéraire préalablement enregistré… Pratique pour simuler des positions ou des changements de position tout en restant confortablement installé sur son PC avec son débogueur.

Utiliser la géolocalisation avec le contrôle Map

La géolocalisation prend tout son intérêt utilisée concomitamment avec le contrôle Map vu dans la partie précédente.
Étant donné que le service de localisation fourni un objet avec une latitude et une longitude (de type Geocoordinate), il est très facile d’utiliser les coordonnées GPS de notre utilisateur sur la carte, par exemple ici je centre la carte sur la position de l’utilisateur :

private void geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
    Dispatcher.BeginInvoke(() =>
    {
        Latitude.Text = args.Position.Coordinate.Latitude.ToString();
        Longitude.Text = args.Position.Coordinate.Longitude.ToString();

        Carte.Center = new GeoCoordinate(args.Position.Coordinate.Latitude, args.Position.Coordinate.Longitude);
    });
}

Remarquons qu’il faut utiliser le dispatcher pour revenir sur le thread d’interface afin de mettre à jour cette dernière.

  • Le service de localisation est accessible à partir du moment où il a été déclaré et accepté par l’utilisateur.

  • La classe Geolocator permet d’obtenir les informations issues du service de localisation.

  • On peut utiliser le contrôle de carte pour afficher sa position, en utilisant la classe GeoCoordinate.

Exemple de certificat de réussite
Exemple de certificat de réussite