Hola UWP: ¿Cortana eres tú? Iniciando aplicaciones con comandos de voz

Una de las características que más me ha gustado de las aplicaciones UWP es la capacidad que se tiene de trabajar con Cortana en Windows 10 y es que por fin poco a poco se está haciendo realidad aquel sueño nerd de poder hablar con tu máquina, darle instrucciones y que además te responda, algo que hace no mucho tiempo parecía algo muy difícil de lograr.

Implementar estos comandos de voz es sencillo en las aplicaciones UWP solo debemos tener en cuenta que los comandos de voz inician con un prefijo, el cual usualmente es el nombre de la aplicación o una "palabra clave" aunque tenemos la libertad de definir opciones para pronunciar el nombre de la aplicación antes o después del comando y elegir que comportamiento implementar cuando la aplicación se lanza.

Al escribir este post Cortana solo está disponible en las siguientes regiones y lenguajes:

  • Australia (Inglés)
  • Canadá (Inglés)
  • China (Chino simplificado)
  • Francia (Francés)
  • Alemania (Alemán)
  • Japón (Japonés)
  • Italia (Italiano)
  • España (Español)
  • Reino Unido (Inglés)
  • Estados Unidos (Inglés)

Si deseas obtener los últimos lenguajes puedes visitar el siguiente link

Nota: Toma en cuenta que para que Cortana funcione correctamente necesitamos que el lenguaje del dispositivo, el paquete de lenguaje y el país o región correspondan con las configuraciones antes mencionadas.

Definiendo VoiceCommands

Y bien vamos ahora con el código que es por lo que seguramente estás en este post.

En primer lugar, todos los comandos de voz están definidos en un archivo XML por lo tanto agregaremos una a nuestro proyecto.

Y después debemos escribir la siguiente estructura.

 <?xml version="1.0" encoding="utf-8" ?>  
<VoiceCommands xmlns="https://schemas.microsoft.com/voicecommands/1.2">  
  <CommandSet xml:lang="en-us" Name="HoLCommandSet en-us">
    <CommandPrefix>Hello commands, </CommandPrefix>
    <Example>Launch</Example>

    <Command Name="LaunchApp">
      <Example>launch</Example>
      <ListenFor>launch</ListenFor>
      <Feedback>Welcome aboard, I'm opening the app</Feedback>
      <Navigate/>
    </Command>

  </CommandSet>

  <!--Se puede agregar un soporte opcional para cualquier otro lenguaje soportado -->
  <!--<CommandSet xml:lang="es-es" Name="HoLCommandSet es-es"-->

</VoiceCommands>

Veamos en que consiste cada una de las secciones.

VoiceCommands es el elemento principal de nuestro XML y dentro del cuerpo de este tag es donde vamos a colocar todos nuestros comandos, el esquema de VoiceCommands debe apuntar a la versión 1.2.

 <VoiceCommands xmlns="https://schemas.microsoft.com/voicecommands/1.2">  

CommandSet es el elemento principal de cada uno de los comandos soportados por nuestra aplicación y debe apuntar al lenguaje que va a soportar en este caso xml:lang="en-us".

 <CommandSet xml:lang="en-us" Name="HoLCommandSet en-us">  

CommandPrefix es la palabra o frase que utilizaremos como usuarios para decirle al sistema que escuche los comandos para nuestra App.
Este prefijo debe ser definido para cada uno de los elementos CommandSet en el lenguaje que definamos.

 <CommandPrefix>Hello commands, </CommandPrefix>  

Nota: la coma que he colocado en el prefijo es opcional y solo sirve para indicar al sistema que debe hacer una pequeña pausa.

Ahora podemos crear nuestro comando, en la estructura debemos definir el elemento ListenFor que indicará al sistema que palabra o frase se utiliza para reconocer el comando, FeedBack que define el texto de confirmación que Cortana dirá al usuario al ejecutar el comando, el elemento Example para este comando y el elemento Navigate que significa que la aplicación se lanzará en el primer plano.

 <Command Name="LaunchApp">  
   <Example>launch</Example>
   <ListenFor>launch</ListenFor>
   <Feedback>Welcome aboard, I'm opening the app</Feedback>
   <Navigate/>
</Command>  

Instalando los comandos de voz

Una vez que hemos definido el archivo XML de nuestro comando de voz, es necesario instalarlo, para ello vamos a utilizar el método InstallCommandDefinitionsFromStorageFileAsync en el método OnLaunched antes de iniciar el frame principal.

  var storageFile =
                await
                    Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///VoiceCommands.xml"));

            await
                Windows.ApplicationModel.VoiceCommands.VoiceCommandDefinitionManager
                    .InstallCommandDefinitionsFromStorageFileAsync(storageFile);

Frame rootFrame = Window.Current.Content as Frame;  

Nota: Como ya habrás notado los comandos se instalan después de la primera vez que ejecutas tu aplicación.

Controlando el lanzamiento de nuestra aplicación

Cuando inicias tu aplicación a través de los comandos de voz la aplicación entra en el evento OnActivated en lugar de OnLaunched por tanto debemos crear el frame principal en este evento para que nuestra aplicación funcione.

También es necesario controlar como fue lanzada nuestra aplicación esto lo he realizado en un switch utilizando el enumerador ActivationKind

y por último manejar en un método los parámetros de nuestro comando de voz.

 protected override void OnActivated(IActivatedEventArgs args)  
{
    Frame rootFrame = Window.Current.Content as Frame;
    if (rootFrame == null)
    {
        rootFrame=new Frame();

        rootFrame.NavigationFailed += OnNavigationFailed;

        Window.Current.Content = rootFrame;
    }

    switch (args.Kind)
    {
        case ActivationKind.VoiceCommand:
            HandleVoiceCommand(args,rootFrame);
            break;
        default:
            break;
    }

    Window.Current.Activate();

    base.OnActivated(args);
}

En el método en el que manejaremos nuestros parámetros haremos un cast del parámetro arg a VoiceCommandActivatedEventArgs y obtendremos el nombre del comando para realizar las tareas que tengamos preparadas para nuestra aplicación, en este caso solo navegaremos a la página de inicio.

 private void HandleVoiceCommand(IActivatedEventArgs args,Frame frame)  
{
    var commandArgs = args as VoiceCommandActivatedEventArgs;

    var speechRecognitionResult = commandArgs.Result;
    var command = speechRecognitionResult.Text;

    var voiceCommandName = speechRecognitionResult.RulePath[0];
    var textSpoken = speechRecognitionResult.Text;

    Debug.WriteLine("Command: " + command);
    Debug.WriteLine("Text spoken: " + textSpoken);

    switch (voiceCommandName)
    {
        case "LaunchApp":
             frame.Navigate(typeof (MainPage));
             break;
        default:
        break;
    }

}

Y ahora podemos ejecutar nuestro proyecto y ver el resultado de nuestro ejemplo como se muestra en las siguientes imágenes (recuerda que debes ejecutar la aplicación al menos una vez para que se instalen los comandos).

El código de ejemplo lo he dejado en github y espero te resulte útil.

Si deseas saber más sobre los comandos de voz para Cortana visita el siguiente link

Espero te resulte útil este post y puedas incluir estos comandos de voz en tus aplicaciones.

¡Saludos!

@saturpimentel