Ludovic ROLAND

Blog technique sur mes expériences de développeur.

Windows Phone 7 : La géolocalisation

17 janvier 2013

Ayant récemment animé une formation Windows Phone 7, j’ai été amené à expliquer et mettre en pratique les fonctionnalités de base de l’OS Mobile de Microsoft (base de données, data binding, carte Bings, isolated storage, etc.).

Autant que possible, je vais tenter de mettre sur ce blog une partie de cette formation en une série d’articles.

Je vous propose de débuter tout de suite avec notre premier billet portant sur le thème de la géolocalisation.

Ce que nous allons faire

Le but de cet article aura pour objectif d’afficher à l’écran les coordonnées du téléphone, ainsi qu’un marqueur sur une carte indiquant la mention «Vous êtes ici».

Première étape : la géolocalisation et l’affichage des coordonnées

Dans le XAML

Commencez par ajouter 4 TextBlocks à votre page :

<!--LayoutRoot est la grille racine où tout le contenu de la page est placé-->
<Grid x:Name="LayoutRoot" Background="Transparent">
    <TextBlock Height="30" HorizontalAlignment="Left" Margin="12,6,0,0" Name="lblLatitude" Text="Latitude :" VerticalAlignment="Top" />
    <TextBlock Height="30" HorizontalAlignment="Left" Margin="12,42,0,0" Name="lblLongitude" Text="Longitude :" VerticalAlignment="Top" />
    <TextBlock Height="30" HorizontalAlignment="Left" Margin="118,42,0,0" Name="lblLongitudeValue" Text="" VerticalAlignment="Top" />
    <TextBlock Height="30" HorizontalAlignment="Left" Margin="118,6,0,0" Name="lblLatitudeValue" Text="" VerticalAlignment="Top" />
</Grid>
  • lblLongitudeValue affichera la longitude ;
  • lblLatitudeValue affichera la latitude.

Dans le code behind

Pour géolocaliser notre téléphone, nous allons utiliser l’objet GeoCoordinateWatcher. Un delegate y sera associé : PositionChanged qui est appelé lorsque la position du téléphone change. **A noter que vous pouvez également utiliser le delegate **StatusChanged qui permet de détecter les changements d’état de notre watcher.

Pour pouvoir utiliser l’objet GeoCoordinateWatcherk, vous devez ajouter la référence System.Device à votre solution.

Voici alors le morceau de code à ajouter à notre fichier xaml.cs pour afficher les coordonnées :

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    //Constructeur dans lequel on précise la précision voulue
    GeoCoordinateWatcher watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);

    //Détermine la distance minimale parcourue entre les appels au delegate positionChanged
    watcher.MovementThreshold = 10.0;

    //Mise en place des delegates
    watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);

    //On tente de démarrer le service de localisation
    if (watcher.Permission == GeoPositionPermission.Granted)
    {
        watcher.Start();
    }
}

private void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
    //On affiche les coordonnées
    lblLatitudeValue.Text = e.Position.Location.Latitude.ToString();
    lblLongitudeValue.Text = e.Position.Location.Longitude.ToString();
}

Normalement, des coordonnées doivent s’afficher. Par défaut, il s’agit de locaux Microsoft aux Etats-Unis. Vous pouvez vous amuser à changer votre emplacement grâce aux fonctions de l’émulateur. Votre application doit normalement se mettre à jour.

Ajouter une carte

Nous allons maintenant ajouter une carte qui se centrera sur l’endroit où le téléphone nous géolocalise.

Obtention d’une clef

La première étape consiste à récupérer une clef pour notre Bing Map. Pour ce faire, rendez-vous sur le site http://www.bingmapsportal.com.

Une fois identifié, cliquez sur le lien «Create or view keys» dans le sous-menu «My Account». Saisissez les informations demandées dans le formulaire et créez votre clef.

Dans le XAML

Nous allons maintenant mettre à jour notre fichier XAML pour y ajouter le composant Map.

Voici ce à quoi ressemble maintenant notre fichier :

<!--LayoutRoot est la grille racine où tout le contenu de la page est placé-->
<Grid x:Name="LayoutRoot" Background="Transparent">
    <TextBlock Height="30" HorizontalAlignment="Left" Margin="12,6,0,0" Name="lblLatitude" Text="Latitude :" VerticalAlignment="Top" />
    <TextBlock Height="30" HorizontalAlignment="Left" Margin="12,42,0,0" Name="lblLongitude" Text="Longitude :" VerticalAlignment="Top" />
    <TextBlock Height="30" HorizontalAlignment="Left" Margin="118,42,0,0" Name="lblLongitudeValue" Text="" VerticalAlignment="Top" />
    <TextBlock Height="30" HorizontalAlignment="Left" Margin="118,6,0,0" Name="lblLatitudeValue" Text="" VerticalAlignment="Top" />

    <my:Map Height="678" HorizontalAlignment="Left" Margin="12,78,0,0" Name="bingMap" VerticalAlignment="Top" Width="456" ZoomLevel="17" LogoVisibility="Collapsed" CopyrightVisibility="Collapsed">
        <my:Map.CredentialsProvider>
                <my:ApplicationIdCredentialsProvider ApplicationId="AuSncdh..." />
        </my:Map.CredentialsProvider>
    </my:Map>
