Archives de Tag: WP7

[WP7] Comment faire des screenshots depuis votre téléphone ?

J’ai réalisé une application qui utilise la caméra pour écrire des sms en marchant (TextWalker : http://www.windowsphone.com/fr-FR/apps/18279149-e3fe-460c-8c35-29316f41bab1).

Et je voulais faire un screenshot de cette application sans avoir le vilain fond blanc de l’émulateur de l’appareil photo. Je voulais donc directement faire cette impression écran depuis mon téléphone.

Et Zozo (http://zozofromelk.wordpress.com/2012/01/22/screenshot-of-your-windows-phone-7-app-on-device/) m’a sauvé !
En effet, il a créé un behavior a intégrer au sein de son application pour faire des impressions écrans avec un Double Tap sur l’écran (double clic avec le doigt) que vous pouvez télécharger ici : http://bit.ly/znSvNE ou depuis son article ci-dessus.

Une fois récupéré, il vous suffit d’ajouter la classe ScreenShotBehavior à votre projet ainsi qu’au sein des pages où vous souhaitez réaliser vos impressions écrans :

<i:Interaction.Behaviors>
        <local:ScreenShotBehavior />
    </i:Interaction.Behaviors>

Une fois que l’application est lancée, il vous suffira de taper deux fois sur votre écran pour retrouver votre screenshot dans les images du téléphone.

Remarque, il a encadré le code de son behavior entre dans un directive préprocesseur “#DEBUG” qui fait qu’il n’est fonctionnel qu’en mode débug.

Par JCVASSELON

[WP7] Utiliser Skydrive dans vos projets WP7

Dernièrement, Microsoft a annoncé la sortie du Live SDK. Cette boite à outil va nous permettre à nous développeur de faire interagir nos applications avec les services du Live. Cela va de l’authentification à nos services, en passant par WLM, l’accès aux calendriers et contacts mais aussi au SkyDrive !
SkyDrive, cet espace de stockage dans le cloud que j’avais évoqué dans cet article : http://onefor4.wordpress.com/2011/10/25/tip-intgrez-skydrive-windows-7/ va ainsi devenir encore plus intégré et nous permettre de faciliter les échanges inter-utilisateurs, inter-applications et inter-plateformes !
Nous allons voir ici quelques opérations basiques pour démarrer.

Prérequis et ressources :

Inscription de l’application

Avant toute chose, il va falloir inscrire votre application ici : https://manage.dev.live.com/AddApplication.aspx pour obtenir un identifiant et des credentials.

image

Rendez vous ensuite dans API Settings pour configurer votre application comme étant une application mobile.

image

Lire et écrire sur SkyDrive

Pour l’exemple, nous allons réaliser l’application suivante qui consiste à ajouter un nouveau fichier dans un dossier de SkyDrive.

image

C’est une simple page, contenant :

  • Un SignInButton que nous détaillerons plus tard et qui permet de s’authentifier sur le live.
  • Un ListPicker (que vous trouverez notamment dans le Silverlight for WP7 Toolkit) qui nous permettra de choisir dans quel dossier enregistrer notre fichier.
  • Une textbox pour donner un nom au fichier et une autre pour ajouter du contenu à ce fichier.

Le code

Pour utiliser SkyDrive, on aura besoin de s’authentifier sur le Live. Le SDK nous donne heureusement un contrôle déjà existant pour cela : le SignInButton ! Sourire
Ajoutez les DLL Microsoft.Live et Microsoft.Live.Controls à votre projet.

Rajoutez le namespace suivant dans votre xaml :

xmlns:my="clr-namespace:Microsoft.Live.Controls;
assembly=Microsoft.Live.Controls"

Vous pouvez maintenant utiliser le SignInButton qui vous permettra de vous authentifier sur le live et de choisir les différents droits que vous souhaitez que l’utilisateur vous donne.

<my:SignInButton 
ClientId=""
Scopes="wl.signin wl.skydrive wl.skydrive_update"
SessionChanged="SignInButton_SessionChanged" />

Les différents attributs importants :

  • ClientId : C’est l’identifiant de votre application. Vous le retrouverez sur cette page : https://manage.dev.live.com/Applications/Index
  • Scopes : C’est les différents droits que vous souhaitez obtenir. Ici, l’authentification, les droits de lecture sur le SkyDrive, et les droits de mises à jour sur le SkyDrive.
    Tous les scopes ici : http://msdn.microsoft.com/fr-fr/library/hh243646.aspx
  • SessionChanged : C’est l’évènement qui est levé lors de la Connexion / Déconnexion de l’utilisateur

En cliquant sur ce nouveau bouton, on est automatiquement redirigé vers la page de connexion de Windows Live.

image

Vient ensuite une demande d’autorisations :

image

La session est initialisée. Traitons là maintenant et voyons comment accéder aux différents dossiers sur notre SkyDrive. Pour cela, nous allons d’ailleurs créer une classe SkydriveItem qui nous permettra d’organiser plus facilement les différents éléments (fichiers, dossiers, albums).

public class SkydriveItem
    {
        public string Id { get; set; }
        public string Type { get; set; }
        public string Name { get; set; }

        public override string ToString()
        {
            return Name;
        }
    }
  • Id : Unique, il nous permet d’accéder directement à l’élément depuis le code.
  • Type : Il existe trois types d’éléments. Folder, un répertoire; Files, un fichier; Albums, un répertoire “spécial”.
  • Name : Le nom du dossier lisible par un humain Sourire

Revenons au code de notre page. On va ajouter un LiveConnectClient qui nous permettra de garder la session et de réaliser nos différentes opérations ainsi qu’une ObservableCollection de SkydriveItem dans laquelle on ajoutera les différents dossiers et que l’on bindera sur l’ItemsSource de notre ListPicker.

private LiveConnectClient _client;
public ObservableCollection<SkydriveItem> SkydriveItems 
{ get; set; } // Constructor public MainPage() { SkydriveItems = new ObservableCollection<SkydriveItem>(); InitializeComponent(); }

Remplissons ensuite la méthode SignInButton_SessionChanged().

private void SignInButton_SessionChanged(object sender, 
                     LiveConnectSessionChangedEventArgs e)
{
//Si on est bien connecté
if (e.Status == LiveConnectSessionStatus.Connected)
{
  //On purge la liste d'éléments
  SkydriveItems.Clear();
  //On initialise notre LiveConnectClient avec la session courante
  _client = new LiveConnectClient(e.Session);
  //On s'abonne à l'événement
  _client.GetCompleted += 
       new EventHandler<LiveOperationCompletedEventArgs>
(OnGetCompleted); //On lance l'opération aynchrone _client.GetAsync("/me/skydrive/files"); } else if (e.Status == LiveConnectSessionStatus.NotConnected) { SkydriveItems.Clear(); _client = null; } else _client = null; }

Et on parcourt ensuite la liste des éléments obtenus en ajoutant ceux qui nous intéressent à notre ObservableCollection.

void OnGetCompleted(object sender, 
LiveOperationCompletedEventArgs e) { if (e.Error == null) { List<object> data = (List<object>)e.Result["data"]; foreach (IDictionary<string, object> content in data) { SkydriveItem nItem = new SkydriveItem(); nItem.Id = (string)content["id"]; nItem.Name = (string)content["name"]; nItem.Type = (string)content["type"]; if(nItem.Type == "folder") SkydriveItems.Add(nItem); } } }

Ils apparaissent maintenant dans notre ListPicker après l’authentification.

image

Occupons-nous de l’écriture dans un des dossiers sélectionnés. Abonnons l’évènement Click de notre bouton sur une méthode Save_Click.
Pour cet exemple, j’ai appelé la textbox qui représente le titre du fichier : Tb_Title et celle représentant le contenu : Tb_Text.

Voici le code de la méthode Save_Click() ainsi que le callback une fois l’upload terminé.

private void Save_Click(object sender, RoutedEventArgs e)
{
    string fileName = Tb_Title.Text.Trim();
    byte[] byteArray = 
Encoding.Unicode.GetBytes(Tb_Text.Text.Trim()); MemoryStream fileStream = new MemoryStream(byteArray); _client.UploadCompleted += new
EventHandler<LiveOperationCompletedEventArgs>(
UploadCompleted); _client.UploadAsync(
((SkydriveItem)LP_Items.SelectedItem).Id, fileName,
fileStream); } void UploadCompleted(object sender,
LiveOperationCompletedEventArgs e) { if (e.Error == null) { Dispatcher.BeginInvoke(() => { MessageBox.Show("Uploadé !"); }); } }

La méthode "_client.UploadAsync(
((SkydriveItem)LP_Items.SelectedItem).Id, fileName,
fileStream); "
nous permet d’uploader notre fichier dans le dossier correspondant. Mais attention, nous ne pouvons pas passer directement le nom du dossier mais son Id !

Une fois l’upload terminé, vous retrouverez votre fichier dans le dossier voulu sur votre SkyDrive : http://skydrive.live.com/

Conclusion

Nous avons ici découvert une partie du Live SDK : comment s’authentifier et comment utiliser des opérations basiques sur SkyDrive.
Ce SDK ouvre de formidables opportunités pour interagir avec les fichiers de vos utilisateurs mais aussi faciliter la migration de vos applications.
En effet, pourquoi ne pas sauvegarder le contenu de votre Isolated Storage pour le récupérer ensuite quand l’utilisateur souhaite changer de téléphone ? Ou simplement partager ses données avec un autre ?

Par JCVASSELON

Converter pour un Binding d’une image dans l’Isolated Storage

J’avais une liste d’éléments  de type Item auxquels je voulais attribuer une image différente pour chacun. Cette image se trouvait dans l’Isolated Storage dans un dossier spécifique pour chaque et était amenée à changer. Je ne pouvais pas mettre l’uri de ces images directement dans l’objet Item.
Dans le template de ma ListBox, au lieu de faire un binding de la source de mon image vers une uri, j’ai fait un binding vers le nom de mon Item (par exemple, “Bonjour le Chat”) et j’ai utilisé un converter pour aller récupérer l’image correspondante dans l’Isolated Storage.

image

(la ListBox avec les éléments)

J’ai donc créé mon converter avec la méthode Convert(…) suivante et qui retourne une BitmapImage.

public object Convert(object value, Type targetType, 
            object parameter, CultureInfo culture)
        {
            string path = value.ToString() + "/";
            using (IsolatedStorageFile store = 
                IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (String.IsNullOrEmpty(value.ToString()))
                    return null;
                try
                {
                    using (IsolatedStorageFileStream fileStream = 
                        store.OpenFile(path + 
                        store.GetFileNames(path + "*").First(),
                        FileMode.Open, FileAccess.Read))
                    {
                        var img = new BitmapImage();
                        img.SetSource(fileStream);
                        return img;
                    }
                }
                catch (Exception e)
                {
                    return null;
                }

            }
        }

Avec la méthode store.OpenFile(path + store.GetFileNames(path + "*").First(), FileMode.Open, FileAccess.Read). Je récupère un stream du premier fichier que je trouve dans le dossier recherché.
La méthode OpenFile est d’ailleurs intéressante puisque je lui passe bien sûr mon path, mais il faut que je liste ensuite tous les fichiers du répertoire (d’où le caractère “*”) avant de pouvoir prendre le premier.

Par JCVASSELON

[WP7] GPS Helper

Le développement d’une application GPS peut être laborieux. Certains Best Practices sont à respecter :

  • Il faut, par exemple, demander à l’utilisateur s’il souhaite être localisé, lui permettre de modifier ce choix en tout temps.
  • Pendant la recherche d’une localisation nous pouvons être amené à montrer le chargement. 
  • En fonction du matériel, du réseau GPS disponible, on peut être amené à afficher des statuts différents.

J’ai donc commencé une petite library pour simplifier tout ça ( http://wp7gpshelper.codeplex.com/ ). Une fois le GPSToolKit instancié :

  • Vous pourrez démarrer le GPS en appelant simplement la méthode Start(). Les vérifications sur les autorisations se font automatiquement. Le GPS ne démarrera pas si l’utilisateur ne le souhaite pas.
  • Vous abonner aux évènements habituels StatusChanged et LocationChanged.
  • Un booléen IsIndeterminate permet de savoir si le GPS est en train de chercher ou non. L’évènement IsIndeterminateChanged a été ajouté.
  • La propriété GPSParam.IsGpsAuthorized est sérialisée dans l’isolated storage et permet donc de savoir si l’utilisateur a autorisé ou non le GPS.

Vous pourrez ajouter par vous-même un bouton bindé sur le GPSParam.IsGpsAuthorized dans les options de votre application. Pensez par contre à préciser les politiques de confidentialités de votre application vis-à-vis des coordonnées GPS.

J’ai aussi inclus une classe pour faciliter l’implémentation du Geocoding.  Il suffit maintenant d’instancier la classe Geocoding en lui passant votre credential Bing Map (vous verrez comment l’avoir dans ce précédent article : http://onefor4.wordpress.com/2011/01/02/geocoding-en-silverlight-avec-bing-map/), de vous abonner à l’évènement souhaité en fonction de ce que vous voulez faire (GeocodeRequestCompleted ou ReverseGeocodeRequestCompleted) et d’appeler votre requête (idem, MakeReverseGeocodeRequest ou MakeGeocodeRequest) avec les paramètres adéquats.

Cette library est toujours en test. J’ai essayé de commenter le plus possible que cela puisse aussi servir d’exemple.
Il y a juste la partie où je récupère et retourne la localisation dont je ne suis pas très fier. Pour être sûr de récupérer les points depuis le GPS et non depuis le cache ou le réseau, j’évince volontairement les 4 premiers points récupérés. S’il y a de meilleures techniques, je suis preneur Sourire.

Par JCVASSELON

[WP7] Installation mise à jour Mango avant l’heure !

EDIT (du 05/10/2011) :
Il semblerait que ce soit l’heure. La mise à jour est en train d’être déployée par les moyens officiels. Assurez vous d’avoir la dernière version de Zune et branchez votre téléphone, elle devrait vous être proposée.
Si vous aimez toujours bidouiller et que vous ne l’avez pas encore par le chemin naturel :
http://www.monwindowsphone.com/comment-obtenir-la-mise-a-jour-mango-t6127.html

——————————————————

Vendredi la nouvelle est tombée, la version finale de la mise à jour Mango a fuité sur Internet, un sujet sur XDA explique comment l’installer (http://forum.xda-developers.com/showthread.php?t=1215501). Cet article va détailler le pas à pas en français selon mon expérience sur mon LG E900 avec les explications de ce forum.
Vous suivez cette procédure à vos risques et périls et êtes seul responsable de votre matériel et des dommages possibles.

Préambule

Comme d’habitude prenez vos précautions en travaillant sur un ordinateur stable, branché sur secteur et qui ne risque pas de s’éteindre ou redémarrer à un moment inopportun.
Réalisez bien la sauvegarde comme nous le verrons au cours de cet article.

La mise à jour ne se fait que depuis les versions 7392 (Nodo), Mango 7661 (Beta) ou Mango 7712 (Version développement)

Vérifiez donc la version de votre téléphone en le branchant sur votre pc et depuis Zune allez dans Settings / PHONE / Update. Et faites les mises à jour le cas échéant.
Update

Si vous avez besoin de faire une sauvegarde de votre téléphone, il est apparemment recommandé d’avoir au minimum 20Go d’espace libre sur le disque C et sur un autre support (sur lequel vous ferez la copie de la sauvegarde).

Prévoyez deux bonnes heures. Personnellement, avec l’écriture de cet article cela m’a pris 4 heures, mais j’ai rencontré de nombreux problèmes à la toute fin et j’espère que cet article vous les évitera. Mon téléphone était tout de même fonctionnel en version 7712 en moins de deux heures.

Commençons à mettre les mains dans le cambouis !

1) Téléchargez l’archive :
https://memory.altibox.no/share.php?id=l94D9nGhY3j3NRi7ukmGkglxqMSnqCzS
ou http://leetfx.com/7720.rar

2) Extrayez le contenu du dossier Mango de l’archive à la racine de votre disque dur (par exemple : C:/NoDoToRC, C:/RCToRTM, C:/Zune)

3) Installez la version de Zune 4.8.2134.0 disponible dans le dossier précédemment décompressé C:/Zune.
Une fois installé cliquez sur Close ou Fermer
ZuneInstalled

4) Rendez-vous ensuite dans le dossier Update Tool (toujours depuis le dossier décompressé C:/Zune). Choisissez le répertoire correspondant à votre système (x86 ou x64) et exécutez l’outil. Après une barre de chargement, il se ferme automatiquement.

5) Branchez votre téléphone sur votre PC. Attendez de voir si Zune s’ouvre, fermez le si c’est le cas. (ça sera certainement le cas !)

6a) Si votre téléphone est en version 7661 ou 7712 allez à l’étape 13

