Apprendre à lancer votre application windows 10 via Cortana

Image non disponible

Avec la sortie de Windows 10 (W10), Microsoft met à disposition de ses utilisateurs un assistant personnel : Cortana. Cet outil permet tout un tas de possibilités, à l'image de Siri chez Apple ou Google Now chez Google.

La fonctionnalité qui va nous intéresser, au sein de cet article, est la possibilité de lancer son application W10 via Cortana. En effet, il est possible de définir des phrases qui seront comprises par Cortana et de les lier à l'application pour lancer cette dernière via un scénario particulier.

Commentez Donner une note à l'article (5)

Article lu   fois.

L'auteur

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction : Cortana et ses modes de fonctionnement

Avant tout, il est nécessaire de comprendre comment fonctionne l'enregistrement d'un fichier de commande (VoiceCommand). Seule l'application, lorsqu'elle est en cours d'exécution, peut enregistrer ce fichier au sein de Cortana. Il est donc nécessaire de lancer au minimum une fois votre application pour qu'elle soit intégrée dans Cortana.

II. Cas simple de lancement d'une application via Cortana

Nous allons commencer par un cas très simple de mise en œuvre, où nous allons demander à notre application de réagir à deux phrases pour lancer une page en particulier. L'application devra donc réagir à la commande « Soat, affiche les séries », en se lançant directement sur la page des vidéos.

Pour ce faire, nous partirons du template de base des applications Windows 10 en C#.

