Integrar a Cortana numa aplicação Windows Phone

Este artigo tem como objetivo apresentar um exemplo de como integrar a Cortana com uma aplicação de Windows Phone.

Introdução

Uma das funcionalidades interessantes no Windows Phone 8.1 é a Cortana. A Cortana não é mais do que uma assistente pessoal, que ajuda os utilizadores em tarefas básicas, tais como ligar a um amigo, marcar na agenda um acontecimento e outras tarefas.

Atualmente não está disponível para todas as línguas, por esta razão muitos utilizadores que não são nativos de inglês mudaram as definições do seu dispositivo para suportar esta funcionalidade, é o caso de muitos portugueses. Para os interessados que ainda não o tenham feito, é recomendado que alterem as definições para Inglês e para Estados Unidos, para mais informações consultar este artigo.

De suporte ao artigo iremos usar o exemplo Menu App criado no Windows App Studio.

Integrando a Cortana

A Cortana irá usar comandos de voz para interagir com as aplicações. Para isso esses comandos de voz tem que ser instalados por cada aplicação (cada vez que a aplicação inicia), para que a Cortana saiba como poderá interagir com cada aplicação.

Desta forma, o primeiro passo para integrar com a Cortana, na Menu App, passa por definir um ficheiro Voice Command Definition (VCD), este ficheiro não é mais do que um ficheiro XML com os vários comandos que a Cortana irá reconhecer e por sua vez permitirá fazer a ligação com a aplicação.

Para a Menu App, iremos definir Menu como o nome para a Cortana irá usar para iniciar a aplicação e iremos definir dois comandos:

  • Show Command – irá ser o comando para apresentar ecrãs específicos da aplicação, para a Menu App poderá ser os ecrãs Beverages, Starters, Mains, Desserts e Special Offers;
  • Natural Language Command – irá permitir que a Cortana reconheça expressões comuns do ser humano, tais como I am hungry, I want to eat e I want to drink.

Como foi mencionado anteriormente a Cortana não está disponível em todas as língua e atualmente não é possível interagir com a Cortana em português, por esta razão se está a usar expressões em inglês.

De seguida iremos ver um exemplo de um VCD, que estará definido para inglês. No entanto, é possível definir para outras línguas que a Cortana suporte.

<? xml version = "1.0" encoding = "utf-8" ?>
 
<!-- Be sure to use the new v1.1 namespace to utilize the new PhraseTopic feature --> 
<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.1">
  <!-- The CommandSet Name is used to programmatically access the CommandSet --> 
  <CommandSet xml:lang="en-us" Name="englishCommands">
    <!-- The CommandPrefix provides an alternative to your full app name for invocation --> 
    <CommandPrefix>Menu</CommandPrefix>
    <!-- The CommandSet Example appears in the global help alongside your app name --> 
    <Example> I am hungry </Example>
 
    <Command Name = "ShowCommand">
      <Example> Show Mains </Example>
      <ListenFor> Show {dictatedShowTerms} </ListenFor>
      <Feedback> Showing in Menu ... </Feedback>
      <Navigate Target = "MainPage.xaml" />
    </Command>

    <Command Name = "NaturalLanguageCommand">
      <Example> I want to eat </Example>
      <ListenFor> {naturalLanguage} </ListenFor>
      <Feedback> Starting Menu ... </Feedback>
      <Navigate Target = "MainPage.xaml" />
    </Command>
 
    <PhraseTopic Label="dictatedShowTerms" Scenario="Search">
      <Subject> Starters </Subject>
      <Subject> Mains </Subject>
      <Subject> Desserts </Subject>
      <Subject> Beverages </Subject>
      <Subject> Special Offers </Subject>
    </PhraseTopic>
    <PhraseTopic Label="naturalLanguage" Scenario="Natural Language">
      <Subject> I want to eat </Subject>
      <Subject> I want to drink </Subject>
      <Subject> I am hungry </Subject>
    </PhraseTopic>
  </CommandSet>
</VoiceCommands>

De salientar que 

  • CommandSet – define os comandos para cada língua
  • CommandPrefix – define o nome com que a Cortana irá reconhecer a aplicação, neste caso Menu
  • Example – define um exemplo de como usar a Cortana para interagir com a  Menu App
  • Command – define o comando de voz suportado
  • PhraseTopic – define possíveis expressões que a Cortana poderá identificar para iniciar o comando de voz

Para mais detalhes consulte o artigo Voice Command Definition (VCD) elements and attributes.

Nota: No ficheiro Manifest é necessário selecionar a capacidade de “Microphone“.

Neste momento temos o ficheiro VCD definido e portanto temos que o instalar no dispositivo (e cada vez que a aplicação inicia). Para isso iremos criar o seguinte método

private async Task InstallVoiceCommandsAsync()
 {
    var storageFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Cortana.xml"));
    await VoiceCommandManager.InstallCommandSetsFromStorageFileAsync(storageFile);
 }