6b) Nous allons créer le backup.
Ouvrez le dossier NoDoToRC (C:/NoDoToRC) et lancez ISV_Provisioning_Live.exe en admin (clic droit / Démarrer en tant qu’administrateur). Cliquez sur “I agree” ou “J’accepte”.
Vous pouvez obtenir une erreur “Zune.exe is not found”. Dans ce cas, copiez le contenu du dossier d’installation de Zune dans “C:/Program Files/Zune.
Normalement, vous devriez arriver à un écran de ce type :
Backup
Quand le téléphone redémarre, tapez votre PIN et déverrouillez l’écran. Un joli message Succeeded devrait apparaître !
Backup2

7) Vous pouvez fermer le logiciel et allez récupérer la sauvegarde dans le dossier : C:\Users\<user>\AppData\Local\Microsoft\Windows Phone Update. Votre sauvegarde est dans le dossier au nom bizarre (un Guid du type a2df96e4 – 60a0e8cc – …)
COPIEZ CETTE SAUVEGARDE DANS UN LIEU SECURISE

8) Copiez cette sauvegarde sur un périphérique externe, dans un autre répertoire de votre disque dur et sachez où elle est !

9) Continuez uniquement si vous avez mis la sauvegarde en lieu sûr !

10) Démarrez Zune avec votre téléphone branché !
Rendez-vous dans settings / PHONE / UPDATE. Une mise à jour va être trouvée (7403) cliquez sur UPDATE !