Une fois ce projet créé (dans mon exemple je l'ai appelé CortanaLaunch), nous allons y ajouter un fichier de commandes. Je l'ai nommé VCD.xml (oui je sais, que d'imagination !).

Ce fichier de commandes contiendra donc les informations nécessaires pour enregistrer les différentes commandes que Cortana devra retenir et associer à notre application.

Voici donc à quoi ce dernier va ressembler :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
<?xml version="1.0" encoding="utf-8">
<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.1">
  <CommandSet xml:lang="fr-fr" Name="CortanaLaunchCommandSet_fr-fr">
    <CommandPrefix> Soat,</CommandPrefix>
    <Example>affiche les séries</Example>

    <Command Name="launchSeries">
      <Example> affiche les séries </Example>
      <ListenFor> affiche les séries </ListenFor>
      <Feedback> Affichage des séries </Feedback>
      <Navigate/>
    </Command>

  </CommandSet>
</VoiceCommands>

Décomposons un peu ce fichier :

  • le CommandSet correspond à une langue. Pour supporter plusieurs langues, il nous suffit donc d'ajouter autant de CommandSet que voulu ;
  • le CommandPrexix, quant à lui, est le nom de votre application ou le nom qui devra être présent au sein de vos différentes commandes ;
  • Example, comme son nom l'indique, sert à fournir un exemple à Cortana ;
  • voilà enfin le côté intéressant, la balise Command ! Cette dernière correspond à une commande particulière ou plutôt un cas d'usage particulier. Quésaco ? Eh bien dans les faits, cette commande contient plusieurs éléments qui correspondront à ce que doit faire Cortana quand une phrase est détectée. C'est donc le point névralgique de votre fichier. À noter qu'une commande peut contenir plusieurs phrases. Nous y reviendrons plus tard. Enfin, une commande peut comporter de nombreux éléments. Ceux présents dans ce fichier sont ceux qui vont nous intéresser immédiatement, nous reviendrons plus tard sur les autres éléments qui peuvent s'avérer très utiles ;
  • la balise Example sert donc à fournir un exemple d'utilisation de cette commande en particulier ;
  • la balise ListenFor définit ce qui doit être reconnu par Cortana ;
  • et enfin, la balise Feedback permet de fournir un retour à l'utilisateur lorsque cette commande est déclenchée ;
  • ah oui, j'allais oublier la balise Navigate. Cette dernière permet de lancer l'application, ou tout simplement de naviguer sur une page précise si cette dernière est déjà lancée.

Comme nous pouvons le voir, dans notre cas, Cortana répondra à la phrase « SOAT, affiche les séries ».

Une fois ce fichier créé, il est donc nécessaire d'enregistrer le fichier VCD auprès de Cortana. Et pour ce faire, nous allons l'enregistrer après chaque lancement de notre application. Nous allons donc créer une classe statique au sein de notre projet, que nous appellerons CortanaHelper, dont le contenu est le suivant pour le moment :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
public static class CortanaHelper
{
    public static async Task RegisterVCD()
    {
        var vcdFile = await Package.Current.InstalledLocation.GetFileAsync("VCD.xml");
        await Windows.ApplicationModel.VoiceCommands.VoiceCommandDefinitionManager.InstallCommandDefinitionsFromStorageFileAsync(vcdFile);
    }
}

Désormais, si on lance Cortana et qu'on lui demande « Que puis-je dire ? », on voit bien apparaître notre application « Cortana.Launch » :

Image non disponible

De plus, si on clique pour plus de détails, on voit bien notre commande avec son exemple :

Image non disponible

Et donc, que se passe-t-il si jamais nous décidons d'ajouter un nouveau cas d'utilisation où l'utilisateur demande à Cortana d'afficher le calendrier (des séries) ? Eh bien, il nous faut tout d'abord ajouter le code suivant au sein de notre fichier VCD :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
<Command Name="launchHomeland">
  <Example> affiche la série homeland </Example>
  <ListenFor> affiche la série homeland </ListenFor>
  <Feedback> Affichage de la série Homeland </Feedback>
  <Navigate/>
</Command>

Après avoir relancé notre application (et donc de nouveau enregistré notre fichier VCD pour mettre à jour les commandes auprès de Cortana), nous obtenons le résultat suivant :

Image non disponible

Bravo ! Nous avons désormais deux commandes enregistrées. Et que se passe-t-il si nous demandons à Cortana « Soat, affiche les séries » ?

Eh bien l'application se lance, mais… rien, elle reste sur son écran de chargement, mais dans les faits elle ne se lance pas réellement. En effet, lorsque l'application est lancée via Cortana, ce n'est pas la fonction OnLaunched de votre fichier App.xaml.cs qui sera appelée, mais la fonction OnActivated.

En faisant un override de la fonction OnActivated au sein de votre fichier App.xaml.cs, on obtient une fonction prenant en paramètre un argument du type IActivatedEventArgs. Ce dernier possède donc une propriété ActivationKind, et lorsque cette dernière est définie à VoiceCommand, l'argument est de type VoiceCommandActivatedEventArgs, et on peut dès lors accéder à une propriété de cet argument qui nous indique le nom de la commande qui correspond au lancement de cette application : RulePath[0], mais aussi directement au texte qui a été reconnu par exemple : Text.

Dans note cas, en fonction de la commande qui aura été déclenchée, nous redirigerons l'utilisateur vers la bonne page. Pour l'occasion j'ai créé deux pages :

  • SeriesPage : qui représente la liste des pages ;
  • SeriePage : qui représente le détail d'une série.

Comme on peut s'en douter, la commande launchSeries doit nous faire naviguer vers SeriesPage, et launchHomeland doit nous faire naviguer vers SeriePage avec le paramètre homeland.

Nous obtiendrons alors le code suivant au sein de la fonction OnActivated :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
protected override void OnActivated(IActivatedEventArgs args)
{
    Type pageToNavigate = typeof(MainPage);
    object param = null;
    if (args.Kind == ActivationKind.VoiceCommand)
    {
        var voiceCommandArgs = args as VoiceCommandActivatedEventArgs;
        if (voiceCommandArgs != null)
        {
            string commandName = voiceCommandArgs.Result.RulePath[0];
            switch (commandName)
            {
                case "launchSeries":
                    pageToNavigate = typeof(SeriesPage);
                    break;

                case "launchHomeland":
                    pageToNavigate = typeof(SeriePage);
                    param = "homeland";
                    break;
            }
        }
    }

    Frame rootFrame = Window.Current.Content as Frame;
    if (rootFrame == null)
    {
        rootFrame = new Frame();
        rootFrame.NavigationFailed += OnNavigationFailed;

        Window.Current.Content = rootFrame;
    }

    rootFrame.Navigate(pageToNavigate, param);
    Window.Current.Activate();
}

Désormais, vous avez un aperçu de ce que peut vous apporter Cortana, mais on constate rapidement une limite à notre scénario. En effet, on s'imagine mal créer autant de commandes que l'on a de séries ! Nous allons donc nous attaquer… aux paramètres !

III. Utilisation de paramètres pour le lancement

Pour ce faire, tout commence par notre fameux fichier de commandes. En effet, nous en avons vu plus haut une version minimaliste, mais deux fonctionnalités sont très appréciées au sein de ce fichier : les paramètres de commandes et les mots optionnels. Les mots optionnels, comme leur nom l'indique, permettent en mettant un mot entre crochets de le rendre optionnel. Attention par contre avec l'utilisation de cette fonction, si vous êtes dans le cas où vous souhaitez pouvoir reconnaître nombre de variantes d'une phrase, alors préférez ajouter plusieurs phrases plutôt qu'une quantité trop importante de mots optionnels.

Par exemple, au lieu de cette formulation :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
<Command Name="launchSeries">
  <Example> affiche les séries </Example>
  <ListenFor> [montre] [affiche] [moi] les séries </ListenFor>
  <Feedback> Affichage des séries </Feedback>
  <Navigate />
</Command>

Préférez la formulation suivante :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
<Command Name="launchSeries">
  <Example> affiche les séries </Example>
  <ListenFor> affiche [moi] les séries </ListenFor>
  <ListenFor> montre [moi] les séries </ListenFor>
  <Feedback> Affichage des séries </Feedback>
  <Navigate />
</Command>

En effet, la multitude de mots optionnels provoque parfois une mauvaise compréhension chez Cortana, il est donc important d'avoir des phrases les plus simples possible.

La seconde fonctionnalité qui se trouve être la plus puissante est donc la présence des paramètres. Il est ainsi possible de définir un paramètre au sein de notre commande. La seule contrainte est de définir une liste de résultats possibles pour ce dernier. Dans notre exemple, nous souhaiterions pouvoir lancer directement la page de différentes séries. Nous commencerons par deux séries : « Homeland » et « Jessica Jones ». Nous obtiendrions la commande suivante :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
<Command Name="launchSerie">
  <Example> affiche la série homeland </Example>
  <ListenFor> affiche la série {serie} </ListenFor>
  <Feedback> Affichage de la série Homeland </Feedback>
  <Navigate />
</Command>

<PhraseList Label="serie">
  <Item> Homeland </Item>
  <Item> Jessica Jones </Item>
</PhraseList>

On peut donc s'apercevoir qu'on a pu ajouter le paramètre nommé « serie » au sein de notre commande. Les paramètres sont entre accolades et doivent donc être liés à une « phraseList » qui peut être commune à plusieurs commandes. Il est important que le label de l'élément phraseList soit le même que le nom du paramètre.

Nous allons désormais pouvoir récupérer la valeur de notre paramètre au sein de notre app.xaml.cs. Il nous suffit pour cela de modifier la valeur de la variable « param » lorsque l'on détecte que la commande LaunchSerie est lancée au sein de la fonction OnActivated. Pour cela, il suffit de changer le code suivant :

 
Sélectionnez
1.
2.
3.
4.
case "launchHomeland":
    pageToNavigate = typeof(SeriePage);
    param = "homeland";
    break;

par celui-ci :

 
Sélectionnez
1.
2.
3.
4.
case "launchSerie":
    pageToNavigate = typeof(SeriePage);
    string param = voiceCommandArgs.Result.SemanticInterpretation.Properties["serie"][0];
    break;

Voilà, avec cette simple petite modification, nous pouvons voir que nous avons de grosses possibilités qui sont très simples à mettre en place.

Il va désormais se poser un problème. Imaginons que notre liste de séries soit définie via un WebService, comment faire pour mettre à jour notre commande de manière à la rendre dynamique ? Voici le thème de la prochaine partie de cet article !

IV. Rendre dynamiques les commandes vocales

À première vue, un choix s'offrirait à nous pour pouvoir rendre notre liste de séries dynamique (la PhraseList « serie ») : réécrire notre fichier VCD.xml avec les bonnes informations puis le réenregistrer. Cette fonctionnalité s'apparenterait à du bricolage néanmoins.

Heureusement, il existe un moyen, dit « natif », de modifier la valeur de notre PhraseList. Pour ce faire, nous allons avoir besoin de modifier directement, auprès de notre VoiceCommandManager, notre liste de paramètres.

Nous allons créer une méthode statique au sein de notre classe CortanaHelper, du nom de « EditSeries », qui aura pour objectif de mettre à jour notre liste de paramètres (PhraseList) avec en plus des séries déjà existantes dans le fichier VCD la série « Breaking Bad ». Nous obtiendrons alors le code suivant :

La méthode statique est créée dans la méthode OnLaunched définie dans le fichier App.xaml.cs.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
public static async Task EditSeries()
{
    Windows.ApplicationModel.VoiceCommands.VoiceCommandDefinition commandSet;

    if (Windows.ApplicationModel.VoiceCommands.VoiceCommandDefinitionManager.InstalledCommandDefinitions.TryGetValue(
            "CortanaLaunchCommandSet_fr-fr", out commandSet))
    {
        await commandSet.SetPhraseListAsync(
          "serie", new string[] {"Homeland", "Jessica Jones", "Breaking Bad"});
    }
}

Un peu plus en détail, nous pouvons donc nous apercevoir que nous tentons de récupérer notre CommandSet, puisque nous modifions la phraseList correspondant au label « serie ». Rien de très compliqué donc !

Il nous suffit désormais d'appeler cette fonction juste après l'appel de la fonction d'enregistrement de notre fichier VCD, puis tout devrait fonctionner. Pour cela, je passe ma fonction OnLaunched au sein de mon fichier App.xaml.cs en async et je remplace la ligne d'enregistrement de mon fichier VCD par le code qui suit :

 
Sélectionnez
1.
2.
await CortanaHelper.RegisterVCD();
await CortanaHelper.EditSeries();

Si l'on teste, on peut désormais s'apercevoir que la série « Breaking Bad » est bien reconnue.

Le code source est disponible ici : https://github.com/SoatGroup/TutoCortanaW10.

V. Conclusion

Désormais, vous savez comment lancer votre application avec Cortana. Dans un prochain article, nous verrons comment s'intégrer directement au sein de Cortana, c'est-à-dire afficher des informations sans avoir à lancer votre application.

VI. Remerciements

Ce tutoriel a été publié avec l'aimable autorisation de la société Soat.

Nous remercions Laethy pour la gabarisation et milkoseck pour la relecture orthographique.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2016 Thomas Gobin. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.