De seguida devemos chamar este método no método OnNavigationTo da MainPage, da seguinte forma

protected override async void OnNavigatedTo(NavigationEventArgs e)
     {
         _dataTransferManager = DataTransferManager.GetForCurrentView();
         _dataTransferManager.DataRequested += OnDataRequested;
         _navigationHelper.OnNavigatedTo(e);
         await MainViewModel.LoadDataAsync();
         if (e.NavigationMode == NavigationMode.New)
         {
             await InstallVoiceCommandsAsync();
         }
     }

Por fim, temos que alterar o método OnActivated no App.xaml.cs para que a interação da Cortana com a Menu App seja concretizada. Portanto, quando a Cortana identifica um comando de voz para a Menu App o método OnActivated será chamado e irá enviar como parâmetro um SpeechRecognitionResult que nos permite obter o comando de voz e o texto reconhecido pela Cortana.

protected override void OnActivated(IActivatedEventArgs args)
       {
           base.OnActivated(args);
         
           if (args.Kind == ActivationKind.VoiceCommand)
           {
               var commandArgs = args as VoiceCommandActivatedEventArgs;
               if (commandArgs != null)
               {
                   SpeechRecognitionResult speechRecognitionResult = commandArgs.Result;
 
                   var voiceCommandName = speechRecognitionResult.RulePath[0];
                   var textSpoken = speechRecognitionResult.Text;
                   
                   switch (voiceCommandName)
                   {
                       case "ShowCommand":
                           if (textSpoken.ToLower().Contains("starters"))
                           {
                               RootFrame.Navigate(typeof (StartersPage));
                           }
                           if (textSpoken.ToLower().Contains("mains"))
                           {
                               RootFrame.Navigate(typeof(Main1Page));
                           }
                           if (textSpoken.ToLower().Contains("desserts"))
                           {
                               RootFrame.Navigate(typeof(DessertsPage));
                           }
                           if (textSpoken.ToLower().Contains("beverages"))
                           {
                               RootFrame.Navigate(typeof(BeveragesPage));
                           }
                           if (textSpoken.ToLower().Contains("special") || 
                               textSpoken.ToLower().Contains("offer"))
                           {
                               RootFrame.Navigate(typeof(MainPage), "SpecialOffers");
                           }
                           break;
                       case "NaturalLanguageCommand":
                           if (textSpoken.ToLower().Contains("eat") ||
                               textSpoken.ToLower().Contains("hungry"))
                           {
                               RootFrame.Navigate(typeof(Main1Page));
                           }
 
                           if (textSpoken.ToLower().Contains("drink"))
                           {
                                RootFrame.Navigate(typeof (BeveragesPage));
                           }
                           if (textSpoken.ToLower().Contains("special"))
                           {
                               RootFrame.Navigate(typeof (MainPage), "SpecialOffers");
                           }
                           break;
                   }
               }
           }
           Window.Current.Activate();
       }

Para cada comando de voz definido no ficheiro VCD devemos definir qual a informação que iremos apresentar. Por exemplo, quando o utilizador diz I want to drink irá ser apresentado o ecrã BeveragesPage.xaml que irá apresentar as bebidas disponíveis.

Para quem tiver interesse em alterar dinamicamente o ficheiro Voice Command Definition (VCD) é recomendado a leitura deste artigo.

Usando a Cortana

Antes de usarmos a Cortana, temos que instalar e correr a Menu App no dispositivo, para que o ficheiro VCD seja instalado e depois disto podemos usar a Cortana para interagir com a Menu App.

Quando iniciamos a aplicação Cortana no Windows Phone, iremos ver o seguinte ecrã

E ao clicar em see more (ver mais) iremos obter os ecrãs

 

Os quais irão ajudar a perceber de que forma podemos usar a Cortana para interagir com a Cortana. Clicando na Menu App iremos ver mais exemplos (que foram definidos no ficheiro VCD).

Voltando ao ecrã inicial da Cortana e introduzindo o texto ou usando a voz para dizer Menu I am hungry iremos obter o ecrã

Por sua vez a Cortana irá inicializar a Menu App

e então será apresentado o ecrã dos pratos principais

Quando mencionamos Menu I want to drink iremos ter o ecrã

Por sua vez a Cortana irá inicializar a Menu App

e então será apresentado o ecrã das bebidas

Quando mencionamos Menu Show offers iremos ter o ecrã

Por sua vez a Cortana irá inicializar a Menu App

e então será apresentado o ecrã das ofertas especiais

Conclusão

Em conclusão, podemos concluir que a interação com a Cortana é relativamente simples, sendo possível fornecer exemplos ao utilizador para facilitar a interação , é possível definir casos em que será apresentados ecrãs específicos e claro será possível usar uma linguagem natural para com expressão mais comuns podermos satisfazer os pedidos do utilizador.