11) Une fois mis à jour, Zune va trouver la mise à jour 7712. Installez la aussi.

12) Fermez Zune

13) Ouvrez le dossier RCToRTM que vous aviez décompressé du dossier Mango. Il doit être à la racine du disque C:. ABSOLUMENT ! Rendez vous donc au sein de ce dossier : C:\RCToRTM

14) Lancez en administrateur le fichier "ISVTo7720.bat" (clic droit, ouvrir en tant qu’administrateur).
Des mises à jour supplémentaires vont être installées. Et c’est là que j’ai rencontré le plus de soucis…

  • Si la fenêtre de la console se ferme rapidement. Vérifiez :
    • Que vous êtes bien dans un dossier à la racine du disque C
    • Que vous l’avez bien lancé en administrateur
    • Que la version de Zune est bien celle de l’archive, à savoir : 4.8.2134.0
  • Si votre téléphone met du temps à redémarrer et que la fenêtre de la console se ferme ou que vous avez un message en rouge parlant de “drivers”.
    • Pour redémarrer le téléphone : Débranchez le, éteignez le en pressant longuement sur le bouton de déverrouillage. Retirez la batterie si cela ne suffit pas. Si au redémarrage, vous avez une flèche demandant de le brancher faites le et éteignez le à nouveau. Et redémarrez le débranché. Normalement il sera fonctionnel mais toujours avec la mise à jour 7712.
    • Essayez de désinstaller proprement Zune (ajout / suppression de programme) ainsi que “Windows Phone Engineering Flashing Tool”. Redémarrez, réinstaller Zune, lancez le avec les paramètres par défaut. Branchez votre téléphone, laissez les drivers s’installer. Fermez Zune, réinstallez l’Update Tool (cf partie 4). Et réessayez.
    • Si malgré ça, vous avez toujours le problème. Editez le fichier .bat, modifiez updatewp /iu par "C:\Program Files\Zune\updatewp.exe" /iu (ce qui a marché pour moi)
    • Si vous rencontrez toujours le problème. Que vous avez un message rouge indiquant un "Timeout" lors du redémarrage, essayez avec le RCToRTM modifié disponible ici : http://www.mascobz.com/windows-phone-7-mango-rtm-7720-timeout-error-fix/