</Grid>

N’oubliez pas de remplacer le CredentialsProvider par votre clef !

Dans le code behind

Il convient maintenant de centrer la carte sur la position du téléphone et ce à chaque fois que celui-ci détecte un changement de position. Tout se passe donc dans la méthode watcher_PositionChanged.

Voici donc notre méthode mise à jour :

private void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
    //On affiche les coordonnées
    lblLatitudeValue.Text = e.Position.Location.Latitude.ToString();
    lblLongitudeValue.Text = e.Position.Location.Longitude.ToString();

    //On centre la carte
    bingMap.SetView(e.Position.Location, 17);
}

Ajout du marqueur

Nous allons maintenant ajouter un marqueur à notre carte pour indiquer plus précisément où nous sommes.

Ce coup ci, tout se passe dans le code behind. C’est la classe Pushpin qui va nous permettre de modéliser nos marqueurs.

Commencez par déclarer un Pushpin :

Pushpin pin;

Instanciez le dans la méthode OnNavigatedTo :

//On instancie le marqueur
pin = new Pushpin();
pin.Location = new GeoCoordinate(0, 0);
pin.Content = "Vous êtes ici ";

//On ajoute le marqueur à la carte
bingMap.Children.Add(pin);

Il faut maintenant modifier l’emplacement du marqueur avec les changements de positions détectés. Cette mise à jour se passe dans la méthode watcher_PositionChanged :

pin.Location = e.Position.Location;

Voici alors ce que vous devriez avoir à l’exécution :

Le code complet

Pour ceux qui en auraient besoin, voici le code complet :

Le fichier XAML

<phone:PhoneApplicationPage 
    x:Class="Blog_GeoCoordinateWatcher.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True" xmlns:my="clr-namespace:Microsoft.Phone.Controls.Maps;assembly=Microsoft.Phone.Controls.Maps">

    <!--LayoutRoot est la grille racine où tout le contenu de la page est placé-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <TextBlock Height="30" HorizontalAlignment="Left" Margin="12,6,0,0" Name="lblLatitude" Text="Latitude :" VerticalAlignment="Top" />
        <TextBlock Height="30" HorizontalAlignment="Left" Margin="12,42,0,0" Name="lblLongitude" Text="Longitude :" VerticalAlignment="Top" />
        <TextBlock Height="30" HorizontalAlignment="Left" Margin="118,42,0,0" Name="lblLongitudeValue" Text="" VerticalAlignment="Top" />
        <TextBlock Height="30" HorizontalAlignment="Left" Margin="118,6,0,0" Name="lblLatitudeValue" Text="" VerticalAlignment="Top" />

        <my:Map Height="678" HorizontalAlignment="Left" Margin="12,78,0,0" Name="bingMap" VerticalAlignment="Top" Width="456" ZoomLevel="17" LogoVisibility="Collapsed" CopyrightVisibility="Collapsed">
            <my:Map.CredentialsProvider>
                <my:ApplicationIdCredentialsProvider ApplicationId="AuSncdh..." />
            </my:Map.CredentialsProvider>
        </my:Map>
    </Grid>
</phone:PhoneApplicationPage>

Le fichier CS

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Device.Location;
using Microsoft.Phone.Controls.Maps;

namespace Blog_GeoCoordinateWatcher
{
    public partial class MainPage : PhoneApplicationPage
    {
        Pushpin pin;

        // Constructeur
        public MainPage()
        {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            //On instancie le marqueur
            pin = new Pushpin();
            pin.Location = new GeoCoordinate(0, 0);
            pin.Content = "Vous êtes ici";

            //On ajoute le marqueur à la carte
            bingMap.Children.Add(pin);

            //Constructeur dans lequel on précise la précision voulue
            GeoCoordinateWatcher watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);

            //Détermine la distance minimale parcourue entre les appels au delegate positionChanged
            watcher.MovementThreshold = 10.0;

            //Mise en place des delegates
            watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);

            //On tente de démarrer le service de localisation
            if (watcher.Permission == GeoPositionPermission.Granted)
            {
                watcher.Start();
            }
        }

        private void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            //On récupère notre objet
            GeoCoordinateWatcher watcher = sender as GeoCoordinateWatcher;

            //On affiche les coordonnées
            lblLatitudeValue.Text = e.Position.Location.Latitude.ToString();
            lblLongitudeValue.Text = e.Position.Location.Longitude.ToString();

            //On met à jour le marqueur
            pin.Location = e.Position.Location;

            //On centre la carte
            bingMap.SetView(e.Position.Location, 17);
        }
    }
}

Commentaires