Pierre's Embedded and Mobile Blog

Soulevons le capot des systèmes embarqués et mobiles

Posts
  • Pierre's Embedded and Mobile Blog

    Windows Phone 8: les premiers articles techniques de la communauté

    • 0 Comments

    Voila quelques jours que le SDK Windows Phone 8 est disponible et la communauté a déjà été très active pour publier des articles détaillant les nouvelles fonctionnalités de celui-ci… Voici un petit billet pour lister ceux que j’ai trouvé (et que je mettrai à jour au fur et à mesure, n’hésitez pas à commenter).

    La série de Julien Corioland qui était à Build 2012

     

    Du coté de chez Rudy Huyn:

     

    Du coté de chez SOAT:

     

    De la part de Samuel Blanchard:

     

    Par Olivier Matis:

     

    J’en profite pour remettre les miens:

     

    Et du coté de la communauté anglophone, il y a des ressources immanquables:

  • Pierre's Embedded and Mobile Blog

    Windows Phone 8: Faites le plein de nouveautés rapide à intégrer dans votre application

    • 2 Comments

    Windows Phone 8 offre un grand nombre de nouvelles APIs qui vont permettre aux développeurs de proposer de nouvelles expériences à leurs utilisateurs, et améliorer grandement l’intégration dans l’OS. Le but de cet article est de faire le tour des plus faciles et rapides à intégrer.

    Ou sont les outils ?

    Tous les liens importants sont listés dans cet article, alors lancez les téléchargements/installations pendant que vous lisez cet article !

    Les liens utiles du SDK Windows Phone 8

    Que faire du code existant ?

    Réponse courte : on peut tout garder ! 100% des API de Windows Phone 7.0/7.1 sont présentes dans Windows Phone 8. Ceci étant dit, le passage à une nouvelle version et l’ajout de fonctionnalités est souvent l’occasion de ré-architecturer un peu son code. Pourquoi ne pas le rendre plus portable, par exemple pour être présent aussi sous Windows 8 ? Pour cela je vous réfère à la série d’articles sur le portage et le partage de code entre Windows 8 et Windows Phone :

    Stratégies et Techniques de Partage et de Portage de code entre Windows Phone et Windows 8

    Que vous décidiez de modifier votre code existant ou pas, vous pouvez par ailleurs tester votre application sur un Windows Phone 8 et constater que sans rien changer, elle fonctionne, voire noter un gain de performance significatif, principalement dû au nouveau matériel, et aux optimisations réalisées sur l’OS et le Runtime.

    Si vous préférez un document offline et l’application exemple:

    Voici le lien vers le dossier Skydrive contenant les deux:

    http://sdrv.ms/Sx5VsO

     

    Quels sont les nouveaux scénarios possibles ?

    Passons maintenant aux nouveaux scénarios, que nous allons étudier en commençant par les plus rapides à intégrer (de l’ordre de quelques minutes !!) et en poussant vers les plus compliqués.

    En moins d’une heure…

    Vous pourrez avoir intégrer des nouvelles vignettes dynamiques, animées, et de différentes tailles, et de l’intégration sur l’écran de verrouillage. Vous pourrez également profiter des nouveaux launchers et choosers, de l’expérience Nokia Maps, des fonctionnalités de reconnaissance et synthèse vocales, d’un gain de performance non négligeable sur le LongListSelector… et aussi éventuellement revoir vos layouts et vos assets pour les nouvelles résolutions J

    En une demi-journée…

    Associez votre application à des types de fichiers ou des schémas d’URL, devenez une application « Lens » intégrée à l’appareil photo, ou bien un fournisseur de contact pour le hub contacts/people. Profitez de la nouvelle option de géolocalisation en background. Monétisez votre contenu et les bonus de vos applications avec les nouvelles options d’achat In-App.

    Et pour aller plus loin…

    Intégrez de nouvelles fonctionnalités ou du code existant avec le nouveau modèle de développement en C++, tirez parti de la technologie NFC pour s’identifier, payer ou établir une communication entre 2 appareils et profiter ensuite du Bluetooth ou du Wifi pour échanger des données, Intégrez-vous au wallet pour offrir à l’utilisateur d’y retrouver ses cartes de fidélité, cartes de membres, et éventuellement des coupons de réduction… Autoriser l’application à tourner 100% du temps en background pour faire de la géolocalisation… Ces points-là méritent des articles à part entière, nous ne les traiterons donc pas dans cet article-ci.

    Passons à la pratique

    Les nouvelles vignettes dynamiques

    Le nouvel écran d’accueil supporte 3 tailles de vignettes :

    • Les petites, d’environ ¼ de la taille des vignettes « normales »
    • Les vignettes carrées, auxquelles nous étions déjà habituées
    • Les vignettes larges, qui font la taille de deux vignettes carrées

    Avec ces nouvelles tailles viennent de nouveaux modèles, à l’instar des vignettes de Windows 8, qui permettent d’animer (ou pas) votre vignette principale et les vignettes secondaires.

    • StandardTile, qui permet d’avoir une icône, un titre, éventuellement du texte au dos, et un compteur
    • FlipTile, qui se retournera aléatoirement et supporte des contenus sur l’avant et l’arrière de la vignette.
    • CycleTile, qui permettra de faire défiler verticalement du contenu (texte ou photos)
    • IconicTile, qui mettra en valeur votre icône et éventuellement du texte ou un compteur associé.

     

    Chacun de ces modèles existe dans les formats normaux et larges, le petit format étant déduit du premier. A chaque modèle est associé une structure de donnée contenant le texte et éventuellement l’adresse des images qu’on veut afficher, il s’agit des classes héritant de la classe abstraite ShellTileData.

    Comme avant, on pourra donc créer une telle structure de donnée, la remplir avec les informations à afficher, et créer une nouvelle vignette correspondante en appelant la méthode ShellTile.Create( …) pour une nouvelle tuile secondaire, ou bien la méthode Update() pour les vignettes existantes.

     

    FlipTileData ftd = new FlipTileData();
    ftd.Title = "Flip Tile Title";
    ftd.Count = 42;
    ftd.BackBackgroundImage = new Uri("/Assets/Tiles/FlipCycleTileMedium.png", UriKind.Relative);
    ftd.WideBackContent = "Flip Tile Wide Back Content";
    ftd.WideBackBackgroundImage = new Uri("/Assets/Tiles/FlipCycleTileLarge.png", UriKind.Relative);
    ftd.SmallBackgroundImage = new Uri("/Assets/Tiles/FlipCycleTileSmall.png", UriKind.Relative);
    
    ShellTile.Create(new Uri("/Pages/TilesAPI.xaml", UriKind.Relative), ftd, true);

    IconicTileData itd = new  IconicTileData();
    itd.BackgroundColor = Colors.DarkGray;
    itd.Title = "Iconic Tile Title";
    itd.IconImage = new Uri("/Assets/Tiles/IconicTileMediumLarge.png", UriKind.Relative);
    itd.SmallIconImage = new Uri("/Assets/Tiles/IconicTileSmall.png", UriKind.Relative);
    itd.Count = 42;
    itd.WideContent1 = "Wide Content 1";
    itd.WideContent2 = "Wide Content 2";
    itd.WideContent3 = "Wide Content 3";
    
    ShellTile.Create(new Uri("/Pages/TilesAPI.xaml", UriKind.Relative), itd, true);

    var images = new List<Uri>();
    images.Add(new Uri("/Assets/Tiles/FlipCycleTileLarge.png", UriKind.Relative));
    images.Add(new Uri("/Assets/Tiles/FlipCycleTileMedium.png", UriKind.Relative));
    images.Add(new Uri("/Assets/Tiles/FlipCycleTileSmall.png", UriKind.Relative));
    
    CycleTileData ctd = new CycleTileData();
    ctd.Count = 42;
    ctd.CycleImages = images;
    ctd.SmallBackgroundImage = new Uri("/Assets/Tiles/FlipCycleTileSmall.png", UriKind.Relative);
                
    ctd.Title = "Cycle Tile Title";
                
    ShellTile.Create(new Uri("/Pages/TilesAPI.xaml", UriKind.Relative), ctd, true);

    Changer le contenu de l’écran de verrouillage

    Une nouvelle API de Windows Phone 8 permet de changer l’image de fond de l’écran de verrouillage, ainsi que les 3 lignes de texte qui apparaissent sous l’heure, et éventuellement un compteur avec une mini-icône, comme les applications mails.

    Le changement de l’image de fond se fait en appelant d’abord l’API du LockScreenManager pour récupérer l’autorisation de changer celui-ci, puis il suffit de lui indiquer l’URL (locale) de l’image à utiliser. Moins de 10 lignes de code :

     

    try
    {
        if (!LockScreenManager.IsProvidedByCurrentApplication)
        {
            await LockScreenManager.RequestAccessAsync();
        }
    
        if (LockScreenManager.IsProvidedByCurrentApplication)
        {
            Uri imageUri = new Uri("ms-appx:///Assets/wpbackground.png", UriKind.RelativeOrAbsolute);
            Windows.Phone.System.UserProfile.LockScreen.SetImageUri(imageUri);
        }
    }
    catch (Exception ex)
    {
        // Handle exception
    }

    Pour ce qui est du texte et éventuellement du compteur, en fait c’est encore plus simple (et logique) : le lockscreen reprendra le texte et le compteur de la vignette dynamique principale de l’application. Il faut donc que l’application soit épinglée sur l’écran d’accueil et que l’utilisateur ait choisi d’avoir ces notifications sur son écran de verrouillage.

    Devenir un Store de contacts

    Avec la version précédente du SDK, il était possible d’accéder à la liste de contacts (avec des API LINQ) en lecture seule, et éventuellement d’écrire dans un store existant, avec le launcher SaveContactTask.

    Il est maintenant possible de devenir un fournisseur de contacts, au même titre que les réseaux sociaux ou de comptes mails existants nativement. Il faut commencer par créer (ou ouvrir, s’il est déjà créer) le store de contacts propre à l’application :

    var store = await ContactStore.CreateOrOpenAsync();

    Ensuite, on peut y faire des requêtes, pour par exemple afficher la liste des contacts déjà enregistrés par l’application :

    ContactQueryResult cqr = store.CreateContactQuery();
    IReadOnlyList<StoredContact> contacts = await cqr.GetContactsAsync();
    if (contacts.Count > 0)
        Dispatcher.BeginInvoke(() => lbxContacts.DataContext = contacts.ToList());

    Enfin, on peut ajouter de nouveaux contacts simplement:

     

    StoredContact c = new StoredContact(store);
    c.DisplayName = "John Doe";
                
    
    IDictionary<string, object> props = await c.GetPropertiesAsync();
    props.Add(KnownContactProperties.Email, "john@doe.com");
    props.Add(KnownContactProperties.MobileTelephone, "118218");
                
    await c.SaveAsync();

    Facile, et on obtient ensuite une fiche contact dans le hub avec lequel l’utilisateur peut interagir, et éventuellement la lier aux autres fiches qu’il aurait de différentes sources sur le même contact :

    wp_ss_20121031_0001

     

    S’intégrer au calendrier

    En plus des alarmes et des rappels, qui permettaient d’imiter l’expérience native du réveil ou du calendrier pour rappeler à l’utilisateur un évènement, et en plus de l’accès en lecture seule au calendrier, l’arrivée de Windows Phone 8 rajoute un launcher qui permet de sauvegarder un évènement dans le calendrier :

    SaveAppointmentTask sat = new SaveAppointmentTask();
    sat.StartTime = DateTime.Now + TimeSpan.FromDays(1);
    sat.Details = "Details of the appointment";
    sat.Subject = "Appointment generated from an app";
    sat.EndTime = sat.StartTime + TimeSpan.FromHours(2);
    
    sat.Location = "location";
    sat.Show();

    Rajouter le partage de photos/vidéos sur les réseaux sociaux

    A l’instar des ShareLinkTask et ShareStatusTask qui permettent, depuis Windows Phone 7.5, de partagere des liens et des statuts sur les réseaux sociaux, la nouvelle ShareMediaTask va permettre de partager des photos et des vidéos.

     

    ShareMediaTask smt = new ShareMediaTask();
    smt.FilePath = "/Assets/ApplicationIcon.png";
    
    smt.Show();

    Profiter du LongListSelector natif

    Ce contrôle, qui était avant fourni dans le Silverlight Toolkit (qui s’appelle maintenant le Windows Phone Toolkit) est maintenant natif. Au menu, le même usage, mais de meilleures performances. Changez juste l’assembly !

    <DataTemplate x:Key="AddrBookItemTemplate">
        <StackPanel VerticalAlignment="Top">
            <TextBlock FontWeight="Bold"  Text="{Binding Name}" />
        </StackPanel>
    </DataTemplate>
    
    <DataTemplate x:Key="AddrBookGroupHeaderTemmplate">
        <Border Background="Transparent" Padding="5">
            <Border Background="{StaticResource PhoneAccentBrush}" BorderBrush="{StaticResource PhoneAccentBrush}" BorderThickness="2" Width="62" 
        Height="62" Margin="0,0,18,0" HorizontalAlignment="Left">
                <TextBlock Text="{Binding Key}" Foreground="{StaticResource PhoneForegroundBrush}" FontSize="48" Padding="6" 
        FontFamily="{StaticResource PhoneFontFamilySemiLight}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
            </Border>
        </Border>
    </DataTemplate>
    
    <phone:JumpListItemBackgroundConverter x:Key="BackgroundConverter"/>
    <phone:JumpListItemForegroundConverter x:Key="ForegroundConverter"/>
    <Style x:Key="AddrBookJumpListStyle" TargetType="phone:LongListSelector">
        <Setter Property="GridCellSize"  Value="113,113"/>
        <Setter Property="LayoutMode" Value="Grid" />
        <Setter Property="ItemTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Border Background="{Binding Converter={StaticResource BackgroundConverter}}" Width="113" Height="113" Margin="6" >
                        <TextBlock Text="{Binding Key}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" FontSize="48" Padding="6" 
            Foreground="{Binding Converter={StaticResource ForegroundConverter}}" VerticalAlignment="Center"/>
                    </Border>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>

     

    <phone:LongListSelector x:Name="lls" 
                            GroupHeaderTemplate="{StaticResource AddrBookGroupHeaderTemmplate}"
                            ItemTemplate="{StaticResource AddrBookItemTemplate}"
                            JumpListStyle="{StaticResource AddrBookJumpListStyle}"
                            LayoutMode="List"
                            HideEmptyGroups="True"
                            IsGroupingEnabled="True" />

    Comment gérer proprement les nouvelles résolutions ?

    Les terminaux Windows Phone 7 et 7.5 n’avaient qu’une seule définition : WVGA, soit 800x480. Avec Windows Phone 8, les fabricants ont la possibilité d’utiliser 2 nouvelles définitions en plus : WXGA (1280x768) et 720p (1280x720). Dans le cas de la première, on garde le même ratio largeur/hauteur, mais pas dans le second ! Il va donc y avoir une petite bande noire en haut de l’écran (de 53px) si vous n’adaptez pas votre layout dynamiquement (la feinte principale consistant à utiliser des "*" et des "Auto" dans les propriétés des tailles de vos contrôles. Une page de la documentation est dédiée à ce sujet et vous permettra de comprendre ce qu’il faut faire pour tirer parti de toutes les résolutions au mieux :

    Multi-Resolution Apps for Windows Phone

    Pour ce qui est des assets graphiques, (images, etc) vous avez la possibilité de les resizer dynamiquement (dans ce cas je vous conseille de les prévoir pour la résolution 1280x768 et faire du downscaling plutôt que l’inverse), ou bien d’utiliser un petit helper qui permet de savoir sur quelle image se binder en fonction de la résolution :

    Une classe statique, ResolutionHelper, qui retourne de manière lisible la définition de l’écran :

    public enum Resolutions { WVGA, WXGA, HD720p };
    
    public static class ResolutionHelper
    {
        private static bool IsWvga
        {
            get
            {
                return Application.Current.Host.Content.ActualHeight == 800
                && Application.Current.Host.Content.ScaleFactor == 100;
            }
        }
    
        private static bool IsWxga
        {
            get
            {
                return Application.Current.Host.Content.ScaleFactor == 160;
            }
        }
    
        private static bool Is720p
        {
            get
            {
                return Application.Current.Host.Content.ScaleFactor == 150;
            }
        }
    
        public static Resolutions CurrentResolution
        {
            get
            {
                if (IsWvga) return Resolutions.WVGA;
                else if (IsWxga) return Resolutions.WXGA;
                else if (Is720p) return Resolutions.HD720p;
                else throw new InvalidOperationException("Unknown resolution");
            }
        }
    }

    Ensuite une classe sur laquelle l’interface pourra se binder et qui renverra l’image adaptée :

    public class MultiResImageChooser
    {
        public Uri BestResolutionImage
        {
            get
            {
                switch (ResolutionHelper.CurrentResolution)
                {
                    case Resolutions.HD720p:
                        return new Uri("/Assets/ResolutionDependent/720x1280.jpg", UriKind.Relative);
                    case Resolutions.WXGA:
                        return new Uri("/Assets/ResolutionDependent/768x1280.jpg", UriKind.Relative);
                    case Resolutions.WVGA:
                        return new Uri("/Assets/ResolutionDependent/480x800.jpg", UriKind.Relative);
                    default:
                        throw new InvalidOperationException("Unknown resolution type");
                }
            }
        }
    }

    Et pour finir, dans l’interface, instancier cette classe sous forme d’une StaticResource et se binder sur le champ approprié :

    <phone:PhoneApplicationPage.Resources>
        <helpers:MultiResImageChooser x:Key="MultiResImageChooser" />
    </phone:PhoneApplicationPage.Resources>
    <
    Image Source="{Binding BestResolutionImage, Source={StaticResource MultiResImageChooser}}"/>

    Enfin, pour ce qui est du SplashScreen, il suffit de le mettre en 3 versions (pour les 3 résolutions) dans le XAP avec la convention de nommage suivante :

    • SplashScreenImage.Screen-WXGA.jpg
    • SplashScreenImage.Screen-WVGA.jpg
    • SplashScreenImage.Screen-720p.JPG

     

    Et le système s’en sortira tout seul !

    Passer à Nokia Maps

    Si vous utilisez le contrôle Map, vous pouvez profiter de la qualité des cartes vectorielles de Nokia Maps quel que soit la marque du téléphone de votre utilisateur, en quelques étapes très simples :

    1. Migrer votre projet à Windows Phone 8
    2. Enlever la référence à l’assembly Bing Maps et changer les namespaces là où ça s’impose
    3. Rajouter la capability « ID_CAP_MAP » dans votre manifest
    4. Recompiler

     

    Pas besoin de changer le code, sauf peut-être pour enlever la clef d’API ;)

    Sachez que les launchers BingMapsTask et BingMapsDirectionTask ouvriront également automatiquement Nokia Maps et non plus Bing Maps.

    Vous pouvez également profiter des nouveaux launchers MapsTask, MapsDirectionTask, et MapsDownloadTask,  qui offrent respectivement l’accès à l’application Nokia Maps, au guidage tour-par-tour, et au téléchargement de cartes pour une utilisation offline. Un exemple avec la MapsTask :

    MapsTask mt = new MapsTask();
    mt.ZoomLevel = 15;
    mt.SearchTerm = "Pizza";
                
    mt.Show();

    Rajouter la reconnaissance et la synthèse vocale

    Avec la reconnaissance vocale, vous allez pouvoir demander à l’utilisateur de parler à votre application, et récupérer le texte déduit par le moteur intégré à Windows Phone. La synthèse vocale, quant à elle, vous permettra de faire lire à l’application du texte, ce qui améliorera l’accessibilité de votre application.

    Reconnaissance vocale : avec l’interface standard, ou la vôtre !

    Voici comment utiliser l’interface graphique du système pour lancer la reconnaissance vocale :

    // Create an instance of SpeechRecognizerUI.
    var speechRecognizerWithUI = new SpeechRecognizerUI();
    
    // Start recognition (load the dictation grammar by default).
    SpeechRecognitionUIResult recoResult = await speechRecognizerWithUI.RecognizeWithUIAsync();
    
    // Do something with the recognition result.
    tbSpeechRecognized.Text = recoResult.RecognitionResult.Text + " || confidence: " + recoResult.RecognitionResult.TextConfidence;

    Vous pouvez également lancer la reconnaissance vocale avec votre propre interface, mais attention à bien guider l’utilisateur ! Voici un exemple minimaliste, avec une boite de message indiquant juste que la reconnaissance vocale va démarrer :

    if (MessageBox.Show("Recognize?", "SpeechRecognizer", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
    {
        speechRecognizer = new SpeechRecognizer();
        var recoResult = await speechRecognizer.RecognizeAsync();
        tbSpeechRecognized.Text = recoResult.Text + " || confidence: " + recoResult.TextConfidence;
    }
    Synthèse vocale : simple comme bonjour ;)

    Pour vocaliser du texte, il suffit de le passer en argument à une instance de la classe SpeechSynthesizer, en ayant précisé la voix à utiliser… sachant que l’utilisateur peut choisir une langue dans les paramètres du téléphone indépendamment de la langue de son interface graphique. Voici un petit exemple qui lit le contenu d’une TextBox :

    // Initialize the SpeechSynthesizer object.
    SpeechSynthesizer synth = new SpeechSynthesizer();
    
    // Query for a voice that speaks French.
    var Voices = from voice in InstalledVoices.All
                    where voice.Id == (lbxVoices.SelectedItem as VoiceInformation).Id
                    select voice;
    
    // Set the voice as identified by the query.
    synth.SetVoice(Voices.ElementAt(0));
    
    await synth.SpeakTextAsync(tbxSpeech.Text);

    L’association avec des extensions de fichier et des schémas d’URL

    Voici une nouvelle option qui permettra à d’autres applications de lancer directement la vôtre, et d’avoir vos propres formats de fichier pour échanger des données d’un utilisateur à un autre.

    S’associer avec des extensions de fichiers

    Pour s’associer avec une extension, il faut signaler au système qu’on a cette capacité : cela se passe évidemment dans le manifest de l’application, dans lequel il faut rajouter, dans la partie extensions :

    <FileTypeAssociation Name="Windows Phone SDK test file type" TaskID="_default" NavUriFragment="fileToken=%s">
      <Logos>
        <Logo Size="small">/Assets/apitests-small-33x33.png</Logo>
        <Logo Size="medium">/Assets/apitests-medium-69x69.png</Logo>
        <Logo Size="large">/Assets/apitests-large-176x176.png</Logo>
      </Logos>
      <SupportedFileTypes>
        <FileType ContentType="application/text">.apitests</FileType>
      </SupportedFileTypes>
    </FileTypeAssociation>

    Quand un fichier est téléchargé, par le navigateur, par email ou par une autre application, et que l’utilisateur tente de l’ouvrir en tapant sur l’icône de celui-ci (fournie, au passage, également par votre application), le système lancera votre application, avec en paramètre, un « token » permettant de récupérer ce fichier. La bonne pratique est donc de vérifier, en utilisant un UriMapper, si un nom de fichier est passé en paramètre au lancement pour éventuellement rediriger vers la page idoine, et l’ouvrir.

    class ApiTestsUriMapper : UriMapperBase
    {
        private string tempUri;
    
        public override Uri MapUri(Uri uri)
        {
            tempUri = System.Net.HttpUtility.UrlDecode(uri.ToString());
            
            if (tempUri.Contains("/FileTypeAssociation")) // File association launch
            {
                // Get the file ID (after "fileToken=").
                int fileIDIndex = tempUri.IndexOf("fileToken=") + 10;
                string fileID = tempUri.Substring(fileIDIndex);
    
                // Get the file name.
                string incomingFileName = SharedStorageAccessManager.GetSharedFileName(fileID);
    
                // Get the file extension.
                int extensionIndex = incomingFileName.LastIndexOf('.');
                string incomingFileType =
                    incomingFileName.Substring(extensionIndex).ToLower();
    
                // Map the .apitests extension to the right page.
                switch (incomingFileType)
                {
                    case ".apitests":
                        return new Uri("/Pages/FileAssociationPage.xaml?fileToken=" + fileID, UriKind.Relative);
                    default:
                        return new Uri("MainPage.xaml", UriKind.Relative);
                }
            }
            // Otherwise perform normal launch.
            return uri;
        }
    }
    

    Une fois dans la page, il faut utiliser les APIs SharedFolder pour récupérer le fichier passé en paramètre :

    protected async override void OnNavigatedTo(NavigationEventArgs e)
    {
        try
        {
            var fileToken = NavigationContext.QueryString["fileToken"];
            this.fileName = SharedStorageAccessManager.GetSharedFileName(fileToken);
                    
            var storageFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
                    
            var localFile = await SharedStorageAccessManager.CopySharedFileAsync(storageFolder, this.fileName, NameCollisionOption.ReplaceExisting, fileToken);
    
            using(var content = await localFile.OpenReadAsync())
            {
                using (DataReader dr = new DataReader(content))
                {
                    await dr.LoadAsync((uint)content.Size);
                    fileContent = dr.ReadString((uint)content.Size);
                }
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
        finally
        {
            base.OnNavigatedTo(e);
        }
    }
    
    S’associer avec des schemas d’URI

    L’association avec des schémas d’URI fonctionne sur le même principe que l’association avec des extensions de fichier. On déclare le support dans le manifest :

    <Protocol Name="apitests" NavUriFragment="encodedLaunchUri=%s" TaskID="_default" />
    

    Puis on utilise un UriMapper pour capturer le lancement éventuel avec une URI en paramètre, afin de le traiter :

    class ApiTestsUriMapper : UriMapperBase
    {
        private string tempUri;
    
        public override Uri MapUri(Uri uri)
        {
            tempUri = System.Net.HttpUtility.UrlDecode(uri.ToString());
            
    if (tempUri.Contains("apitests:UriAssociation?Parameter=")) // URI assocation launch
            {
                // Get the category ID (after "CategoryID=").
                int paramIndex = tempUri.IndexOf("Parameter=") + 10;
                string param = tempUri.Substring(paramIndex);
    
                // Map the show products request to ShowProducts.xaml
                return new Uri("/Pages/UriAssociationPage.xaml?Parameter=" + param, UriKind.Relative);
            }
    
            // Otherwise perform normal launch.
            return uri;
        }
    
    }
    

    Une fois la page chargée, il suffit de récupérer le paramètre dans le NavigationContext :

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        try
        {
            parameter = NavigationContext.QueryString["Parameter"];
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
        finally
        {
            base.OnNavigatedTo(e);
        }
    }
    
    Lancer une application tierce depuis un fichier ou une URI dans l’application

    Pour lancer une application tierce depuis un fichier ou une Uri, il suffit d’appeler une API du système, qui automatiquement proposera à l’utilisateur de télécharger une appli ayant la capacité d’ouvrir ce type du contenu si il n’y en a pas déjà d’installée. Ça tient en une ligne de code :

     

    await Windows.System.Launcher.LaunchUriAsync(new Uri("apitests:UriAssociation?Parameter=" + tbParameter.Text));
    

    Il est également possible de lancer des pages de l’interface native (paramètres, etc) en suivant le même principe, avec les schémas d’uri réservés du système documentés.

    Devenir une « Lens app » et s’intégrer à l’expérience de prise de photo

    La photo est de plus en plus au cœur de Windows Phone : dorénavant, il existe un petit bouton (matérialisé par deux flèches) dans l’application-bar de l’application photo native, qui permet de choisir une application pour prendre la photo, en y appliquant des filtres par exemple pour modifier l’apparence de la photo, y appliquer un traitement, la partager directement… A vous d’inventer ces nouveaux usages !

    Pour cela, vous devez vous enregistrer cette extension dans votre manifeste, puis vérifier au lancement de l’application, à l’aide d’un UriMapper par exemple, si la chaine de caractère « ViewfinderLaunch » est présente dans l’URL. et si c’est le cas, c’est que votre application est lancée depuis l’appareil photo. Dans ce cas-là, un simple UriMapper vous permettra de rediriger l’utilisateur vers une page de votre application qui appliquera votre traitement, tout en veillant de respecter les recommandations de design spécifique à ce type de page qui sont disponibles ici :

    Lens Design Guidelines for Windows Phone

    Voici l’exemple d’extension à rajouter dans le fichier WMAppManifest.xml :

    <Extension ExtensionName="Camera_Capture_App" ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5631}" TaskID="_default" />
    

    Et celui de l’UriMapper :

     

    PrFont34Bin0BinSub0Frac0Def1Margin0Margin0Jc1Indent1440Lim0Lim1class ApiTestsUriMapper : UriMapperBase
    {
        private string tempUri;
    
        public override Uri MapUri(Uri uri)
        {
            tempUri = System.Net.HttpUtility.UrlDecode(uri.ToString());
            // Look for a URI from the lens picker.
            if (tempUri.Contains("ViewfinderLaunch"))
            {
                // Launch as a lens, launch viewfinder screen.
                return new Uri("/Pages/Lense.xaml", UriKind.Relative);
            }
    
            // Otherwise perform normal launch.
            return uri;
        }
    
    }
    

    En enregistrant cette extension et cet UriMapper, la page « Lense.xaml » contenue dans le dossier « Pages » sera automatiquement lancée, si l’application est lancée depuis l’appareil photo. Attention à ne pas oublier d’inclure également l’iconographie correspondante pour que votre application apparaisse correctement dans la liste des lentilles (le LensPicker) : à savoir :

    Phone resolution

    Icon size (pixels)

    Folder

    File name

    WVGA

    173 x 173

    Assets

    Lens.Screen-WVGA.png

    HD720p

    259 x 259

    Assets

    Lens.Screen-720p.png

    WXGA

    277 x 277

    Assets

    Lens.Screen-WXGA.png

     

    En plus de pouvoir être identifié dans le hub photo comme une application qui peut prendre des photos en entrée (PhotoViewer), ou les partager, vous pouvez maintenant également faire identifier votre application comme éditeur de photo, ou mieux, « appliquant un traitement riche sur une image ». Dans ce cas, les photos que vous aurez prise depuis votre application pourront être rééditez dans votre application directement depuis leur fiche dans le hub photo. Dans tous les cas, cela passe par un ajout d’extension à votre manifest :

    <!-- Extend the photo edit picker. -->
    <!-- This is only for Windows Phone 8 apps. -->
    <Extension ExtensionName="Photos_Extra_Image_Editor" 
                ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5632}" 
                TaskID="_default" />
    
    
    <!-- Integrate as a rich media app. -->
    <!-- This is only for Windows Phone 8 apps. -->
    <Extension ExtensionName="Photos_Rich_Media_Edit" 
                ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5632}" 
                TaskID="_default" />
    

     

    Puis un bout de code dans un UriMapper pour rouvrir la bonne page (vous allez commencer à connaitre le système ;)) :

     

    PrFont34Bin0BinSub0Frac0Def1Margin0Margin0Jc1Indent1440Lim0Lim1// Launch from the photo edit picker.
    // This is only for Windows Phone 8 apps.
    // Incoming URI example: /MainPage.xaml?Action=EditPhotoContent&FileId=%7Bea74a960-3829-4007-8859-cd065654fbbc%7D
    if ((tempUri.Contains("EditPhotoContent")) && (tempUri.Contains("FileId")))
    {
        // Redirect to PhotoEdit.xaml.
        mappedUri = tempUri.Replace("MainPage", "PhotoEdit");
        return new Uri(mappedUri, UriKind.Relative);
    }
    
    
    // Launch from the rich media "Open in" link.
    // This is only for Windows Phone 8 apps.
    // Incoming URI example: /MainPage.xaml?Action=RichMediaEdit&token=%7Bed8b7de8-6cf9-454e-afe4-abb60ef75160%7D
    if ((tempUri.Contains("RichMediaEdit")) && (tempUri.Contains("token")))
    {
        // Redirect to RichMediaPage.xaml.
        mappedUri = tempUri.Replace("MainPage", "RichMediaPage");
        return new Uri(mappedUri, UriKind.Relative);
    }
    

    Pour comprendre tout ce qu’on peut faire avec le hub photo, le mieux est encore de se référer au code d’exemple dédié à ça :

    Photo Extensibility Sample

    Il existe encore plein d’autres sujets et nouveautés, qui méritent des articles à part entière pour en faire le tour : In-App Purchase, Intégration avec le Wallet, Utilisation de NFC que ce soit avec des tags ou bien pour appairer des appareils entre eux et échanger des données… sans compter les nouveautés du support C++ (et l’arrivée de frameworks type Unity ou Havok) ou HTML5 avec IE10 ! Beaucoup d’autres articles en prévision donc ;)

  • Pierre's Embedded and Mobile Blog

    Le SDK Windows Phone 8 est disponible!

    • 1 Comments

    Windows Phone 8 SDK sur le Download Center Microsoft

    Il s’agit du web-installer: autrement dit, il installe les composants en même temps qu’il le télécharge. Si vous voulez une iso complète à installer offline, le lien est sur la même page, un peu caché en dessous, je vous le remet ici:  ISO Complète du SDK Windows Phone 8

    Des nouveaux outils

    Ce SDK amène évidemment énormément de nouvelles APIs, que j’aurai l’occasion d’exposer dans un article séparé. En ce qui concerne les outils en eux-même, sachez qu’on passe à Visual Studio 2012, à une nouvelle version de Blend, qu’on ajoute en plus des images 7.1 existantes des images d’émulateurs WVGA, WXGA et 720p. Ces émulateurs reposent sur la technologie Hyper-V, qui nécessite une machine avec Windows 8, en 64bits, et une fonctionnalité appelée SLAT qui améliore le support de la virtualisation. Si vous voulez tester votre machine pour savoir si elle supporte le SLAT, lisez ce petit how-to.

    Du coté de Visual Studio, on va retrouver un nouveau Simulation Dashboard permettant de déclencher des évènements comme les reminders ou le verrouillage du téléphone et de simuler l’état du réseau. Le profiler de performances s’améliore également au passage avec plus d’infos. Enfin, l’éditeur de pages repose maintenant sur Blend et permet de concevoir l’application d’un seul coup pour les différentes résolutions. On a au passage rajouté un éditeur de manifest un peu plus graphique que ce qu’on avait avant…

    Enfin les templates de projets ont été améliorés pour supporter nativement la localisation et la globalisation de l’application, et pour rajouter le support des nouveautés du runtime, notamment DirectX.

    Des exemples de code

    De nombreux exemples de code sont déjà disponibles ici pour illustrer les nouvelles fonctionnalités du SDK

    Le Toolkit Nouveau

    Le Windows Phone Toolkit est maintenant, pour plus de clarté, séparé du Silverlight Toolkit, sur codeplex. Certains contrôles sont devenus natifs (comme le LongListSelector) il faut donc cette nouvelle version pour en profiter dans les applications Windows Phone:

    http://phone.codeplex.com/

    Des sites plus clairs

    Au cas où vous les chercheriez… Voici…

     

    Et aussi au cas où, sur les blogs officiels

  • Pierre's Embedded and Mobile Blog

    Dev Camp: Design d’une application Windows 8 et Windows Phone, par les designers, pour les développeurs

    • 1 Comments

    a89ff0a3-df21-440d-8132-bfab3d9c9f2bVous êtes développeurs, et que vous ailliez la chance de travailler avec un designer, un ergonome ou un graphiste, ou pas, vous aimeriez comprendre un peu mieux leur monde? le 29 novembre, nous vous invitons pour une après-midi faite pour vous Sourire  En voici le pitch:

    Le design d’une application moderne, que ce soit sur Windows 8 ou Windows Phone, repose sur un certain nombre de codes. Ces codes sont souvent exprimés dans le langage des designers interactifs, graphistes et autres ergonomes, mais sont souvent incompris des développeurs, qui n’ont pas nécessairement le background et les études pour en comprendre les tenants et aboutissants.

    Durant ce devcamp, des designers qui ont l’habitude de travailler avec les développeurs reviendront à la fois sur les fondamentaux, mais aussi sur les petits raffinements, qui font qu’une application aussi simple soit-elle, devient une expérience exceptionnelle pour l’utilisateur : le but : familiariser les développeurs avec ce langage, ces codes, car nombre d’entre eux n’ont pas la chance de travailler avec des designers.

    Un agenda qui couvre à la fois les fondamentaux, et des conseils pratiques pour vos applications:

    • Le design moderne dans Windows 8 /  Windows Phone
    • Le savant mélange d’une image de marque et du style moderne
    • Les composants fondamentaux d’une interface
    • Les outils pratiques et l’intégration

     

    Inscrivez-vous, et RDV le 29 Novembre au centre de conférence Microsoft

  • Pierre's Embedded and Mobile Blog

    Debugger sur une tablette Windows 8 depuis son PC

    • 0 Comments

    Debugger du code directement sur un téléphone ou une carte électronique, piloté depuis le PC du développeur, c’est assez classique dans les systèmes embarqués et le monde mobile. C’est aussi possible avec les tablettes Windows 8, et nettement plus pratique que d’avoir tout le tooling Visual Studio installé dessus, comme on peut le voir beaucoup en ce moment. Il suffit d’installer le Remote Debugger dessus (s’il n’est pas déjà inclus dans l’image de Windows qui est installée). Vous pouvez configurer le remote debugger comme un service qui tourne en permanence, ou comme une application, qui ne tourne donc que quand on l’active. Je préfère la seconde méthode… qui est par ailleurs celle recommandée. on obtient alors cette fenêtre:

    remote dbg

     

    Directement depuis son projet, on peut ensuite choisir de debugger sur la tablette plutôt que sur le poste local: ça se configure dans l’onglet Debug de votre projet:

     

    remote dbg 2

    Le bouton “find” permet de trouver votre tablette, et il est possible d’entrer un nom d’utilisateur et un mot de passe pour sécuriser la connexion et éviter que n’importe qui se connecte n’importe où.

     

    remote dbg 3

     

    Ensuite, lancer le projet pour un debuggage comme d’habitude (la touche F5, le bouton Debug…) et l’application se lancera sur la machine distante, plutôt que sur la machine locale. Facile Sourire 

    Pour tout savoir sur le remote debugger, la page de doc sur MSDN et le HowTo officiel.

    Happy debugging!

  • Pierre's Embedded and Mobile Blog

    La rentrée des accélérateurs : les programmes d'accompagnement des développeurs de Microsoft France

    • 1 Comments

    Les accélérateurs Windows Phone et Windows 8 sont les programmes d’accompagnement qui permettent aux développeurs de rentrer en contact avec Microsoft. Le but avoué : faciliter l’arrivée sur les stores des applications, en faisant sauter les barrières à l’adoption des technologies, et les freins au développement et à la certification. Pas de critère à l’entrée, mais plein de bénéfices à la sortie…

    clip_image002

    L’accélérateur Windows Phone a démarré depuis l’an dernier, et a déjà accompagné jusqu’au store plusieurs centaines de développeurs, et au moins autant d’applications. Au programme :

    • Des prêts de téléphones
    • Des "jetons" pour obtenir gratuitement un compte de développeur sur le store Windows Phone (et donc la possibilité de débloquer des téléphones pour le debuggage, et de publier des applications)
    • Du support technique
    • Du coaching régulier avec des membres actifs de la communauté à la technicité reconnue
    • Des webcasts dédiés aux questions les plus remontées par les développeurs de l’accélérateur.
    • De la visibilité avec la mise en avant des applications sur le store.

     

    clip_image004

    L’accélérateur Windows 8 est plus récent, évidemment, mais il compte déjà plusieurs centaines de développeurs…

    Au programme :

    • La possibilité de tester son application sur des tablettes Windows 8 de référence
    • Du coaching et des webcasts/sessions dédiées, à la fois sur les aspects développement et design, par des experts de Microsoft France
    • Du support technique
    • De la visibilité avec la mise en avant des applications sur « l’appli du jour »… et pour les développeurs avec les plus belles applications, une arrivée sur le store en avant-première (et des dizaines de milliers de downloads d’avance !)

     

    Encore une fois, les accélérateurs n’ont pas de critère d’entrée – quel que soit votre projet ou votre plateforme préférée, si vous faites une application, vous pouvez nous contacter. Derrière ces programmes, des « vraies personnes » vous répondent (pas de robots, de mails automatisés, ou de formulaires à la noix), et surtout, pas de pub, juste du concret, et peut-être le début du succès… Certains développeurs se sont même inscrits aux deux programmes ! Voici les liens vers les pages officielles :

     

    N’hésitez pas aussi, à nous dire ce dont vous avez besoin Sourire ces programmes sont faits pour vous, et sont prévus pour évoluer avec vos idées!

  • Pierre's Embedded and Mobile Blog

    Les rendez-vous de la rentrée

    • 2 Comments

    fierdetredev3Cette année va être riche en opportunités pour les développeurs – des lancements de nouvelles plateformes, de nouveaux terminaux, et beaucoup d’évènements techniques pour se retrouver et en parler. Rien que sur Septembre:

     

    Paris n’est pas la seule ville concernée par les évènements de rentrée, en effet, nous organisons également un Tour de France Windows 8 pour les développeurs (avec du Windows Phone Inside Clignement d'œil):

     

    Comment faire pour se tenir au courant des évènements?

    Il faut suivre, car il y a plusieurs endroits clefs en fonction des types d’évènements:

     

    et du coté des communautés:

  • Pierre's Embedded and Mobile Blog

    Annuaires d’APIs pour développeurs en mal d’idées

    • 0 Comments

    ideaJ’ai souvent l’occasion de croiser des développeurs qui ont envie de coder mais pas vraiment d’idée d’applications – on dirait même que c’est une tendance car la plupart des hackathons auxquels j’ai assisté récemment commencent par des pitchs d’idées, avant de se lancer dans le code, pour constituer des équipes.

    On ressort souvent les grands classiques du genre “branche toi sur une source opendata!” mais la vérité c’est que ces sources sont rarement dynamiques (paye ton bon gros fichier CSV statique) et que ce n’est pas évident d’en faire quelque chose d’utile (une énième copie d’iToilettes?).

    Il existe pourtant sur le web quelques “annuaires” d’APIs, officielles ou pas, payantes ou pas, mais qui sont des mines d’idées, surtout quand on les combine entre elles!

     

    Presque sur le même principe, certains sites proposent des outils pour créer des APIs: ils ont souvent une liste de références intéressantes de gens qui utilisent leur backend: cet article de ProgrammableWeb en liste 11

    Enfin, n’hésitez pas à chercher dans les petites lignes en bas de vos sites favoris… il se pourraient bien qu’il y ait une API accessible sur laquelle le site ne fait pas vraiment de pub…

    Dernier point (et pas des moindres) : toutes les APIs ont des conditions d’utilisation, et ce n’est pas parce qu’une API est ouverte sur le net, qu’elle est automatiquement libre de droit et utilisable par n’importe qui n’importe comment… si vous voulez évitez les lettres de type “cease & desist” des ayant-droits des données… lisez les petites lignes!

    Happy summer coding!

  • Pierre's Embedded and Mobile Blog

    Prototyping a connected object using the .NET Gadgeteer: the example of a steampunk meteo station

    • 2 Comments

    clip_image002[6]

    For years I’ve had this very old voltmeter I wanted to do something with: I liked the beautiful wooden case, the leather strap, but honestly, I had better tools for my day to day electronics experiments. I found a purpose for it when I started experimenting with the .NET Gadgeteer kit, and one of my first prototype of connected object: a simple meteo station that would measure temperature, humidity and pressure and upload data to a feed in Cosm, formerly known as Pachube, which is a connected objects web platform used to publish and consume realtime data. I had two goals with this project: have fun with the .NET Gadgeteer kits, and experiment on a complete connected object prototyping cycle (I’m not going to talk about industrialization or mass production here).

    Here’s the plan:

    1. Discovering the .NET Gadgeteer tooling, and interfacing with sensors
    2. Connecting to Cosm (Pachube)
    3. Creating the steampunk GUI
    4. Making the meteo station user-configurable using a small webserver
    5. Prototyping the finished design using 3D modeling tools

     

    >> If you want to download the whole article in a Word document, here’s the link. <<

    Discovering the .NET Gadgeteer tooling, and interfacing with sensors

    The .NET Gadgeteer is a rapid prototyping environment for connected objects. Kits are manufactured by Microsoft partners, like GHI Electronics (http://www.ghielectronics.com), Seed Studio (http://www.seeedstudio.com/depot/), or the Mountaineer Group (http://www.mountaineer.org/). The core libraries (based on the .NET Micro Framework: (http://www.netmf.com)) are maintained by Microsoft and the community, while the hardware specific drivers and updaters are maintained by the different partner.

    Therefore, there are 3 different packages to install on top of Visual Studio 2010 (any version, Express will do) to install the .NET Gadgeteer tools: the .NET Micro Framework base, the Gadgeteer Core, and the hardware specific SDK. In our case, we are going to use a FEZ Spider Kit from GHI Electronics as well as a couple of sensors and a Wifi module.

    Once you have installed everything, you can create your first .NET Gadgeteer application. You are then presented with a “designer” view of your project: at this time there’s only one motherboard in the designer. Using the toolbox, you can add the modules you are going to use. Once you have all the modules you need, you can either click on the connectors to wire them manually or right-click anywhere on the designer and select “Connect all modules”. If you don’t know anything about hardware, this will show you how to connect modules to the motherboard. Once this is done, you’re ready to start coding!

    clip_image004[6]

    Click on Program.cs to dive into the source code. At this point there’s only the main entry point, and a debug instruction. However all the objects needed to control the hardware have already been instantiated (in the Program.Generated.Cs file) and can be used right away. For example, if you have a temperature sensor, you can directly subscribe to the MeasurementComplete event, that will fire whenever a new measure is ready.

    In our case, we are going to use a timer to regularly measure the meteorological parameters (temperature, pressure, and humidity). Everytime the timer fires, we will ask the different sensors to start measuring and they will notify us through their respective MeasurementComplete event that a new measure is ready.

    First register for sensor events:

    temperatureHumidity.MeasurementComplete += new TemperatureHumidity.MeasurementCompleteEventHandler(temperatureHumidity_MeasurementComplete);
    barometer.MeasurementComplete += new Barometer.MeasurementCompleteEventHandler(barometer_MeasurementComplete);

     

    Then instantiate the timer and start it:

    GT.Timer SensorTimer = new GT.Timer(TimeSpan.FromTicks(TimeSpan.TicksPerMinute));
    SensorTimer.Tick += new GT.Timer.TickEventHandler(timer_Tick);
    SensorTimer.Start();
    And here’s the timer handler code:
     

    void timer_Tick(GT.Timer timer)
    {
        barometer.RequestMeasurement();
        temperatureHumidity.RequestMeasurement();
    }
    

    At this point, you already have an object that regularly measure meteorological parameters. You can compile and run it directly on the .NET Gadgeteer kit by connecting it to a USB port on your PC. It’s not connected though; we will handle that in the next part.

    Connecting to Cosm

    Before connecting to Cosm, we need to connect to a network. GHI Electronics offer different modules, we’ll talk about the Wifi Module, and the Ethernet (J11D) module .When purchasing anyone of them, pay attention that there are different references depending on the motherboard you’re using. Read the docs!

    The Ethernet module is the easier to program: here’s the code to connect to a network using DHCP:

    ethernet.NetworkSettings.EnableDhcp();

    The static equivalent:

    ethernet.NetworkSettings.EnableStaticIP("192.168.0.10", "255.255.255.0", "192.168.0.1");
    string[] dnsServers = { "192.168.0.1", "192.168.0.2" };
    ethernet.NetworkSettings.EnableStaticDns(dnsServers);
    

    There are a couple of events you can subscribe to be notified about Network changes:

    ethernet.NetworkDown += new GTM.Module.NetworkModule.NetworkEventHandler(ethernet_NetworkDown);
    ethernet.NetworkUp += new GTM.Module.NetworkModule.NetworkEventHandler(ethernet_NetworkUp);

    The Wifi module is also very straightforward to configure: you are going to use the same code, only you need to join a network first:

    WiFi_RS21.WiFiNetworkInfo wifiInfo = wifi.Search("<SSID>");
    wifi.Join(wifiInfo, "<KEY>");

    The second step is to set the system time. Since there’s no “backup” battery that saves the clock time, one has to set it everytime the system is powered. This is done with a small NTP library called MicroNTP extracted from the Micro Framework Toolkit: http://mftoolkit.codeplex.com/

    DateTime UtcTime = NtpClient.GetNetworkTime("0.fr.pool.ntp.org");
    Microsoft.SPOT.Hardware.Utility.SetLocalTime(UtcTime + new TimeSpan(TimeSpan.TicksPerHour * 2));

    The NTP server returns the Coordinated Universal Time (UTC) therefore I add the timezone difference (+2H, hardcoded here for readability reasons, it would have to be a system parameter, we’ll see later how to create a settings system.

    Once you’re connected to a network you need to send (and eventually, receive) data from Cosm (Pachube). It’s using a simple REST API and JSON serialization… you just have to pass your API key in the headers. Here’s how to send a simple webrequest posting data to your feed:

    public void Post(IFeedItem item)
    {
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(this.AssociatedAccount.EventsUrl + this.Id.ToString());
        req.Method = "PUT";
        req.ContentType = "application/json";
        req.UserAgent = "NetduinoPlus";
        req.Headers.Add("X-PachubeApiKey", this.AssociatedAccount.ApiKey);
        req.Timeout = 1000;
        if (this.AssociatedAccount.HttpProxy != null)
            req.Proxy = this.AssociatedAccount.HttpProxy;
    
        string content = item.ToJson(this.Id);
        Debug.Print(content);
    
    
        byte[] postdata = System.Text.Encoding.UTF8.GetBytes(content);
        req.ContentLength = postdata.Length;
    
        try
        {
            using (Stream s = req.GetRequestStream())
            {
                s.Write(postdata, 0, postdata.Length);
            }
    
            using (WebResponse resp = req.GetResponse())
            {
    
                using (Stream respStream = resp.GetResponseStream())
                {
                    byte[] respBytes = new byte[respStream.Length];
    
                    int length = respStream.Read(respBytes, 0, respBytes.Length);
    
                    string respString = new string(System.Text.Encoding.UTF8.GetChars(respBytes));
                    Debug.Print(respString);
                }
            }
        }
        catch (Exception ex)
        {
            Debug.Print("exception : " + ex.Message);
        }
        finally
        {
            req.Dispose();
        }
    }
    
     
    I’m not going to go into many details about how Cosm works. Most of these networks (like OpenSenSe) have the same kind of APIs so feel free to adapt them. For your convenience I’ve wrapped my code into a very simple nuget package that you can find here:
     

     

    And the sources are on codeplex:

     

    The use of this package is really easy: first, instantiate an Account object and pass it your API key. Then you can create as many feeds as you want (I only have one here, with 3 datasets), and use the Post() method to send directly data to it:

    Account pachube = new Account("miQnUMICT-KjWhDwOxWQuycKTiuSAKxCWGgrdTNyaUNEND0g");
    Feed meteoFeed = new Feed(44741, pachube);
    
          
    meteoFeed.Post(new DoubleFeedItem("barometer", sensorData.Pressure));

    There you have it – a connected meteo station, in a few lines of code. Now, let’s make use of that screen!

    Creating the Steampunk GUI : reading and displaying images from the SD Card, and charting data.

    There are two ways to create a user interface using the .NET Micro Framework. Either using the very small subset of WPF, or, a bit like a game, create a display loop and use graphical elements and fonts, just like a game. In my case, I really want my interface to have a steampunk feeling so I’m going to use a lot of images. Since it will be sealed in a box, I have no need for touch interactions, so I’m going to go for the game-like approach. I’ll have a timer that will regularly draw all images, in the right order and at the right place, depending on the various data I have. The only “non-image” data that I’m going to display is a graph, and for that all I need is a SetPixel() method. It’s very easy.

    The first step of the creation of the user interface was to work with a designer (Michel, who’s part of my team) to create a bitmap of the finished interface. Then, Michel generated all the images necessary to compose the interfaces: all the numbers, the different meteorological symbols, the fake copper plate, etc.

    I will store the graphical assets on an SD Card, and load them at startup : here’s how to check that the SD Card is present and mounted:

    if (sdCard.IsCardInserted)
    {
        if (!sdCard.IsCardMounted)
            sdCard.MountSDCard();
    
        Debug.Print("sd card mounted");
    }

    And the files are accessed this way:

    var storage = sdCard.GetStorageDevice();
    
    for (int i = 0; i < 10; i++)
    {
        Numbers[i] = storage.LoadBitmap(i.ToString() + ".bmp", Bitmap.BitmapImageType.Bmp);
    }

    Then there is a very simple API to display an image:

    display.SimpleGraphics.DisplayImage(MetalCover, 0, 0);

    The only thing I have to do to build my user interface is to combine them in the right order to draw the bitmaps on top of one another. The problem is that, as you have correctly read, I’m using… bitmaps. .NET Micro Framework only supports JPEG, GIF and Bitmap images . Luckily for me the Bitmap class has a method that I can call to specify that a specific color should be treated as transparent… so I can lay a square bitmaps on top of one another and using a specific color (a really ugly pink color in my case) give them a square look: here’s an example of a clock number, and the corresponding transparency API:

    clip_image005[6]

    Color Transparent = ColorUtility.ColorFromRGB(255, 0, 255);
    MetalCover = storage.LoadBitmap("FondTransp.bmp", Bitmap.BitmapImageType.Bmp);
    MetalCover.MakeTransparent(Transparent);

    The trick with such a technique (which is not very elegant, but quit effective) to build an interface is to have pixel perfect assets and placements. Work with your designer and be precise!

    The last thing is to draw the graph. It’s not very complicated, either algorithmically or technically: I just store a list of measures in memory, discarding them as new ones come in, much like a queue with a fixed length. Then I go through every element, drawing them backwards from the latest one, and making sure I never get out of the rectangle in which I’m allowed to draw. Here’s the code for the whole Graph class:

    class Graph
    {
        public ArrayList Values;
    
        public double Max;
        public double Min;
    
    
        public Graph(int Capacity)
        {
            Values = new ArrayList();
            Values.Capacity = Capacity;
        }
    
        public void Add(double measure)
        {
            if (Values.Count == Values.Capacity)
            {
                Values.RemoveAt(0);
            }
    
            Values.Add(measure);
            UpdateMinMax();
        }
    
        private void UpdateMinMax()
        {
            int index = Values.Count - 1;
    
            this.Min = (double)Values[index] - 3.0;
            this.Max = (double)Values[index] + 3.0;
        }
    
        public void Draw(Display_T35 display, uint x, uint y, uint height) // width == capacity
        {
            double a,b;
            uint offset;
    
            if (Max > Min)
                a = -(height / (Max - Min));
            else
                a = 0;
    
            b = y - a * Max;
    
            for (int i = 0; i < Values.Count; i++)
            {
                int index = Values.Count - 1 - i;
    
                if (a == 0)
                    offset = y + (height / 2);
                else
                    offset = (uint)System.Math.Round(a * (double)Values[index] + b);
    
                DrawPoint(display, (uint)(x + Values.Capacity - i), offset);
            }
        }
    
        public void DrawPoint(Display_T35 display, uint x, uint y)
        {
            display.SimpleGraphics.SetPixel(Gadgeteer.Color.Black, x, y);
            display.SimpleGraphics.SetPixel(Gadgeteer.Color.Black, x + 1, y);
            display.SimpleGraphics.SetPixel(Gadgeteer.Color.Black, x, y + 1);
            display.SimpleGraphics.SetPixel(Gadgeteer.Color.Black, x + 1, y + 1);
        }
    
        public double Mean(int Count)
        {
            if (Count > 0 && Values.Count > 0)
            {
                var max = (Count > Values.Count) ? Values.Count : Count;
    
                double tmp = 0.0;
                for (int i = 0; i < max; i++)
                {
                    tmp += (double)Values[max - i - 1];
                }
                tmp /= max;
    
                return tmp;
            }
            else
                return 0;
        }
    }
     
    You may also see that I have a vertical bitmap indicating the latest value of measured temperature: Placing it on the interface requires a small trick: since it’s very high, it’s far larger than the screen, so using simple maths to know, according to the temperature, which section I need, I just cut a small part of it and display this small part: here’s how I do it:
    int pixel = (int)(System.Math.Round((double)(40 - Status.Temperature) * 16.3)) - 38;
    if (pixel < 0)
        pixel = 0;
    
    Bitmap tmpCopy = new Bitmap(TemperatureIndicator.Width, TemperatureIndicator.Height);
    tmpCopy.DrawImage(0, 0, TemperatureIndicator, 0, pixel, 34, 109);
    display.SimpleGraphics.DisplayImage(tmpCopy, 137, 120);

    There we have the user interface for a connected meteo station… if you look at connected object however, you will guess that most of them need some configuration (network, usernames…). The next part is about how to build a small webserver within the meteo station, with a small form to configure its parameters (timezone, etc).

    Building a webserver and configuration interface within the meteo station

    There’s a sample project for .NET Micro Framework that works great, but the .NET gadgeteer makes it even simpler: there’s a WebServer class already included, with basic routing functionalities. We’re going to use it. We will store the HTML files on the SD Card, as well as a configuration file.

    Starting a WebServer is as simple as one line of code:

    WebServer.StartLocalServer(ethernet.NetworkSettings.IPAddress, 80);

    To configure routing (i.e. associate code execution with specific URLs), use the WebEvent class:

    WebEvent webevt = WebServer.SetupWebEvent("Settings.htm");
    webevt.WebEventReceived += new WebEvent.ReceivedWebEventHandler(webevt_WebEventReceived);

    Once the webevent is configured, calling “http://ip:port/Settings.htm” will automatically trigger the execution of the handler associated with the string “Settings.htm”. What we need to do in the handler, is therefore to return, as an HTTP response, the content of the Settings.htm file.

    void webevt_WebEventReceived(string path, WebServer.HttpMethod method, Responder responder)
    {
        responder.Respond(LoadHtmlFile(path), "text/html");
    }

    The Responder class makes it really easy to send an HTTP response, and takes a byte array as the first argument of its Respond method. This byte array is generated from an HTML file stored in the SD Card:

    private byte[] LoadHtmlFile(string path)
    { 
        byte[] result = null;
        var storage = sdCard.GetStorageDevice();
        using (var stream = storage.OpenRead(wwwRoot + path))
        {
            using (StreamReader sr = new StreamReader(stream))
            {
                string content = sr.ReadToEnd();
                result = new System.Text.UTF8Encoding().GetBytes(content);
            }
        }
    
        return result;
    }

    Once the form is submitted with the right parameters, it’s caught with another WebEvent, and the configuration is saved to the SD Card before sending the response:

    void setparams_WebEventReceived(string path, WebServer.HttpMethod method, Responder responder)
    {
        Config c = new Config();
        c.Name = (string)responder.UrlParameters["Name"];
        c.UtcOffset = int.Parse(HttpUtility.UrlDecode((string)responder.UrlParameters["UtcOffset"]));
    
        SaveConfigToSdCard(c);
    
        responder.Respond(LoadHtmlFile(path), "text/html");
    }

    The HttpUtility class that I’m using is from the community and can be found here:

     

    The SaveConfigToSdCard method is very simple:

    private void SaveConfigToSdCard(Config c)
    {
        var storage = sdCard.GetStorageDevice();
        using (var stream = storage.OpenWrite(configFilePath))
        {
            using (StreamWriter sw = new StreamWriter(stream))
            {
                sw.Write(c.ToString());
            }
        }
    }

    The Config object stores all the parameters :

    public class Config
    {
        public string Name { get; set; }
        public int UtcOffset { get; set; }
            
        public static Config FromString(string str)
        {
            Config res = new Config();
            string[] settings = str.Split('\n');
            res.Name = settings[0].Split(':')[1];
            res.UtcOffset = int.Parse(settings[1].Split(':')[1]);
                
            return res;
        }
    
        public override string ToString()
        {
            return "name:" + Name + "\n utcoffset:" + UtcOffset.ToString();
        }
    }

    As you see, the serialization/deserialization mechanism is as simple as possible. Since we’re on an embedded system with limited capabilities, the simpler the code, the faster it runs: no need for fancy XML or JSON serialization here.

    You could use the same kind of mechanism to build an API for your object so that other devices could connect directly to it. In the present case, it’s not necessary since we publish feeds to Cosm: we can use Cosm APIs!

    As anything with a configuration, one has to think of a mechanism for resetting to factory defaults. We could do that with a simple button and a timer, it’s not really interesting to detail it here, but you’ll have to think about it!

    Cherry on the cake: Using 3D modeling tool to prototype the object

    There are two ways to build a “physical” object around an electronic kit such as the gadgeteer: either by trial and error, at the risk of using a lot more material than what’s needed, or by being modeling it either on paper or using 3D tools. The pen & paper is a simple approach so it works for simple objects, but the gadgeteer teams contributed 3D models of most parts of the kits, and even if you can’t afford professional tools such as SolidWorks (personally, I can’t) there are some free tools that work really great. While researching the subject to prepare this article I’ve used 123D, but I also gave a shot at FreeCad, SketchUp, and even had Blender installed (useful for 3D format transformation). These tools manipulate different formats, and for example SketchUp doesn’t support STEP files natively (this is the format used for the gadgeteer models). So you want to be careful about the tool you choose depending on the input format for models, and the output format you wish to have. Especially if you want to model some parts using a 3D printer!

    Getting used to a CAD tool takes some time. You’re not going to make complex parts and assemblies overnight, and you’ll spend quite a few hours learning keyboard shortcuts, navigation, and good practices to be efficient. What I found out is that it’s more efficient to follow a couple of tutorials, rather than try to prototype directly the object you need. Then work on individual parts. Then assemble them. Don’t try to do the whole thing in one project directly. Here’s an example of the work in progress for the internals of my meteo station:

    clip_image007[6]

    It’s your call to see what method you prefer. For most of my projects I’ve been experimenting directly with hardware, but in this case, since I didn’t want to damage the case, and since I wanted to have a reuseable design, I decided to go with the CAD tools.

    Conclusion

    In this article, we’ve gone through the process of prototyping every function of a connected object, from the sensors, to the network, and configuration. Hopefully you now understand:

    • How to use the .NET Gadgeteer tooling
    • How to connect sensors, and get data from them
    • How to work with different kind of files on the SD Card
    • How to build a simple user interface
    • How to post them on the network
    • How to interface with Cosm
    • How to buld a webserver in your object
    • How to build a configuration mechanism

     

    We also made use of a few toolkits (mftoolkit, HttpUtility, Pachube DAL, etc) that will hopefully help you, and concluded on the possibility to use CAD tools to physically design the object around the 3D models of the gadgeteer components. Now it’s your turn to build something!

  • Pierre's Embedded and Mobile Blog

    Windows Phone 8 annoncé!

    • 6 Comments

    A l’occasion du Windows Phone Summit à San Francisco, Terry Myerson, Joe Belfiore et Kevin Gallo se sont partagé la scène pour montrer les premiers éléments de Windows Phone 8. Certaines fonctionnalités, et certains éléments de la plateforme et du SDK ont été révélés… Vous pouvez en retrouver le contenu sur le blog de l’équipe Windows Phone et le webcast des 2 heures de keynote sur Channel 9.

    En substance, auront été abordées quelques nouveautés de l’expérience utilisateur et les fondations de la nouvelle plateforme de développement. A ce stade, ce n’est pas une vue exhaustive, il y aura d’autres bonnes surprises dans les semaines qui viennent Sourire Notamment le SDK et les nouveaux outils de développement basés sur Visual Studio 11 plus tard cet été.

    Une nouvelle version majeure de Windows Phone

    La chose la plus importante à comprendre à propos de Windows Phone 8 est qu’il s’agit d’une nouvelle version de Windows Phone, ce n’est pas une simple mise à jour:  en effet, le coeur de Windows Phone 8, c’est Windows 8! Et avec un nouvel OS, vient du nouveau matériel, et de nouvelles fonctionnalités…

    • Les processeurs multi-coeurs
    • de nouvelles résolutions d’écrans: WXGA (1280x768) et 720p (1280x720) en plus de la résolution WVGA classique (800x480)
    • Le stockage amovible (Micro SD)
    • Différents usages du NFC (partage, paiement…)
    • Internet Explorer 10 avec un support de HTML5 et des performances Javascript sans précédent, et des fonctionnalités de sécurité, comme un filtre anti-phishing par exemple.
    • Un “wallet” permettant de stocker des cartes de paiement, mais aussi des bons de réductions, des billets, etc. Tout ça relié à des cartes SIM sécurisée.
    • Nokia Maps! et notamment la fonctionnalité “offline” permettant de stocker des cartes directement sur le téléphone, et un “vrai” guidage GPS, sans avoir besoin de la connexion de données.

    Certains éléments de la nouvelle expérience utilisateurs ont également été abordés, notamment le nouvel écran d’accueil, qui étend le principe des tuiles dynamiques… avec 3 tailles différentes, toutes disponibles pour les applications!

    Ces nouvelles fonctionnalités, ces nouveaux matériels pour la nouvelle génération de Windows Phones, rendent malheureusement impossible la mise à jour des téléphones existants vers cette nouvelle version de l’OS. Cela ne veut pas dire que les terminaux existants ne bénéficieront plus d’améliorations: au contraire, une mise à jour est également prévue pour ces terminaux: il s’agit de Windows Phone 7.8, qui bénéficiera par exemple du nouveau start screen!

    Windows Phone 8 pour les développeurs

    L’autre question qui vient immédiatement en tête quand on parle de changement de plateforme, c’est la question de la compatibilité avec les applications existantes… Il y en a quand même 100.000 sur le marketplace Windows Phone! La bonne nouvelle (qui avait déjà été annoncée d’ailleurs) c’est qu’elle sont entièrement compatibles avec Windows Phone 8, il n’y aura pas de problème pour les faire tourner sur la nouvelle plateforme, sans modification. Et il sera très facile des les modifier pour bénéficier des nouvelles fonctionnalités, étant donné qu’on retrouve le modèle de développement XAML/C#! En parlant de modèle de développement, en vrac, les nouveautés:

    • Un modèle de développement en C++, natif, sera disponible!
    • On retrouvera également DirectX… si vous regardez la vidéo du lancement vous retrouverez même une démonstration du moteur Havok sur Windows Phone 8!
    • Des API de paiement “in-app”
    • La VoIP disponible pour les développeurs
    • Des améliorations du multitasking notamment la possibilité d’avoir une application en background avec le tracking GPS activé, par exemple pour les applications sportives!
    • Un contrôle WebBrowser basé sur IE10… accélération 3D du rendu des canvas, touch events… que du bonheur pour les développeurs HTML5/Javascript Clignement d'œil

    Il est encore tôt pour révéler à quel point les applications Windows 8 et Windows Phone 8 seront similaires… mais ça sera une belle histoire. Vous pourrez alors voir une nouvelle version de mes articles précédents sur les techniques de portage…

    Windows Phone 8 en entreprise

    Les besoins des entreprises sont au coeur de Windows Phone 8: tout le contenu du téléphone (OS, données…) sera crypté, et le téléphone supportera le boot UEFI sécurisé. Les Windows Phone seront manageables avec les mêmes outils avec lesquels les entreprises gèrent leur parc informatique de PC, et la plateforme applicative supporte les applications métiers, et notamment la possibilité de les déployer sans passer par l’infrastructure Marketplace. Il sera également possible pour les entreprises d’avoir leur propre “hub”, par exemple pour gérer les infos des employés et leurs applications métiers.

    Windows Phone 8 partout dans le monde

    Windows Phone 8 supportera 180 pays, 50 langages, y compris l’arabe, le turque, le farsi… autre bonne nouvelle, les mises à jour de la nouvelle plateformes pourront passer “over the air”, plus besoin de connecter le téléphone au PC. Enfin, tous les téléphones recevront les mises à jour pendant au moins 18 mois. Les premiers OEMs à s’être déjà engagé dans la course à Windows Phone 8 sont Nokia (qui étaient également nos invités sur scène) mais également Samsung, HTC, et Huawei.

  • Pierre's Embedded and Mobile Blog

    Stratégies et techniques de partage de code C# et XAML entre Windows Phone et Windows 8 Release Preview : Partie 5: Voir plus loin que la portabilité

    • 0 Comments

    Cette (longue) série d’articles est découpée en plusieurs billets sur ce blog, mais disponible également dans un seul document ici:

    http://sdrv.ms/K4BXdN

    Voir plus loin que la portabilité: penser l’expérience utilisateur sur les différents terminaux : le paradigme du “continuous client”

    Si votre utilisateur apprécie votre application il y a de fortes chances qu’il cherche à la retrouver sur les différents terminaux qu’il possède. Cet utilisateur s’attendra au minimum à trouver une expérience taillée pour chaque facteur de forme, au mieux, à pouvoir importer et partager ses paramètres, ses favoris, entre ces différents terminaux.

    Par exemple, dans l’application Klout qu’on vient de voir, il est tout à fait raisonnable d’imaginer que les favoris et le ranking soit partagés, par exemple à travers un service Cloud, entre l’application téléphone et l’application tablette.

    Si la synchronisation des données est la base de l’idée de continuous client, on peut aller plus loin, en imaginant que l’utilisateur pourra « continuer » l’activité qu’il avait sur un terminal directement sur un autre terminal de façon fluide. Par exemple, pour une application autour du cinéma, consulter des fiches de film dans le métro sur son téléphone, et pouvoir retrouver et regarder les bandes annonces des films qu’il a sélectionné dans le métro une fois chez lui, sur sa tablette. Dans toutes ces expériences le rôle du Cloud va devenir prépondérant, donc si vous n’êtes pas familiers avec les concepts d’Azure, par exemple (au dela de l’hébergement ou du stockage, tout ce qui est fédération d’identité, scénarios de synchro online/offline, etc) je vous encourage à y jeter un œil pour comprendre à quel point le cloud pourra enrichir votre application. Il y a d’ailleurs pour Windows Azure un toolkit qui simplifie le développement de backends pour WinRT, Windows Phone mais aussi disponible sur iOS et Android, et vous pouvez le trouver sur codeplex et sur github :

  • Pierre's Embedded and Mobile Blog

    Stratégies et techniques de partage de code C# et XAML entre Windows Phone et Windows 8 Release Preview : Partie 4: De la théorie à la pratique: le cas de l’application Klout Kikimeter

    • 0 Comments

    Cette (longue) série d’articles est découpée en plusieurs billets sur ce blog, mais disponible également dans un seul document ici:

    http://sdrv.ms/K4BXdN

     

    De la Théorie à la Pratique : le cas de l’Application Klout Kikimeter

     

    Klout Kikimeter est une application qui utilise les API des services Klout (http://www.klout.com) et Twitter (http://twitter.com) pour mesurer “l’influence” de l’utilisateur sur les réseaux sociaux (le "kiki" pour ceux qui ont un peu d’humour et se demandent pourquoi j’ai appelé l’application comme ça ;)).

     

    En termes de fonctionnalités, l’application propose :

    • Un composant principal qui se charge de récupérer et d’afficher le score Klout et les statistiques Twitter
    • Un système de favoris qui permet de mémoriser vos amis afin de suivre leurs scores
    • Un système de paramètres qui permet de mémoriser le nom d’utilisateur principal et d’activer ou pas la vignette dynamique
    • Un background agent permettant de mettre à jour la vignette
    • Un « générateur de vignette » qui sera utilisé par le composant principal et le background agent pour afficher le score de l’utilisateur sur la vignette de l’application dans le start screen.

     

    C’est donc une application simple mais qui illustre quand même quelques problématiques classique : modèles métiers, couche d’accès aux données sur des APIs REST/Json, nécessité d’utiliser à la fois des services du matériel et de l’OS.

     

    Etape 0 : Repenser l’expérience

     

    La première chose qui me vient en tête, c’est la différence de résolution : un écran en mode paysage plus large me permet d’avoir plus d’information en première page, c’est un luxe dont je vais profiter. Je crée donc une page qui regroupe toutes les infos utilisateurs (y compris les topics, influencers, etc) avec les favoris alignés horizontalement en haut. Cela me permettra de me servir de cette liste comme d’une forme de contrôle pivot ou tabulé pour naviguer rapidement entre les fichers de mes amis.

     

    Coté comparateur de score, je vais garder l’organisation en colonne, sauf que j’ai beaucoup plus de place. Je vais donc autoriser l’utilisateur à comparer plus de 2 personnes en ajoutant des colonnes au fur et à mesure qu’il sélectionne des utilisateurs.

     

    Pour ce qui est des paramètres, de la recherche et du partage du score sur les réseaux sociaux, je choisi de m’intégrer dans l’expérience native de Windows 8 Release Preview. Pour la vignette dynamique, je reste sur le même principe que celle de Windows Phone, avec un design Metro pour Windows 8. Et voilà, j’ai fait le tour !

     

    Etape 1: Revue d’architecture de l’application

     

    Voici le diagramme d’architecture en fonction des fonctionnalités et du découpage du code métier par rapport à la vue. Le pattern MVVM est à peu près respecté.

     

    image

     

    Première étape, refactorer les modèles objets, et la couche d’accès aux données, pour les rendre portables. Je crée donc un nouveau projet de type Portable Library qui contiendra :

    • Un dossier avec mes modèles métiers (KloutService / KloutUser)
    • Un dossier avec mes ViewModels : je les découpe suffisament pour pouvoir les composer dans différentes vues.
    • Un dossier « SystemFeatures » qui contiendra des interfaces génériques vers des services qui habituellement sont dépendants de la plateforme : on y retrouvera la gestion des paramètres de l’application, la gestion des favoris (qui dépend de l’isolated storage), une interface vers le dispatcher, et vers le background agent.

     

    Du coup, Model et ViewModels peuvent être partagés entre les projets sans problèmes ! Voici le résultat auquel j’arrive :

     

    klout kikimeter object model w8 image

     

    Théoriquement la couche d’accès aux données est partageable aussi… Si je regarde les dépendances, elle dépend de mon modèle métier (pas de soucis, on vient de voir que c’est un projet de type Portable Library) mais également d’un framework tiers : Json.NET. Heureusement l’auteur publiait, au moment de la rédaction de cet article, une version "Portable Library". Du coup, je peux aussi passer ma couche d’accès aux données dans un projet de type « Portable Library ». C’est idéal, facile à gérer dans le source control, facile à tester indépendamment de la plateforme… bref, quand on peut utiliser la portable library, on gagne sur tous les terrains.

     

    Tout le code vraiment purement spécifique à chaque plateforme (que ce soit l’accès au materiel ou au système d’exploitation) est isolé dans un projet à part que je décide de nommer « PlatformImplementation ». Le rôle de ce projet ? Implémenter les interfaces que j’ai défini dans la partie « SystemFeatures » de mon projet de type Portable Library:

    klout kikimeter platform implementation w8 image

     

    Ici, on peut séparer la gestion de source et réécrire entièrement le code, ceci étant dit, on s’apercevra souvent qu’on peut optimiser un peu : par exemple pour la gestion des favoris : si les APIs de l’isolated storage sont différentes d’une plateforme à l’autre, la sérialisation XML reste la même ! Du coup dans ce cas, je choisi d’utiliser le même fichier dans les 2 projets, et d’utiliser la compilation conditionnelle. Economie de bout de chandelle ? Peut-être, je mutualise à peine une vingtaine de ligne de code. Mais du coup, je suis sûr de ne pas faire d’oubli quand je devrai les faires évoluer. Pas de petits profits, donc ;). On parlera plus spécifiquement de ce projet dans la troisième partie de cet article, pour en voir les détails d’implémentation.

     

    Pour les vues, il n’y a malheureusement pas de magie possible. Je les recrée à la main et j’adapte les styles et les templates en premier, ce qui m’aide à construire rapidement quelque chose ayant l’identité visuelle de mon application Windows Phone. Mais pour l’architecture des composants sur la page en revanche, je pars de zéro. Ayant été relativement propre sur le pattern MVVM de ce côté-là, je n’ai quasiment pas de code-behind (quelques chargements associés à des évènements de page) que je peux copier/coller facilement. Je réutilise également les mêmes ViewModels et donc les mêmes Bindings et les mêmes IValueConverters (pour lesquels il faut juste ajuster le prototype). Pour certaines vues notamment pour démarrer sur le comparateur, j’ai quand même pu copier/coller du XAML de Windows Phone vers WinRT sans problème.

     

    klout kikimeter projects and views w8 image

     

    En ce qui concerne le Background Agent, il ne fonctionne pas du tout de la même manière dans Windows 8 Release Preview et dans Windows Phone. J’ai donc fait 2 projets séparés, avec du code séparé aussi. Cela ne me dérange pas plus que ça car le rôle d’un Background Agent c’est juste d’aller chercher le score (un appel simple à la couche d’accès aux données) et de mettre à jour la tuile (avec le générateur qui est aussi un projet séparé)… je n’ai donc que très peu de code dedans, l’impact en terme de fragmentation par plateforme est mineur. Je vais quand même générer une interface générique qui permet de l’activer et de le désactiver, histoire de pouvoir appeler des APIs unifiées depuis n’importe quelle application de la même manière : c’est utile si vous l’appelez notamment depuis un projet de type Portable Library.

     

    Comme vous pouvez le voir je n’utilise que certaines des techniques décrites précédemment pour cette application, et je me permets quelques entorses aux patterns. Chacun devra faire son choix de façon pragmatique et en fonction de ses préférences de code et de gestion de sources ! Voila le résultat final:

     

    klout kikimeter projects folded w8 image

     

    A cette étape, on a donc notre ancien code, découpé dans des nouveaux projets, et plus rien ne compile ! C’est normal, ça aurait été trop facile sinon. Il reste à « réparer » ce qui ne marche pas et notamment toutes les couches spécifiques à chaque plateforme. C’est l’objectif de l’étape 3.

     

    Etape 3 : Fixer ce qui ne marche pas dans le code existant pour coller à la nouvelle architecture

    On pourrait en dire énormément sur les équivalences entre les APIs plateformes, certains le font déjà dans des articles que j’ai mentionnés plus haut. Dans cette partie je préfère rester générique, car les APIs de WinRT ne sont pas forcément définitives : il ne s’agit que d’une Release Preview de Windows 8 ! je vais plutôt m’expliquer sur les méthodes et les questions à se poser.

     

    Dans la couche d’accès aux données : porter le code Windows Phone vers la portable library

    Mon seul problème dans cette étape, c’est l’absence d’une classe souvent utilisée dans Windows Phone mais non présente dans les projets de type Portable Library: la classe WebClient. Pour cela l’approche « wrapper » est très simple à mettre en place :il me suffit d’improviser une classe WebClient contenant uniquement le code qui m’est nécessaire et qui repose sur le couple HttpWebRequest / WebResponse. C’est une feinte pour éviter d’avoir à réécrire du code, ici, l’approche me fait largement gagner du temps (allez… au moins 1 heure ;) mais c’est une petite application, l’impact est plus important sur les couches d’accès aux données plus complexes).

    En voici la substance :

    namespace KloutKikimeter.ObjectModel.PortabilityHelpers
    {
        public class WebClient
        {
            public event DownloadStringCompletedEventHandler DownloadStringCompleted;
    
            public void DownloadStringAsync(Uri uri)
            {
                HttpWebRequest request = WebRequest.CreateHttp(uri);
                request.BeginGetResponse(state => 
                {
                    DownloadStringCompletedEventArgs dscea = new DownloadStringCompletedEventArgs();
                    try
                    {
                        var req = state.AsyncState as HttpWebRequest;
                        WebResponse response = req.EndGetResponse(state);
                        using (StreamReader sr = new StreamReader(response.GetResponseStream()))
                        {
                            dscea.Result = sr.ReadToEnd();
                        }
                    }
                    catch (Exception ex)
                    {
                        dscea.Error = ex;
                    }
                    finally
                    {
                        if (DownloadStringCompleted != null)
                        {
                            DownloadStringCompleted(this, dscea);
                        }
                    }
                }, request);
            }
        }
    
        public delegate void DownloadStringCompletedEventHandler(object sender, DownloadStringCompletedEventArgs e);
        public class DownloadStringCompletedEventArgs : EventArgs 
        {
            public Exception Error;
            public string Result;
        }
    
    }
    

    Les favoris (un fichier dans l’isolated storage)

    Ici on cherche à masquer les APIs spécifiques sous les interfaces génériques définies dans le projet de type Portable Library. Par exemple, la portable library ne dispose pas des mots clefs async/await… hors il faut utiliser ce pattern asynchrone pour accéder à l’Isolated Storage sous Windows 8 Release Preview… ce que je fais en remontant un pattern à base d’events pour garder le coté asynchrone.

     

    namespace KloutKikimeter.ObjectModel.SystemFeatures
    {
        public interface IFavorites
        {
            event FavoritesLoadedEventHandler FavoritesLoaded;
            void LoadAsync();
    
            event EventHandler FavoritesSaved;
            void SaveAsync(IEnumerable<KloutUser> favs);
    
        }
    
        public delegate void FavoritesLoadedEventHandler(object sender, FavoritesLoadedEventArgs e);
        public class FavoritesLoadedEventArgs : EventArgs
        {
            public IEnumerable<KloutUser> Results;
        }
    }
    

    Les paramètres (settings)

     

    Pour ce qui est de la gestion des paramètres, WinRT propose un accès unifié aux paramètres depuis les “charms”, c’est à dire la petite barre vertical qui apparait à droite de l’écran quand on glisse de le doigt depuis le bord droite de l’écran, vers le centre dans Windows 8 Release Preview. WinRT propose deux « bibliothèques » pour stocker les paramètres: une bibliothèque locale (les LocalSettings) et une bibliothèque synchronisée avec le cloud (les RoamingSettings). Ces APIs prennent la forme d’un stockage clef/valeur, plus simple à utiliser que l’Isolated Storage, je réécris donc totalement le code pour tirer parti de cette fonctionnalité… Et apprendre qu’il en existe un équivalent sur Windows Phone, chose que j’ignorais, que j’implémenterai plus tard… qui améliorera la portabilité de mon code. Une méconnaissance de l’API Windows Phone aura donc un peu augmenté ma dette technique et un portage sur Windows 8 Release Preview m’aidera à la faire diminuer ! Au final, j’ai donc une interface avec 2 champs (le nom d’utilisateur et l’utilisation ou pas de la vignette dynamique) et 2 méthodes (Load et Save) qui masquent des systèmes totalement différents !

     

    namespace KloutKikimeter.ObjectModel.SystemFeatures
    {
        public interface ISettings
        {
            string TwitterUserName { get; set; }
            bool IsLiveTileAgentActive { get; set; }
    
            void Load();
            void Save();
        }
    }
    

    Le Dispatcher

     

    Autre point assez intéressant, le dispatcher. En effet, comme beaucoup je fais appel au Dispatcher au moment d’appeler l’évènement PropertyChanged du ViewModel. Hors.. ce dispatcher n’existe tout simplement pas dans un projet de type Portable Library, dans lequel j’ai pourtant mes ViewModels ! du coup, je crée une interface IDispatcher avec une méthode Invoke qui prend une Action en paramètre… et j’appelle cette interface dans mes ViewModels. Dans l’implémentation spécifique, je wrappe l’appel soit au Dispatcher Windows 8, soit au Dispatcher Windows Phone.

    Voici ci-dessous l’interface, la classe qui l’implémente, et son utilisation :

    namespace KloutKikimeter.ObjectModel.SystemFeatures
    {
        public interface IDispatcher
        {
            void Invoke(Action a);
        }
    }
    
    namespace PlatformImplementation
    {
        public class Dispatcher : IDispatcher
        {
    #if !WINDOWS_PHONE
            private CoreDispatcher cd;
    
            public Dispatcher(CoreDispatcher currentDispatcher)
            {
                cd = currentDispatcher;
            }
    #endif
    
            public void Invoke(Action a)
            {
                
    #if WINDOWS_PHONE
                    System.Windows.Deployment.Current.Dispatcher.BeginInvoke(a);
    #else
                await cd.RunAsync(
                    Windows.UI.Core.CoreDispatcherPriority.Normal, 
                    new DispatchedHandler(a));
    #endif
            }
        }
    }
    
    namespace Klout_Kikimeter.ViewModels
    {
        public class ViewModelBase : INotifyPropertyChanged
        {
            protected IDispatcher Dispatcher;
            public ISettings Settings;
    
            public ViewModelBase(ISettings settings, IDispatcher dispatcher)
            {
                this.Settings = settings;
                this.Dispatcher = dispatcher;
            }
            
            #region INotifyPropertyChanged implementation
            public event PropertyChangedEventHandler PropertyChanged;
            public void NotifyPropertyChanged(string PropertyName)
            {
                if (PropertyChanged != null)
                    Dispatcher.Invoke(() => PropertyChanged(this, new PropertyChangedEventArgs(PropertyName)));
            }
    
            #endregion
        }
    }
    

    Le Générateur de Vignettes Dynamiques

     

    Windows 8 Release Preview et Windows Phone proposent une fonctionnalité de “Vignette Dynamique”, mais d’un système à l’autre elles ne sont pas implémentées de la même manière, notamment la logique de « template » qui existe dans Windows 8 Release Preview n’existe pas dans Windows Phone. Encore une fois, il suffit d’implémenter une interface générique (une simple méthode GenerateTile) et d’avoir le spécifique dans un fichier dans le projet PlatformImplementation.

     

    Le Background Agent

     

    Comme dit précédemment, les Background Agents ne fonctionnent pas du tout de la même manière dans Windows 8 Release Preview et dans Windows Phone. J’ai donc deux projets de deux types différents qui ne partagent pas de code, mais qui implémentent la même interface définie dans mon projet portable library.. interface ultra simple contenant 2 méthodes : ActivateBackgroundAgent() et DeactivateBackgroundAgent().

     

    Conclusion

     

    La tâche de portage, ou de migration, de l’application Klout Kikimeter aura pris environ 3 jours, sans rien connaitre au développement d’applications Metro/WinRT. Avec le recul, si j’avais eu un niveau de connaissance suffisant en WinRT j’aurai probablement mis moins d’une journée, la tâche la plus longue étant de redéfinir les vues, ainsi que le support des résolutions multiples, ce qui d’une certaine manière peut être vu comme de l’ajout de fonctionnalité, puisque Windows Phone ne supporte qu’une résolution.

     

    Voici une évaluation “de tête” de ce que j’estime partager entre les plateformes. Bien-sûr, ces mesures variant grandement d’une application à une autre dépendant à la fois de votre manière de coder et des fonctionnalités que vous utilisez. Ceci étant dit, passer à Windows 8 Release Preview m’a donné plein d’idées pour améliorer l’application, il va donc devenir de plus en plus difficile de fournir ce genre de mesure étant donné qu’à partir de ce tronc commun, chaque version va commencer à bénéficier de spécificités propres à la plateforme

    Composant

    Code partagé

    Views

    5% (styles)

    ViewModels

    90% (exceptions are because of kludges like calling the Dispatcher)

    Models and Data Access

    100%

    Background Agent

    0% (different project)

    Platform Abstraction (Settings, Favorites, Live Tile)

    20%

    Overall

    80%

    Comme vous pourrez le constater, il n’y a donc ni moulinette automatique de code, ni règle, ni méthodes infaillible, pour réaliser cette tâche, il faut comprendre ce qu’on fait, et coller pragmatiquement aux bonnes pratiques.

     

    >> Vers la partie 5: Conclusion: Voir plus loin que la portabilité, penser à l’expérience utilisateur sur les différents terminaux. Le “continuous client”.

  • Pierre's Embedded and Mobile Blog

    Stratégies et techniques de partage de code C# et XAML entre Windows Phone et Windows 8 Release Preview : Partie 3: Techniques d’adaptation et de partage de code

    • 0 Comments

    Cette (longue) série d’articles est découpée en plusieurs billets sur ce blog, mais disponible également dans un seul document ici:

    http://sdrv.ms/K4BXdN

    Techniques de portage et de partage de code

    Entre le simple usage des mots clefs du langage, et jusqu’à des librairies spécifiques, il y a différentes manières d’architecturer le code et de minimiser la partie spécifique à chaque plateforme. Nous allons commencer avec quelques rappels sur les bases de la programmation orientée objets, puis nous avancerons dans des concepts et des outils plus complexes.

     

    Interfaces, Classes Abstraites, Classes Partielles et Méthodes d’Extension

    Les Interfaces sont l’outil le plus classique, dans le monde orienté objet, pour ajouter une couche d’abstraction, en spécifiant un “contrat” de classe sans en définir l’implémentation, qui permettrait d’avoir plusieurs classes, par exemple dans des projets différents avec les mêmes champs, propriétés et méthodes. Pour en savoir plus:

    L’avantage des interfaces, c’est qu’on peut en implémenter plusieurs dans une classe.

    Les classes abstraites peuvent être utilisées quand il faut spécifier une implementation de base qui peut être « écrasée » par des classes qui en héritent (les classes dérivées). Par rapport à une interface, on perd le multi-héritage, mais on peut y gagner une implémetnation par défaut ! Pour en savoir plus :

    Les classes partielles permettent de définir une seule classe, dans plusieurs fichiers différents. Elles sont au cœur du framework .NET et particulièrement du couple XAML/C#! Cela permet de découper la défintion d’une classe dans des fichiers séparés qui pourraient, par exemple, avoir une partie dans un projet générique, avec une autre partie dans un projet spécifique à une plateforme (à condition d’être dans le même espace de nommage). Pour en savoir plus sur les classes partielles :

    Les méthodes d’extension peuvent aussi être utilisées pour découper le code de méthodes dans différents fichiers : par exemple en étendant une classe générique avec des méthodes spécifiques à chaque plateforme. LINQ est un bon exemple d’utilisation des méthodes d’extension puisque l’ajout d’un espace de nommage et d’une référence LINQ permet d’ajouter des méthodes comme Where() et Select() aux types énumérables. Pour en savoir plus sur les méthodes d’extension:

     

    La Portable Library

     

    La portable library permet, en function des frameworks que vous ciblez, de créer des projets “portables” utilisant le sous-ensemble de classes et de méthodes commun à toutes les cibles. La portable library est inclue par défaut dans Visual Studio 11 (sauf pour la version Express) et est disponible en tant qu’extension pour Visual Studio 2010. Les frameworks cibles supportés incluent le framework .NET, WinRT, Silverlight, Silverlight pour Windows Phone, et la Xbox 360.

     

    image

     

    La portable library, de par sa nature, n’inclue pas d’APIs spécifiques à une plateforme ou un OS, mais contient tous les types de base, les fonctionnalités coeur de .NET, l’accès à Internet et au web, le parsing XML… bref, ce qu’il faut pour créer des modèles objets, et éventuellement des couches d’accès aux données. Malheureusement, très peu de frameworks d’accès aux données tiers ciblent la portable library.

     

    Une chose à garder en tête quand on conçoit l’architecture d’une application : un projet ciblant la portable library ne peut pas référencer de projets qui ciblent des plateformes spécifiques. Cela peut paraitre évident, pour rester indépendant justement, mais il en découle des implications importantes, notamment le fait que la portable library ne peut pas servir de couche intermédiaire entre deux composants spécifiques à une plateforme, ou bien de couche d’abstraction à des services du système d’exploitation par exemple. Pour en savoir plus à propos de la portable library :

     

    Voici également une belle série d’articles par Stéphanie Hertrich qui détaille l’utilisation de cette portable library WinRT, Windows Phone et Silverlight 5 :

     

    Ecrire son propre wrapper.

     

    La plupart du temps on écrit du code sans penser à la portabilité… en utilisant des classes de haut niveau qui n’existent que sur une plateforme plutôt qu’une classe équivalente qui serait portable. C’est le cas, par exemple, de la classe WebClient, spécifique à Windows Phone, alors qu’il existe la classe HttpWebRequest qui est portable et qui fait la même chose (voire plus, en fait). Dans ces cas-là, 2 solutions : soit réécrire le code, soit ré-implémenter la classe manquante au-dessus de celles qui existent dans le nouveau framework… une sorte de wrapper. L’avantage est que cela permet de ne pas toucher du tout au code existant.

     

    ATTENTION : n’utilisez pas de désassembleurs comme Reflector ou DotPeek, pour « récupérer » une classe dans un framework et la porter dans un autre. C’est une mauvaise pratique !

     

    La compilation conditionnelle, les liens et les directives de préprocesseur

     

    La “compilation conditionnelle” peut être utilisée quand on veut mélanger, dans le même fichier, du code spécifique à une plateforme, et du code générique. Ensuite il suffit d’ajouter ce fichier à tous les projets, en utilisant le bouton « ajouter un lien » dans la fenêtre d’ajout de nouveaux éléments.

     

    image

     

    Chacun se fera son idée de la “propreté” de cette méthode, en ce qui me concerne j’apprécie la clarté du découpage entre le code spécifique et le code générique, cela permet de voir facilement comment maximiser la réutilisation de l’une ou de l’autre.

    image

    [Attention] Les gestionnaires de sources ne prennent pas en compte les liens entre les fichiers (seuls les “vrais” fichiers sont commité. Il faut donc que les développeurs aient accès aux projets de toutes les plateformes s’ils lient dans leur projets des fichiers d’autres projets.

     

    L’utilisation de la CTP Async pour Visual Studio

    Toutes les opérations pouvant prendre plus de 50ms dans WinRT sont asynchrones dans Windows 8 Release Preview, et font usage des mots clefs async et await. Ce n’est pas le cas dans Windows Phone, mais il est possible de rajouter cette fonctionnalité et ces mots clefs dans le runtime Windows Phone à l’aide de l’Async CTP. Même s’il s’agit d’une CTP, donc non supportée, elle est pour autant suffisamment stable pour être utilisée dans une application. Cela permet de réutiliser les mêmes API et les mêmes patterns de code sur les deux plateformes, et ça peut être particulièrement utile sur tout ce qui concerne l’abstraction du hardware ou du réseau (celles-ci étant quasi systématiquement asynchrones). Vous pouvez trouver plus d’informations sur la CTP Async avec le lien suivant :

     

    Attention, la CTP Async n’est pas installable sur une machine avec le framework .NET 4.5, Visual Studio 11 ou Windows 8 Release Preview !

     

    L’utilisation de frameworks multi-plateformes

    La plupart des développeurs font appel à des frameworks tiers pour simplifier le développement d’applications et compléter les APIs du Framework .NET : par exemple, pour parser du JSON, pour s’interfacer aux APIs des réseaux sociaux, ou pour implémenter simplement des patterns. Dans le cas où vous utilisez des frameworks tiers, assurez-vous que leurs dépendances restent dans les APIs tolérées par WinRT et les applications de type Metro (qui n’ont pas accès à l’intégralité du framework .NET 4.5).

     

    XAML: Utiliser les Styles et les DataTemplates

    En ce qui concerne la description des interfaces, en XAML, il faut essayer de distinguer au maximum le découpage de la page (la façon d'empiler et de situer les éléments) des éléments purement graphiques : choix des couleurs, des polices de caractères, etc. Plus cette separation sera claire, plus il sera simple de réimporter la charte graphique sur une autre plateforme tout en réarrangeant, indépendament les éléments sur la page pour utiliser l’intégralité de l’écran par exemple, ce qu’il faut absolument faire quand on change de facteur de forme et donc d’ergonomie.

     

    Une dernière chose sur l’injection de dépendances, MEF et Unity

    Certains outils d’injection de dépendances comme MEF et Unity auraient pu permettre de découpler certaines parties du code, en faisant encore une fois usage d’interfaces et de bouts de code plateforme spécifiquement séparés et chargés dynamiquement au démarrage. Malheureusement, le Managed Extensibility Framework (MEF) n’est pas supporté dans Windows Phone. Il est donc d’une utilité très limitée dans le cas qui nous occupe…

    >> Vers la partie 4: De la théorie à la pratique: le cas de l’application Klout Kikimeter

  • Pierre's Embedded and Mobile Blog

    Stratégies et techniques de partage de code C# et XAML entre Windows Phone et Windows 8 Release Preview : Partie 2: Le processus de migration/portage du code

    • 0 Comments

    Cette (longue) série d’articles est découpée en plusieurs billets sur ce blog, mais disponible également dans un seul document ici:

    http://sdrv.ms/K4BXdN

    Le Processus de Portage.

    Avant toute chose: Travaillez votre expérience utilisateur.

    Comme dit dans la partie précédente : avant de plonger dans le code, travaillez votre expérience utilisateur : que ce soit simplement avec un papier et un crayon, ou bien avec Sketchflow, ou PowerPoint, ou n’importe quel autre outil de mockup. Ce travail vous fournira une ligne directrice pendant tout le reste du travail de portage.

     

    Étape 1 : Savoir regarder son code, froidement

    [Dette technique] http://en.wikipedia.org/wiki/Technical_debt

    L’idée de dette technique est la suivante : le plus vous « cassez » votre code en y appliquant des corrections rapides et pas forcément très propres, le plus vous aurez de problèmes à résoudre pour faire évoluer votre code. L’ensemble de ces problèmes représente votre dette technique.

    La première étape quand vous portez votre application sur une nouvelle plateforme, c’est de revoir votre code. Cette revue de code est souvent prise un peu trop à la légère au profit de résultats rapide, et aussi parce qu’en tant que développeur on a tendance à croire qu’on connait son code par cœur. En fait, durant tout le développement et particulièrement durant le débuggage et la phase de tests pré-certification, nous cassons tous les patterns pour résoudre des « petits bugs », tout en accroissant notre dette technique. Tous ces petits fix ne sont pas forcément très lisibles, ni frais dans notre mémoire. Enfin, même si vous avez déjà revu votre code dans le passé, le revoir une nouvelle fois avec l’idée du portage en tête vous en donnera surement une lecture différente.

     

    Le but de cette revue de code est donc de rafraichir votre mémoire sur les différents composants de votre application, les couches de votre architecture, et à quel point ils sont dépendants les uns des autres. A la fin de cette revue de code, vous aurez probablement en tête un plan de refactoring du code pour préparer le portage... Une étape que vous auriez surement négligée si vous n’aviez pas fait cette revue !

     

    A ce point du processus, il est facile de céder à la tentation de copier vos fichiers sources dans un nouveau projet d’application Metro, et de commenter tout ce qui ne compile pas, pour avoir un début de prototype en 10 minutes. C’est une approche pragmatique mais qui risque d’être pénalisante pour votre utilisateur, car elle vous pousse à conserver une expérience existante parfois inadaptée, et vous risquez d’augmenter votre dette technique alors que le but de la revue de code précédente était justement de la diminuer !

    Que faut-il chercher pendant cette revue de code “spéciale portabilité”?

    Pour chaque projet de votre solution, vous devez lister les références que vous utilisez et à quel point elles sont portables. Si vous utilisez des frameworks tiers, il faut savoir s’il en existe des versions portables (soit à travers la portable library, ou ciblant spécifiquement chaque plateforme). Le résultat de cette investigation sera surement que cela existe, étant donné que c’est le but même de l’existence de ces frameworks… Mais parfois vous constaterez que les fonctionnalités ne sont pas les mêmes d’une version à une autre, ou bien qu’elles ne sont tout simplement pas au même niveau de maturité ou de stabilité. A vous de voir dans ce cas, si vous souhaitez vous attaquer plutôt au portage de l’existent ou tenter de remplacer par un framework concurrent. En tout état de cause, c’est plus facile si le code source existe, et dans ce cas-là, pourquoi ne pas contribuer à la communauté ?

     

    En ce qui me concerne, j’utilise surtout Json.Net et parfois MVVM Light, qui sont tous deux très portables.

     

    Pour chacun des fichiers sources, essayez de nettoyer vos “using” par exemple en utilisant la fonctionnalité de Visual Studio qui permet de les réorganiser. Avoir la liste la plus courte possible de « using » permet de comprendre plus facilement les dépendances de vos fichiers et de vos références.

     

    image

     

    Pour chaque appel à une fonctionnalité ou une API spécifique de la plateforme, voyez si l’équivalent existe sur l’autre plateforme. Il y a quelques billets dans la communauté qui relatent l’expérience des développeurs sur le sujet :

     

     

    Le dernier lien pointe vers une série de billets de mon collègue Jared Bienz qui promet d’être particulièrement bien détaillée.

     

    Si vous disposez d’une version de Visual Studio qui embarque les outils d’architecture (Premium ou Ultimate), c’est peut-être aussi l’occasion de s’en servir : ils sont capables de générer des graphes qui permettent de voir tout de suite à quel points vous avez cassé les patterns que vous avez utilisé, et les dépendances entre vos composants.

     

    image

     

    Voici un exemple de ce que j’obtiens avec une application cross-platform en cours d’écriture :

     

    image

     

    On voit à la fois dans l’application elle-même (FoursquareTracker) le pattern MVVM et la séparation des namespaces (qui correspond à peu près aux assemblies) et les dépendances à des namespaces externes.

     

    Cette étape vous permettra d’avoir une idée à des dépendances de vos fichiers entre eux, et vous mènera naturellement à l’étape 2, qui consiste à ré-architecturer le code en modules portables individuellement. Une fois que ces modules seront découpés, il ne restera plus qu’à choisir la bonne stratégie de portage pour chacun.

     

    Etape 2 : Séparer les composants (ou modules) du code et choisir la bonne technique de portage pour chacun

    Pour le reste de l’article nous allons considérer qu’un composant (ou module) est un bout de code faiblement lié au reste de l’application. Si vous n’avez pas encore réussi à isoler vos composants (ce que j’appelle du code « spaghetti »), il faut revenir à l’étape de revue de code et de refactoring. En tout état de cause, démarrer un portage sur du code spaghetti c’est s’assurer à terme de perdre du temps et de passer un assez mauvais moment à fabriquer quelque chose de bancal. C’est donc le dernier moment pour faire votre nettoyage de printemps, et ça commence avec le choix de bons design patterns…

     

    Un design pattern est une solution prouvée à un problème récurrent. C’est le résultat de travail de développeurs qui ont essuyés les plâtres avant vous. La plupart des designs patterns ont un objectif principal qui est la « séparation des problèmes » (separation of concerns). En d’autres mots, faire en sorte que le code soit découpé en unités fonctionnelles faiblement couplées pouvant évoluer indépendamment les unes des autres. Utiliser un design pattern permet souvent d’améliorer la testabilité du code, sa lisibilité, et même, sa portabilité ! Il faut toutefois faire attention à ne pas surutiliser les patterns, un défaut classique de développeur chevronné qui oublie que si un jour ce code est repris par quelqu’un de moins sénior, il sera surement moins lisible car il sera plus difficile de comprendre le rôle de chacun des composants… amenant donc l’effet inverse que celui escompté : des problèmes de maintenabilité, de performances, et d’évolutivité (difficile pour un développeur novice de faire évoluer correctement un code qu’il ne comprend pas !)…

     

    Voici quelques patterns que vous devriez avoir en tête en pensant « portabilité »

    • Le pattern MVVM, ou n’importe quel autre pattern de séparation entre les vues et le code métier de l’application, pour tout ce qui est interface graphique.
    • Les patterns Adapter, Bridge et Factory pour tout ce qui est séparation du code spécifique la plateforme et au matériel:
      • Les services du système d’exploitation
      • L’accès aux capteurs et au matériel d’une manière générale.

     

    En plus des design patterns, essayez de nettoyer votre code au maximum en le factorisant (ce que nous avons tendance à faire naturellement en C# mais pas forcément en XAML : hors les DataTemplates et les Styles sont là pour ça, et s’appliquer à soigner son XAML facilitera le portage des vues, qui est sans doute la plus grosse partie du travail à réaliser, comme on le verra par la suite).

     

    Il y a différents moyens de séparer les composants dans votre code. La manière que je qualifie « d’horizontale » consiste à séparer le code sous forme de couches métiers, par exemple entre les modèles objets et les objets contenant les données à afficher. Ces composants s’étagent en général de bas en haut dans un diagramme d’architecture. La manière « verticale » de séparer les composants consiste à essayer d’isoler plutôt les fonctionnalités de l’application : par exemple, la fonctionnalité « gestion des favoris » ou la fonctionnalité « comparaison des scores ».

     

    Une fois que vous avez séparé vos composants horizontalement et verticalement vous obtenez une sorte de matrice de composants. Cette matrice de composant va vous permettre d’examiner chacun des composants individuellement pour choisir la meilleure technique de portage.

    Etape 3 : Passer à l’action : découper son code sous forme de solutions/projets/namespaces pour maximiser la portabilité, et réparer.

    Dans cette étape, pas besoin de gants : on casse avant de reconstruire. Il faut prendre les morceaux de codes (qu’ils soient dans des fichiers séparés ou pas, et peu importe l’architecture actuelle du projet) et les réordonner, en fonction des stratégies de portage que vous adopterez pour chacun des composants… pas la peine, donc d’en écrire plus pour le moment. Voyons ces techniques !

     

    >> Vers la partie 3: Techniques d’adaptation et de partage de code

  • Pierre's Embedded and Mobile Blog

    Stratégies et techniques de partage de code C# et XAML entre Windows Phone et Windows 8 Release Preview : Partie 1 : Introduction – les différences entre les plateformes à avoir en tête

    • 0 Comments

    Cette (longue) série d’articles est découpée en plusieurs billets sur ce blog, mais disponible également dans un seul document ici:

    http://sdrv.ms/K4BXdN

     

    Les différences entre les plateformes Windows Phone et Windows 8 Release Preview à avoir en tête au moment du portage.

    En tant que développeur vous avez probablement une vue orientée “fonctionnalités” de votre application. C’est une vue cohérente qu’il est important d’avoir mais pour que l’opération de portage soit vraiment bénéfique à l’utilisateur, il faut se mettre à sa place, et penser que l’usage de votre application sera probablement différent d’une plateforme à une autre.

    Un aspect particulièrement important est le facteur de forme : il s’agit de profiter des 10 pouces en mode paysage que propose un écran de tablette par rapport aux 4 pouces en mode portrait d’un écran de téléphone par exemple ! Une ergonomie pertinente sur un type d’écran ne le sera pas forcément sur un autre, particulièrement si on considère la manière d’interagir avec ce terminal : avec un ou plusieurs doigts, ou avec une souris dans le cadre d’un PC.

    Toujours sur le même sujet, il faut savoir que les applications « Metro » tournant sur la Windows 8 Release Preview peuvent fonctionner en plein écran, en mode « snapped » ou en mode « filled » c’est-à-dire en partageant l’écran avec une autre application. Pour chacun de ces modes les proportions de l’écran sont différentes, et l’usage que l’utilisateur en fera aussi (puisqu’il fera 2 choses à la foi) !

    Un autre exemple de point important à garder en tête est la présence (ou l’absence) de certains capteurs comme le GPS, ou bien les capteurs d’accélération ou de position.

    Coté logiciel, il y a aussi des différences significatives, pas forcément dans les fonctionnalités, mais plutôt dans la manière de les utiliser. Par exemple les paramètres, la recherche ou le partage unifiés entre les applications dans Windows 8 Release Preview ne fonctionnent pas de la même manière que Windows Phone.

    En conséquence de quoi, avant d’aborder la partie technique du portage de votre application, je vous encourage à repenser l’usage en fonction du facteur de forme… Il y a de nombreux articles détaillant l’expérience utilisateurs de Windows 8 Release Preview ou de Windows Phone qui pourront vous guider dans votre réflexion:

    · Pour Windows Phone : User Experience Design Guidelines for Windows Phone

    · Pour Windows 8 Release Preview : Windows Dev Center: Designing UX for Apps

    >> Vers la partie 2: Le processus de migration/portage du code

  • Pierre's Embedded and Mobile Blog

    [Windows Phone 7.5] Protéger les données sensibles dans l’Isolated Storage

    • 0 Comments

    Il arrive que l'’on doive échanger des données sensibles, par exemple à travers du réseau, ou entre des couches applicatives. Pour cela on a accès à toute une couche de sécurité qui est très simple à utiliser et qui inclue les algos les plus classiques, qu’il s’agisse de crypto (AES, RSA etc) ou du hashage (HMAC, SHA1, SHA256…). Cette couche permet de crypter un contenu à partir d’une clef secrète ou d’un couple clef publique / clef privée.

    Mais parfois on veut stocker ces données, et autant on peut utiliser ces algos pour stocker les crypter, on ne peut pas les utiliser pour stocker la clef de cryptage elle-même! Dans ce cas, on a la Data Protection API (DPAPI) qui utilise une clef secrète contenue dans le téléphone, impossible à récupérer et qui permettra de crypter n’importe quel type de contenu. Cette DPAPI est accessible depuis la classe statique System.Security.Cryptography.ProtectedData. Celle ci contient 2 méthodes, Protect et UnProtect, qui agissent tout simplement sur des tableaux de bytes:

    Un exemple de cryptage:

    byte[] dataBytes = System.Text.Encoding.UTF8.GetBytes(data);
    byte[] encryptedData = ProtectedData.Protect(dataBytes, null);

    Et un décryptage, aussi simple!

    byte[] decryptedData = ProtectedData.Unprotect(encryptedData, null);
    result = new string(System.Text.Encoding.UTF8.GetChars(decryptedData));

     

    En tout état de cause, si vous n’avez qu’à stocker des données cryptées et pas forcément à les partager, vous pouvez ne vous servir que de cette classe. Ca simplifie grandement l’écriture de certaines applications comme par exemple les coffres de mots de passe… mais n’oubliez pas de gérer, lors de vos cryptages/décryptages, les tombstoning correctement…  et n’écrivez jamais nulle-part un secret en clair!

  • Pierre's Embedded and Mobile Blog

    Livemeeting “monétisation des applications mobiles” : le contenu est disponible!

    • 0 Comments

    Vendredi 9 Mars se tenait le deuxième livemeeting de l’accélérateur, dont le sujet était la monétisation des applications.

    La première partie couvre les différents business models avec leurs avantages et inconvénients, et les clefs pour réussir le lancement d’une application. Cette partie a été présentée par Julien Amouroux de Nokia.

    Voici le lien vers sa présentation

    La deuxième partie couvre l’utilisation du SDK Microsoft Advertising, et une petite démonstration d’intégration de celui-ci dans une application, tout ceci par Aurélien Lemoine, de ClevLab (twitter).

    Aurélien a posté sa présentation sur le skydrive de ClevLab.

    Enfin, sachez que vous pouvez également revoir le webcast !

    A vous de nous dire maintenant ce que vous aimeriez vois dans le prochain livemeeting!

  • Pierre's Embedded and Mobile Blog

    [Windows Phone 7.5] Ce que signifie la mise à jour 7.1.1 (Tango) du SDK pour votre application

    • 0 Comments

    Une CTP de la version 7.1.1 du SDK Windows Phone “Tango” a été annoncée au Mobile World Congress, et sur le blog de l’équipe Windows Phone. Au menu, plutôt des bonnes nouvelles: la mise à jour “Tango” ouvre la porte à des terminaux plus low-cost, particulièrement utiles dans les pays émergents, ajoute le support d’un certain nombre de langues et de pays pour le marketplace, et cela se traduit par un nombre d’utilisateurs potentiels de vos apps qui grossit d’environ 60% d’un seul coup…

    Parmi les concessions faites sur le châssis hardware pour diminuer les coûts des téléphones, il y a la possibilité de faire des terminaux avec seulement 256Mo de RAM. Ce choix a pour conséquence qu’une application qui consommerait plus de 90Mo de mémoire serait coupée automatiquement… Cela concerne moins de 5% des applications du Marketplace et nous travaillons avec ces développeurs pour les aider à revenir sous cette barre fatidique.

    Pour tester si c’est votre cas, la CTP de la version 7.1.1 du SDK Windows Phone amène une version “bridée” à 256Mo de l’émulateur. il n’y a en gros que ça d’intéressant dans cette version, qui n’est de toutes façons pas encore mure pour publier des applications sur Marketplace (pas de licence dite “go live”). Pas besoin de se jeter dessus, donc, surtout pour votre machine de production, mais si vous êtes dans les 5% à consommer plus de 90Mo, il peut être bon de le tester rapidement.

    Si vous savez que vous avez systématiquement besoin de plus de 90Mo, vous pouvez l’indiquer dans votre manifest, et alors l’application n’apparaitra plus aux utilisateurs des téléphones low-cost, évitant l’expérience “j’installe mais ça plante”.

    Il suffit de rajouter, dans le fichier WMAppManifest.xml, sous les capabilities les 3 lignes suivantes:

    <Requirements>
      <Requirement Name="ID_REQ_MEMORY_90" />
    </Requirements>
    

     

    Si on résume, soit vous utilisez moins de 90Mo, et tout va bien, soit vous utilisez plus de 90Mo de RAM, et là 2 options:

    1. Vous optimisez
    2. Vous décrétez que vous ne voulez pas que votre application soit installable sur les téléphones ne disposant que de 256Mo de mémoire, avec les 3 lignes ci-dessus

     

    Attention aux background agents…

    Votre application n’est pas sensée dépendre d’un background agent pour fonctionner correctement: dès le début, vous deviez prendre en compte le fait que vos utilisateurs peuvent les désactiver manuellement dans le panneau de configuration. Sur les terminaux à 256Mo de RAM, ils ne tourneront pas, de toutes façons. Une raison de plus d’y penser, donc, en créant l’expérience de votre application…

    • Cela ne concerne que les background agents génériques (PeriodicTask/ResourceIntensiveTask).
    • Si vous n’avez pas encadré le lancement de votre background agent dans un block try/catch, une InvalidOperationException sera levée et fera éventuellement crasher votre application… (qui aurait crashé de la même manière si le nombre maximum de background agents sur un terminal “normal” est atteint)… Si vous n’avez pas envisagé ce cas, je vous conseille de le faire Sourire
    • Si vous avez besoin de background agents pour activer des options spécifiques (live-tile, par exemple) essayez de ne proposer cette option que si le terminal dispose de plus de 256Mo… ce qui m’amène à la question suivante:

     

    Comment savoir si un terminal dispose de plus de 256 Mo?

    Réponse: En utilisant les DeviceExtendedProperties:

    try
    {
        long result = 
        (long)DeviceExtendedProperties.GetValue("ApplicationWorkingSetLimit");
    }
    catch (ArgumentOutOfRangeException) 
    {
        // The device has not received the OS update, which means the device is a 512-MB device.
    }

     

    Comment optimiser l’usage de la mémoire?

    La racine de tout ce qui concerne les performances des applications Windows Phone est sur cette page:

     

    Si vous êtes dans le cas d’un jeu en XNA (particulièrement sensible à l’usage de la mémoire) vous pouvez vous tourner vers:

     

    Une session qui a été jouée au Techdays 2012 sur le sujet sera par ailleurs bientôt en ligne…

    Pour conclure, je dirais bien que pragmatiquement à partir du moment où on code propre, et où on avait regardé dès le début les contraintes de certification de Marketplace (qui incluent, depuis la première version, la limite de 90Mo), il n’y aura pas de problème. Et pour ceux qui auraient une situation particulière, lié à un usage spécifique ou à une erreur bénigne dans le code au lancement des background agents, la résolution est facile! A vous de jouer!

    Source: Developping for 256-MB devices sur MSDN

  • Pierre's Embedded and Mobile Blog

    [Windows Phone 7.5] Supprimer le “pinch to zoom” sur un contrôle WebBrowser

    • 3 Comments

    Le ViewPort

    Le ViewPort se défini dans le code HTML. Il indique la largeur “virtuelle” de la page web. Sur un terminal mobile, on a envie d’ajuster le ViewPort en fonction de la largeur de l’écran, et d’une plateforme à une autre, ça peut varier (ça sera la même pour tous les Windows Phone). Le ViewPort permet de définir plusieurs propriétés:

    • width: par défaut, 320 (pixels). Comme ça c’est compatible iPhone, et après c’est le navigateur qui se charge de faire la conversion “pixels web –> pixels réels”.
    • height : par défaut, 480
    • user-scalable: permet de définir si l’utilisateur peut zoomer dans la page

     

    Certaines plateformes définissent des paramètres comme minimum-scale, maximum-scale, ou initial-scale… Ils ne sont pas supportées par IE9 dans Windows Phone.

    Le truc classique en manipulant le viewport pour supprimer l’effet de zoom, c’est de passer le paramètre user-scalable à “no” et le paramètre “width” à “device-width”:

    <meta name="viewport" content="width=device-width, user-scalable=no"/>  
    

     

    Supprimer les manipulations

    Mais cela ne suffit pas! En effet, si l’utilisateur essaie de zoomer, la page zoomera quand même… puis reviendra en place automatiquement, empêchant d’afficher un autre niveau de zoom que celui prescrit initialement, mais indiquant à l’utilisateur que son geste a bien été pris en compte (bonne pratique d’ergonomie en général, mais pas top quand on veut cacher qu’on utilise une webview… parce qu’on sait tous que c’est pourri!).

    Pour supprimer cet effet, il faut supprimer carrément les évènements de manipulation au niveau du contrôle WebBrowser. cela nécessite un peu de code qui m’a gentiment été soufflé par nos amis d’Ucaya, et plus particulièrement Romuald, dont l’origine est ce post de Colin Eberhardt:

    private void WebBrowser_Loaded(object sender, System.Windows.RoutedEventArgs e)
    {
        var border = ((Microsoft.Phone.Controls.WebBrowser)sender).Descendants<Border>().Last() as Border;
    
        border.ManipulationDelta += Border_ManipulationDelta;
        border.ManipulationCompleted += Border_ManipulationCompleted;
    }
    
    private void Border_ManipulationCompleted(object sender,
                                        ManipulationCompletedEventArgs e)
    {
        // suppress zoom
        if (e.FinalVelocities.ExpansionVelocity.X != 0.0 ||
            e.FinalVelocities.ExpansionVelocity.Y != 0.0)
            e.Handled = true;
    }
    
    private void Border_ManipulationDelta(object sender,
                                            ManipulationDeltaEventArgs e)
    {
        // suppress zoom
        if (e.DeltaManipulation.Scale.X != 0.0 ||
            e.DeltaManipulation.Scale.Y != 0.0)
            e.Handled = true;
    
        //// optionally suppress scrolling
        //if (ScrollDisabled)
        //{
        //    if (e.DeltaManipulation.Translation.X != 0.0 ||
        //      e.DeltaManipulation.Translation.Y != 0.0)
        //        e.Handled = true;
        //}
    }

    Evidemment, il faut associer la méthode WebBrowser_Loaded à l’évènement Loaded du contrôle WebBrowser…

    Petite précision à propos de ce bout de code: il utilise la très excellente extension LinqToVisualTree qu’il faudra donc ajouter également au projet…

    Et voila, plus d’effet de zoom. Ceci étant dit, ça ne doit pas vous encourager à utiliser les WebBrowser pour autre chose qu’afficher des pages HTML… et surtout, quelqu’en soit votre utilisation, ne les utilisez jamais, AU GRAND JAMAIS, dans un Panorama ou un Pivot, ça casse l’expérience de navigation horizontale. Il y a une place spéciale en enfer pour les gens qui font ça. Vous voilà prévenu!

    Du bon usage du contrôle WebBrowser

    Les contrôles de type “WebBrowser”, (ou WebView) sont rarement bien utilisés…

    Un WebBrowser, c’est fait pour afficher du contenu web (du HTML) parce qu’on ne veut/peut pas le parser (par exemple, une page d’authentification OAuth).

    • Ce n’est pas fait pour éviter d’avoir à créer une expérience native.
    • Ce n’est pas fait pour réutiliser des vues entre différentes plateformes.
    • Ce n’est pas fait pour s’acheter une place sur un store, qu’on n’aurait pas eu avec un site web mobile.

     

    Malheureusement 90% du temps c’est ça qu’on voit. Il ne faut pas faire. Une expérience native c’est justement pour avoir quelque chose de spécifique à chaque plateforme, en terme d’ergonomie, de look’n’feel. C’est ce que les utilisateurs attendent! Malheureusement le développement d’application n’est pas toujours piloté par le développeur soucieux de la beauté du code, ou le créa soucieux de la beauté des visuels et des animations. Des fois, le responsable du projet qui n’a pas assez de sous, ou de temps, et qui doit faire avec ce qu’il a… et on se retrouve avec des webviews mal utilisées.

    Alors quand on utilise un contrôle WebBrowser, pour de bonnes ou de mauvaises raisons, il faut en contrôler le comportement. Sinon on se retrouve sur wtfmobileweb.com.

    Encore merci à @RomuxX pour l’info, et pour d’autres lectures intéressantes sur le sujet, je vous encourage à aller voir la page sur le développement web pour Windows Phone 7.5, sur MSDN.

  • Pierre's Embedded and Mobile Blog

    [E-Camp] Animations et Transitions de pages dans Windows Phone 7.5, webcast et slides

    • 0 Comments

    Comme pour tous les e-camps, vous pouvez retrouver le webcast directement sur la page de l’évènement (en cliquant sur “Afficher en ligne”). Quant aux slides, je les ai publiées sur ce skydrive, les voici :

    D’une manière générale sachez que chaque e-camp peut être retrouvé directement sur sa page d’inscription, une fois qu’il a été enregistré (le jour J) il peut être revu.

  • Pierre's Embedded and Mobile Blog

    [Techdays 2012] The Geek is in da House : le webcast, les slides et le code de la session

    • 0 Comments

    Suite à cette session mémorable dont le but était d’exposer les “petits projets” de quelques geeks bien fondus pour leur maison, voici le contenu de la session… le webcast, les slides, le code!

    Le Webcast

    image

    Pour retrouver la session il faut cliquer sur le 4ème chapitre dans la barre de défilement Sourire

    Contrôler son portail avec son téléphone (Fabien Tanquerel)

    Fabien (@ftanquerel) de D-Cube a commencé par nous faire une petite démonstration d’interfaçage avec du hardware à base de Netduino Plus : il nous explique le matériel utilisé, et nous fournit slides et codes sources sur le blog D-Cube

    Installer une infrastructure domotique pour pas cher et la piloter avec… n’importe quoi (Salah Amer)

    Salah (@proteus91300) nous montre quel matériel utiliser pour automatiser sa maison en X10 et le service WCF qu’il a développé pour interfacer sa maison avec son téléphone, son Nao, Kinect… bref un peu tout. Bonus à la fin, il nous parle de proteus, sa salle serveur chez lui, avec robot lego monté sur rails pour allumer/éteindre les machines, et serrure biométrique…  et vous pouvez retrouver à la fois ses slides et son code source sur cet article de son blog.

    Automatiser son climatiseur avec l’internet des objets… (moâ)

    Je montre dans cette partie comment on utilise un Netduino Plus et OpenSenSe pour mettre son climatiseur sur internet et pouvoir avoir des relevés de température réguliers, une automatisation de son démarrage en fonction de la chaleur dans la pièce, et un contrôle à distance. Les slides et le code sont sur ce skydrive là!

    L’infrastructure de streaming vidéo geek

    David (@deltakosh) et Stan (@squastana) ont fait des recherches avancées, field-testés et wife-proofées pour se débarasser de leurs dvds acquis légalement en les stockant sans pertes de qualité ou de données dans des gros NAS, et conçu à base de matériel (peu corporate on en conviendra) un mediacenter ultime et pas cher. Leur présentation est disponible dans ce même skydrive

    Pour terminer, je dirai que le futur de cette session est à écrire! on peut garder ce format avec d’autres projets, on peut imaginer des sessions “geek in the office”, “geek in the car”… j’ai même eu une proposition “geek in the kitchen” Sourire Alors lancez-vous, bidouillez, codez, racontez nous vos projets, faites vous connaitre, bref, partageons!

  • Pierre's Embedded and Mobile Blog

    [Techdays 2012] EMB202 : Concevoir une application robotique avec Kinect et Robotics Developer Studio 4: les slides et la démo!

    • 0 Comments

    Voici un petit dossier avec les slides et la démo de la session EMB202, sur la conception d’applications robotique avec Kinect, et son intégration dans Robotics Developer Studio 4

    Les slides:

    La totale avec la démo disponible dans ce dossier skydrive

    Pour ceux qui s’intéressent plus particulièrement à la plateforme robotique que j’utilise dans cette session, il s’agit d’Eddie de chez Parallax

    Prochain rendez-vous pour la robotique chez Microsoft, Innrobo, les 14,15 et 16 Mars, à Lyon!

  • Pierre's Embedded and Mobile Blog

    LiveMeeting : Comment faire des animations et des transitions pour rendre vos applications plus fluides?

    • 0 Comments

    E-camp : Windows Phone 7 - Comment faire des animations et transitions pour rendre vos applications plus fluides ?

     

    Ce vendredi, à la pause déjeuner, 13h30 – 14h, retrouvez moi pour un petit livemeeting de 20 minutes + 10 minutes de questions/réponses sur le thème des animations et des transitions. Ces dernières sont un point clef pour rendre votre application fluide aux yeux de l’utilisateur, le guider dans l’expérience, et c’est souvent un des détails qui font la différence entre une bonne et une excellente application.

    Voici le lien pour s’inscrire et suivre l’évènement!

    Pensez à être là 5 minutes en avance pour vérifier que la connectivité est bonne, il s’agit d’un livemeeting! et si vous ne pouvez être là, sachez que ce livemeeting sera webcasté, et accessible avec ce même lien!

  • Pierre's Embedded and Mobile Blog

    [Windows Phone 7.5] Récupérer les rapports de crashs sur Marketplace

    • 2 Comments

    Petite astuce qui gagne à être partagée évoquée lors d’une discussion avec David Catuhe ce matin : la possibilité de récupérer les stacktraces des crashes de votre application après l’avoir publiée (c’est à dire les crashes que subissent vos utilisateurs)! petit guide pour trouver cette fonctionnalité (un peu planquée, et en béta) de Marketplace.

    Quand vous êtes loggés, accédez à votre dashboard Windows Phone 7

    image

    Dans le dashboard, il y a la case “App Highlights” dans lequel vous avez les downloads récents, ainsi que les crashs:

    image

    Et là, si vous cliquez sur le nom de l’application, ça vous emmène sur les détails (reviews, etc)…. mais si vous cliquez sur le nombre de crash vous arrivez sur un joli graph de reporting:

    image

    observez que vous avez un bouton en haut à droite, qui permet de télécharger un fichier excel avec les dernières stacktraces (c’est une fonctionnalité en beta)

    Voici un exemple de crash report détaillé, avec la stack trace et la fonction qui pose problème

    image

    (bien entendu le bug qui cause ce crash a été créé uniquement dans le but d’écrire cet article, et pas du tout à cause d’une erreur de débutant dans le code de votre serviteur… Clignement d'œil)

    Si vous voulez plus de détails, il faudra vous tourner vers une solution d’instrumentation plus précise, comme par exemple BugSense (petit article dessus de l’ami Fabien).

  • Pierre's Embedded and Mobile Blog

    Slides du Livemeeting “outils et trucs pratiques, de la conception à la certification”

    • 2 Comments

    imageVoici les slides du Livemeeting d'u 20/12/2011, organisé dans le cadre de l’Accélérateur Windows Phone 7. Le webcast devrait être disponible rapidement, j’updaterai ce post quand ça sera le cas!

    Le but de ce livemeeting était de fournir des trucs pratiques tout au long du cycle de développement d’une application, que ce soit des outils de mockup, des petits toolkits et des librairies à connaitre… le slide deck n’est pas bien long car il y a eu beaucoup de démonstrations sur Visual Studio 2010 et Expression Blend, mais vous retrouverez dedans tous les liens utiles.

     

    A bientôt pour d’autres livemeeting dans le cadre de l’accélérateur!

Page 1 of 10 (240 items) 12345»