15) Félicitations vous êtes sous Mango !

Par JCVASSELON

[WP7] Vérifier connexion à internet

Lors du développement d’une application Windows Phone 7, il se peut que que vous souhaitiez réaliser des opérations ayant besoin d’internet.
Pour que votre application puisse accéder au marketplace, vous devez afficher un message quand le réseau n’est pas disponible.

Pour cela, vous pouvez utiliser la méthode suivant (de System.Net.NetworkInformation) :
NetworkInterface.GetIsNetworkAvailable() qui retourne un booléen en fonction de la connectivité.

Globalisation d’une application Windows Phone 7

La globalisation d’une application WP7 peut être un procédé laborieux. Nous allons voir dans cet article comment mettre en place l’affichage des textes en fonction de la langue de l’utilisateur.
Cet article est en grande partie un résumé illustré de la page MSDN (en anglais) suivante  : http://msdn.microsoft.com/en-us/library/ff637520%28v=VS.92%29.aspx.

Commencez par ajouter un dossier Resources à votre application qui contiendra un premier fichier Resources.resx qui sera le fichier par défaut.

Resources

Les fichiers *.resx contiennent toutes les chaînes de caractères de votre application. C’est lui qui permettra de stocker les différentes langues. Un fichier .resx correspond à une langue.
Ouvrez le fichier Resources.resx :
ResourcesOpened

La première colonne Name représente la clef de la valeur, c’est elle que vous allez binder aux propriétés qui nécessitent un texte traduit en fonction de l’utilisateurs. Elle doit être unique.
La valeur, c’est le texte qu’elle doit afficher.
Le commentaire vous permettra de savoir à quoi ça correspond.
Par exemple : Title | Titre | Titre de mon application

Pensez à mettre l’Access Modifier sur la valeur “Public” (menu déroulant entouré en bleu en haut à droite).

Ajoutez maintenant un fichier resx pour chaque langue. Votre fichier devra maintenant porter la syntaxe suivante [NomDeVotrePremierFichier].culture-language.resx
Dans notre cas, pour notre fichier Resource en français : Resources.fr-FR.resx. La liste des cultures est disponible ici : http://msdn.microsoft.com/en-us/library/ee825488%28v=cs.20%29.aspx
Bien sûr, pas la peine d’ajouter toutes les cultures. Si la langue de l’utilisateur n’est pas prévue, l’application sera dans la langue par défaut.

Faites maintenant un clic droit sur le nom de votre projet et rendez-vous dans les propriétés. Dans l’onglet Application, cliquez sur “Assembly Information…”.
En bas de la nouvelle fenêtre, dans la propriété “Neutral Language” sélectionnez la langue que traduit votre premier fichier Resources.resx. Dans notre cas “English”.
Assembly Options

Validez ces modifications et faites à nouveau un clic droit sur le nom de votre projet puis “Open folder in Windows Explorer”. Ouvrez le fichier .csproj dans un éditeur de texte puis ajoutez les différentes langues supportées entre les balises <SupportedCultures></SupportedCultures>. Dans notre cas : <SupportedCultures>en-EN;fr-FR;</SupportedCultures>

Le processus est presque terminé, il ne vous reste plus qu’à ajouter une classe Strings.cs dans le dossier des Resources qui permettra de binder les différentes valeurs à vos champs de texte :

public class Strings
{
    public Strings()
    {   }
    private static Resources localizedresources = new Resources();
    public Resources Localizedresources {
        get { return localizedresources; }
    }
}

Le nom de la classe Resources correspond bien sûr au nom de votre premier fichier Resources.

Ajoutons maintenant cette classe string dans notre feuille de style, ou dans les ressources de votre App.xaml :
<Resources:Strings x:Key="Strings" />

Félicitation, la globalisation de votre application est terminée !
Vous pouvez binder vos chaînes de caractères globalisées de la manière suivante <TextBlock Text="{Binding Localizedresources.Title, Source={StaticResource Strings}}"/>

Si vous souhaitez aller plus loin et globaliser vos converters, ça se passe par ici : http://blogs.dotnet-france.com/gregoryc/post/Net-e28093-Globalisation-de-la-valeur-de-ConverterParameter.aspx

Par JCVASSELON

[WP7] Trouver son chemin avec Bing Map

Suite à mon article précédent sur le geocoding : http://onefor4.wordpress.com/2011/01/02/geocoding-en-silverlight-avec-bing-map/ nous allons maintenant voir comment relier des points sur la carte et ensuite comment suivre une route.

Mise en place du module

Ouvrons notre projet WP7 et ajoutons notre carte à notre fichier xaml :

<Microsoft_Phone_Controls_Maps:Map CredentialsProvider="{Binding MyCredential, ElementName=phoneApplicationPage}" x:Name="MyMap" Mode="Road" Center="{Binding CenterCoord, ElementName=phoneApplicationPage}" ZoomLevel="10"  >
<Microsoft_Phone_Controls_Maps:MapLayer>
<Microsoft_Phone_Controls_Maps:MapPolyline x:Name="routeLine" Stroke="Black" StrokeThickness="6" Locations="{Binding Points, ElementName=phoneApplicationPage}" />
</Microsoft_Phone_Controls_Maps:MapLayer>
</Microsoft_Phone_Controls_Maps:Map>

On remarquera quelques bindings :

- MyCredential : Votre “API Key” que vous avez normalement généré dans l’article précédent

- CenterCoord : Objet GeoCoordinate qui représente les coordonnées sur lesquelles vous souhaitez centrer votre carte.

- Points : objet LocationsCollection, comme son nom l’indique c’est une collection d’objets GeoCoordinate ou Location. Ce sont tous les points par lesquels passera notre ligne.

Ensuite on modifie la propriété MapLayer. C’est celle là qui nous permettra de modifier ensuite notre fond de carte. Ici nous ajoutons un objet MapPolyline nous permettant de tracer justement des lignes. Des lignes qui passeront par des points (Captain Obvious spotted !).
On paramètre notre MapPolyline en lui donnant une couleur “Stroke” et une épaisseur “StrokeThickness”.

Notre code-behind ressemblera à ça :

public Credentials MyCredential { get; private set; }
public GeoCoordinate CenterCoord { get; private set; }
public MainPage()
{
MyCredential = new Credentials(){ApplicationId = "VOTRECLEF"};
CenterCoord = new GeoCoordinate(42.00, 1.337);
Points = new LocationCollection();
InitializeComponent();
}

Traçons notre premier trait

MapPolyline trace donc des traits en passant par les points représentés par des coordonnées stockées dans sa collection Locations.
Créons donc une méthode AddLocation().

private void AddLocations()
{
Points.Add(new GeoCoordinate(42.00, 1.337));
Points.Add(new GeoCoordinate(42.600, 1.42));
}

On appelle notre méthode et nous pouvons voir notre premier trait tracé au nord de l’Espagne (oui l’exemple est totalement abstrait).

Maintenant que l’on voit l’idée, il serait intéressant de pouvoir récupérer une liste de points correspondant à un trajet réel entre deux ou plusieurs lieux !

Récupérons les coordonnées de notre route

Ajoutons une référence de service vers :
http://dev.virtualearth.net/webservices/v1/routeservice/routeservice.svc?wsdl
Créons ensuite nos méthodes qui calculeront et afficheront le trajet entre nos points.

private void CalculateRoute(IEnumerable<GeoCoordinate> Lieux)
{
var routeRequest = new RouteRequest();
routeRequest.Credentials = MyCredential;
routeRequest.Waypoints = new ObservableCollection<Waypoint>();
foreach (GeoCoordinate geoCoordinate in Lieux)
routeRequest.Waypoints.Add(new Waypoint(){Location = geoCoordinate});
var routeService = new RouteServiceClient("BasicHttpBinding_IRouteService");
routeService.CalculateRouteCompleted += new EventHandler<CalculateRouteCompletedEventArgs>(routeService_CalculateRouteCompleted);
routeRequest.Options = new RouteOptions();
routeRequest.Options.Mode = TravelMode.Driving;
routeRequest.UserProfile = new UserProfile() { DistanceUnit = DistanceUnit.Kilometer };
routeService.CalculateRouteAsync(routeRequest);
}

Lieux est donc une collection de GeoCoordinate, le LocationsCollection vu précédemment est parfaitement le type de valeur attendu. Vous pouvez donc tester avec notre objet Points.
Rien de compliqué dans cette première méthode. On créé notre requête, on y ajoute notre credential et nos Waypoints (littéralement “points de passages” Clignement d'œil).
On s’abonne à l’évènement levé lorsque les données seront récupérés, on verra la méthode plus bas.
routeRequest.Options.Mode nous permet de choisir grâce à l’énumération TravelMode entre un trajet en véhicule ou à pied.
Et avec l’UserProfile on peut choisir les unités de distances. La doc vous en apprendra plus !
Nous avons là la requête basique, voyons maintenant comment traiter ses valeurs de retours.

void routeService_CalculateRouteCompleted(object sender, CalculateRouteCompletedEventArgs e)
{
Points.Clear();
var P_Start = new Pushpin();
var P_End = new Pushpin();

P_Start.Location = e.Result.Result.Legs.First().ActualStart;
P_End.Location = e.Result.Result.Legs.Last().ActualEnd;

foreach (RouteLeg leg in e.Result.Result.Legs)
foreach (ItineraryItem itineraryItem in leg.Itinerary)
Points.Add(itineraryItem.Location);
MyMap.Children.Add(P_Start);
MyMap.Children.Add(P_End);
}

La partie la plus intéressante dans le résultat de notre requête est la collection “Legs”. Elle contient des objets Leg qui sont des portions de routes. En effet, un trajet passe par différents points, donc du coup un trajet est un ensemble de petits segments passant par ces points : les legs.

On fait un Clear() sur notre collection de Points histoire de mettre à jour notre trajet.
Je créé ensuite des Pushpins, ces petites flèches sur la carte qui nous permettront de savoir où démarre et finis le trajet.
Je les positionne en utilisant leur propriété Location et en récupérant le premier point du premier leg de ma collection pour le départ et bien sûr le dernier point du dernier leg pour l’arrivée.
Ensuite je parcours la collection pour ajouter à ma liste de points les coordonnées de chaque segment.

On n’oublie pas d’ajouter les push pins à la carte et voilà vous avez votre trajet !
En couplant ça à la géolocalisation et au geocoding de nombreuses possibilités s’offrent à vous !

Par JCVASSELON

Geocoding en Silverlight avec Bing Map

Le geocoding permet de transformer une adresse en coordonnée (latitude, longitude). Au contraire, le reverse geocoding permet de récupérer une adresse à partir de coordonnées.

Nombreuses sont les ressources autour de ce sujet en utilisant les services Bing Map. Que ce soit par une référence web ou en REST en requêtant depuis notre application.
Mais l’utilisation en silverlight est moins documentée. Le développeur se retrouvant dans l’impossibilité d’ajouter une web reference, avec des noms des classes différents, et une utilisation asynchrone…

Dans cet article nous allons donc présenter les prérequis et dégrossir le fonctionnement du geocoding par le code.

Créer un compte bing map

Première étape, créez votre compte Bing Map sur https://www.bingmapsportal.com/.

Une fois votre compte créez cliquez sur “Create or view keys” :

ScreenBingMapPortal

Dans “Application name” entrez le nom de votre application.
Pour “Application URL” donnez l’adresse de la page de votre application ou une adresse quelconque.
Le champ “Application Type” est important, n’hésitez pas à cliquer sur le bouton “What’s this ?” pour plus d’explications. En effet, cela concerne la licence et l’utilisation du service Bing Map par votre application.
Pour cette démo nous utiliserons le type “Developer”.

Une fois la clef générée, gardez-la sous la main nous allons bientôt l’utiliser.

Au sein du projet Silverlight (ou WP7)

Créez donc votre projet silverlight ou Windows Phone 7.
Ajoutez une référence de service à l’adresse : http://dev.virtualearth.net/webservices/v1/geocodeservice/geocodeservice.svc/mex
Pour cet article nous nommerons la référence “GeocodeService”.

Déclarons un objet de type Credentials qui permettra de nous authentifier au service.
Déclarons aussi un objet de type GeocodeRequest pour formuler notre requête.

private GeocodeRequest GeocodeRequest;
private Credentials myCredentials;

Créons ensuite une méthode InitGeocode() dans laquelle nous préparerons l’authentification au service.

private void InitGeoCodeRequest()
        {
            myCredentials = new Credentials();
            myCredentials.ApplicationId = VOTRE_CLEF_GENEREE_DANS_LA_PARTIE_PRECEDENTE;
            GeocodeRequest = new GeocodeRequest();         
            GeocodeRequest.Credentials = myCredentials;
}

Il ne nous reste plus qu’à faire une méthode qui recevra en paramètre un lieu et qui le geocodera.

private void MakeGeocodeRequest(string query)
{
    try
    {
        GeocodeRequest.Query = query;
        var geocodeService = new GeocodeService.GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
        geocodeService.GeocodeCompleted += delegate(object sender, GeocodeService.GeocodeCompletedEventArgs e)
        {
          if (sender != null)
        {
              //Location est une variable que j’utilise pour stocker le résultat de la méthode. A vous de voir comment vous souhaiter le traiter.
              Location = e.Result.Results[0].Locations[0];
         }
        };
        geocodeService.GeocodeAsync(GeocodeRequest);
    }
   catch(Exception ex)
    {
        MessageBox.Show("An exception occurred: " + ex.Message);
    }
}

De la même manière, pour récupérer une adresse depuis des coordonnées, il vous suffit de passer en paramètre un objet de type GeocodeLocation et d’utiliser l’event handler ReverseGeocodeCompleted à la place de GeocodeCompleted.  
Bien évidemment, le delegate prendra un ReverseGeocodeCompletedEventArgs à la place du GeocodeCompletedEventArgs.
Ensuite faites l’appel asynchrone avec la méthode ReverseGeocodeAsync (et non plus GeocodeAsync) sur un objet de type ReverseGeocodeRequest initalisé de la même manière que le GeocodeRequest.
L’objet retourné sera de type Address.

Pour aller plus loin :
http://msdn.microsoft.com/en-us/library/cc966793.aspx
qui vous expliquera ce que retourne le  service : un GeocodeResponse. Il contient un GeocodeResult et la doc est intéressante au niveau de cet élément (plusieurs attributs peuvent vous intéresser comme le type Address introduit plus haut).

Par JC VASSELON

[WP7] Windows Phone 7 et les icônes

Dans cet article nous allons faire le point sur les besoins en illustrations et en icônes d’une application Windows Phone 7.
Pour rappel, vous trouverez un fichier .PSD regroupant les éléments de l’interface dans cet article : http://onefor4.wordpress.com/2010/09/17/wp7-panorama-du-designer-au-developpeur/

Vis-à-vis des icônes officielles – notamment celles qu’on peut retrouver dans les ApplicationBar – un pack a longtemps été disponible au téléchargement à cette adresse : http://go.microsoft.com/fwlink/?LinkId=187311 mais il est maintenant installé par défaut avec vos tools WP7. Vous le trouverez sur votre disque dur à l’emplacement : C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.0\Icons\

Parlons maintenant des illustrations dont a besoin votre application. Notamment l’icône dans la liste des applications, celle que l’on peut placer sur la page d’accueil et la splashcreen.

icones dans le projet

ApplicationIcon.png : Fichier png en 62*62. Correspond à l’illustration dans le menu des applications
Background.png : Fichier png en 173*173. Correspond à l’illustration sur la page d’accueil.
SplashScreenImage.jpg : Attention fichier jpeg ! C’est la page qui s’affichera lors du lancement de votre application.

Attention, dans le cas où vous avez bien ces fichiers dans votre projet et que certains ne s’affichent pas, pensez à bien mettre la Build Action sur "Content".

Propriété Content

Lors de l’ajout sur le Marketplace. Il vous sera demandé :
- Une illustration png en 173*173
- Une illustration png en 99*99 pour le marketplace mobile
- Une illustration png en 200*200 pour le marketplace pc
- Au moins une impression écran png en 480*800 de votre application

Optionnellement vous pouvez ajouter 7 impressions écran de plus et une image png en 1422*800 pour les campagnes de pub sur le background du panorama du marketplace (l’image de fond qu’il y a quand vous vous rendez sur le marketplace depuis votre téléphone).

Par JCVASSELON