Share via


Activación de una aplicación en segundo plano en Cortana mediante comandos de voz

Advertencia

Esta característica ya no se admite a partir de la actualización de mayo de 2020 de Windows 10 (versión 2004, nombre de código "20H1").

Consulte Cortana en Microsoft 365 para obtener información sobre cómo Cortana está transformando las experiencias de productividad modernas.

Además de usar comandos de voz en Cortana para acceder a las características del sistema, también puede ampliar Cortana con características y funcionalidades de la aplicación (como una tarea en segundo plano) mediante comandos de voz que especifican una acción o un comando para ejecutar. Cuando una aplicación controla un comando de voz en segundo plano, no tiene foco. En su lugar, devuelve todos los comentarios y los resultados a través del lienzo de Cortana y la voz de Cortana.

Las aplicaciones se pueden activar en primer plano (la aplicación toma el foco) o activarse en segundo plano (Cortana conserva el foco), en función de la complejidad de la interacción. Por ejemplo, los comandos de voz que requieren información adicional de contexto o usuario (como enviar un mensaje a un contacto específico) se controlan mejor en una aplicación en primer plano, mientras que los comandos básicos (como enumerar los próximos viajes) se pueden controlar en Cortana a través de una aplicación en segundo plano.

Si quieres activar una aplicación en primer plano con los comandos de voz, consulta el tema Activar una aplicación en primer plano con los comandos de voz a través de Cortana.

Nota

Un comando de voz es una sola expresión con una intención específica, definida en un archivo de definición de comandos de voz (VCD), dirigida a una aplicación instalada a través de Cortana.

Un archivo VCD define uno o más comandos de voz, cada uno de ellos con un único propósito.

Las definiciones de comandos de voz pueden variar en complejidad. Pueden admitir cualquier cosa desde una sola expresión restringida a una colección de expresiones de lenguaje natural más flexibles, que denotan la misma intención.

Usamos una aplicación de planeación y administración de viajes denominada Adventure Works que se integra en la interfaz de usuario de Cortana, que se muestra aquí, para demostrar muchos de los conceptos y las funciones que analizamos. Para obtener más información, consulta el ejemplo de comando de voz de Cortana.

Captura de pantalla del inicio de la aplicación en primer plano de Cortana

Para ver un viaje de Adventure Works sin Cortana, un usuario debe iniciar la aplicación y navegar a la página Viajes próximos.

Con comandos de voz a través de Cortana para iniciar la aplicación en segundo plano, el usuario puede decir, en su lugar, Adventure Works, when is my trip to Las Vegas?. La aplicación controla el comando y Cortana muestra los resultados junto con el icono de la aplicación y otros datos de aplicación, si se han proporcionado.

Captura de pantalla de Cortana con una consulta básica y una pantalla de resultados mediante la aplicación AdventureWorks en segundo plano

Los pasos básicos siguientes agregan funcionalidad de comando de voz y amplían Cortana con funcionalidad en segundo plano desde la aplicación mediante la entrada de voz o teclado.

  1. Crea un servicio de aplicaciones (consulta Windows.ApplicationModel.AppService) que Cortana invoque en segundo plano.
  2. Crea un archivo VCD. El archivo VCD es un documento XML que define todos los comandos hablados que el usuario puede decir para iniciar acciones o invocar comandos al activar la aplicación. Consulta VCD elements and attributes v1.2.
  3. Registra los conjuntos de comandos en el archivo VCD cuando se inicia la aplicación.
  4. Controle la activación en segundo plano del servicio de aplicaciones y la ejecución del comando de voz.
  5. Muestra y di la información apropiada para el comando de voz en Cortana.

Sugerencia

Requisitos previos

Si acabas de empezar a desarrollar aplicaciones para la Plataforma universal de Windows (UWP), consulta estos temas para familiarizarte con las tecnologías que te presentamos aquí.

Directrices para la experiencia del usuario

Consulta Directrices de diseño de Cortana para obtener información sobre cómo integrar tu aplicación con Cortana e interacciones de voz para obtener sugerencias útiles sobre cómo diseñar una aplicación habilitada para voz útil y atractiva.

Crear una nueva solución con un proyecto principal en Visual Studio

  1. Inicia Microsoft Visual Studio 2015.
    Aparecerá la página de inicio de Visual Studio 2015.

  2. En el menú Archivo, seleccione Nuevo>Proyecto.
    Se abre el cuadro de diálogo Nuevo proyecto. El panel izquierdo del cuadro de diálogo te permite seleccionar el tipo de plantillas que se muestran.

  3. En el panel izquierdo, expanda Plantillas > instaladas > Visual C# > Windows y, a continuación, elija el grupo de plantillas universales. El panel central del cuadro de diálogo muestra una lista de plantillas de proyecto para aplicaciones Plataforma universal de Windows (UWP).

  4. En el panel central, selecciona la plantilla Aplicación vacía universal de Windows.
    La plantilla Aplicación en blanco crea una aplicación para UWP mínima que se compila y ejecuta. La plantilla Aplicación en blanco no incluye ningún control o datos de la interfaz de usuario. Agregue controles a la aplicación con esta página como guía.

  5. En el cuadro de texto Nombre, escribe el nombre del proyecto. Ejemplo: use AdventureWorks.

  6. Haga clic en el botón Aceptar para crear el proyecto.
    Microsoft Visual Studio crea tu proyecto y lo muestra en el Explorador de soluciones.

Agregar recursos de imagen al proyecto principal y especificarlos en el manifiesto de aplicación

Las aplicaciones para UWP deben seleccionar automáticamente las imágenes más adecuadas. La selección se basa en configuraciones específicas y funcionalidades del dispositivo (contraste alto, píxeles efectivos, configuración regional, etc.). Debe proporcionar las imágenes y asegurarse de usar la convención de nomenclatura y la organización de carpetas adecuadas en el proyecto de la aplicación para las distintas versiones de recursos.
Si no proporciona las versiones de recursos recomendadas, la experiencia del usuario puede sufrir de las siguientes maneras.

  • Accesibilidad
  • Localización
  • Calidad de la imagen
    Las versiones de recursos se usan para adaptar los siguientes cambios en la experiencia del usuario.
  • Preferencias de usuario
  • Habilidades
  • Tipo de dispositivo
  • Location

Para obtener más información sobre los recursos de imagen para los factores de contraste alto y escala, visite la página Directrices para los recursos de icono y icono que se encuentra en msdn.microsoft.com/windows/uwp/controls-and-patterns/tiles-and-notifications-app-assets.

Debe asignar un nombre a los recursos mediante calificadores. Los calificadores de recursos son modificadores de carpetas y nombres de archivo que identifican el contexto en el que debe usarse una versión particular de un recurso.

La convención de nomenclatura estándar es foldername/qualifiername-value[_qualifiername-value]/filename.qualifiername-value[_qualifiername-value].ext.
Ejemplo: images/logo.scale-100_contrast-white.png, que puede hacer referencia al código con solo la carpeta raíz y el nombre de archivo: images/logo.png.
Para obtener más información, visite la página How to name resources using qualifiers (Cómo asignar nombres a los recursos mediante calificadores) que se encuentra en msdn.microsoft.com/library/windows/apps/xaml/hh965324.aspx.

Microsoft recomienda marcar el idioma predeterminado en los archivos de recursos de cadena (como en-US\resources.resw) y el factor de escala predeterminado en imágenes (por logo.scale-100.pngejemplo, ), aunque actualmente no planee proporcionar recursos de resolución localizados o múltiples. Sin embargo, como mínimo, Microsoft recomienda proporcionar recursos para 100, 200 y 400 factores de escala.

Importante

El icono de aplicación usado en el área de título del lienzo de Cortana es el icono Square44x44Logo especificado en el Package.appxmanifest archivo.
También puede especificar un icono para cada entrada en el área de contenido del lienzo de Cortana . Los tamaños de imagen válidos para los iconos de resultados son:

  • 68 (ancho) x 68 (alto)
  • 68 (ancho) x 92 (alto)
  • 280 (ancho) x 140 (alto)

El icono de contenido no se valida hasta que se pasa un objeto VoiceCommandResponse a la clase VoiceCommandServiceConnection . Si pasa un objeto VoiceCommandResponse a Cortana que incluye un icono de contenido con una imagen que no cumple estas relaciones de tamaño, puede producirse una excepción. 

Ejemplo: La aplicación Adventure Works (VoiceCommandService\\AdventureWorksVoiceCommandService.cs) especifica un cuadrado simple y gris (GreyTile.png) en la clase VoiceCommandContentTile mediante la plantilla de icono TitleWith68x68IconAndText . Las variantes del logotipo se encuentran en VoiceCommandService\\Imagesy se recuperan mediante el método GetFileFromApplicationUriAsync .

var destinationTile = new VoiceCommandContentTile();  

destinationTile.ContentTileType = VoiceCommandContentTileType.TitleWith68x68IconAndText;
destinationTile.Image = await StorageFile.GetFileFromApplicationUriAsync(
    new Uri("ms-appx:///AdventureWorks.VoiceCommands/Images/GreyTile.png")
);  

Creación de un proyecto de App Service

  1. Haga clic con el botón derecho en el nombre de la solución y seleccione Nuevo > proyecto.

  2. En Plantillas instaladas >> Visual C# > Windows > Universal, seleccione Windows Runtime Componente. El componente Windows Runtime es el componente que implementa el servicio de aplicaciones (Windows.ApplicationModel.AppService).

  3. Escriba un nombre para el proyecto y haga clic en el botón Aceptar .
    Ejemplo: VoiceCommandService.

  4. En Explorador de soluciones, seleccione el proyecto y cambie el VoiceCommandService nombre del Class1.cs archivo generado por Visual Studio. Ejemplo: Adventure Works usa AdventureWorksVoiceCommandService.cs.

  5. Haga clic en el botón ; cuando se le pregunte si desea cambiar el nombre de todas las apariciones de Class1.cs.

  6. En el archivo AdventureWorksVoiceCommandService.cs:

    1. Agrega la siguiente directiva de uso:
      using Windows.ApplicationModel.Background;
    2. Cuando creas un nuevo proyecto, el nombre del proyecto se usa como el espacio de nombres raíz de forma predeterminada en todos los archivos. Cambia el nombre del espacio de nombres para anidar el código de servicio de la aplicación en el proyecto principal. Ejemplo: namespace AdventureWorks.VoiceCommands.
    3. Haga clic con el botón derecho en el nombre del proyecto de App Service en Explorador de soluciones y seleccione Propiedades.
    4. En la pestaña Biblioteca , actualice el campo Espacio de nombres predeterminado con este mismo valor.
      Ejemplo: AdventureWorks.VoiceCommands.
    5. Crea una nueva clase que implemente la interfaz IBackgroundTask. Esta clase requiere un método Ejecutar que es el punto de entrada cuando Cortana reconoce el comando de voz.

    Ejemplo: una clase de tarea en segundo plano básica de la aplicación Adventure Works .

    Nota:

    La propia clase de tarea en segundo plano, así como todas las clases del proyecto de tarea en segundo plano, deben ser clases públicas selladas.

    namespace AdventureWorks.VoiceCommands
    {
        ...
    
        /// <summary>
        /// The VoiceCommandService implements the entry point for all voice commands.
        /// The individual commands supported are described in the VCD xml file. 
        /// The service entry point is defined in the appxmanifest.
        /// </summary>
        public sealed class AdventureWorksVoiceCommandService : IBackgroundTask
        {
            ...
    
            /// <summary>
            /// The background task entrypoint. 
            /// 
            /// Background tasks must respond to activation by Cortana within 0.5 second, and must 
            /// report progress to Cortana every 5 seconds (unless Cortana is waiting for user
            /// input). There is no running time limit on the background task managed by Cortana,
            /// but developers should use plmdebug (https://msdn.microsoft.com/library/windows/hardware/jj680085%28v=vs.85%29.aspx)
            /// on the Cortana app package in order to prevent Cortana timing out the task during
            /// debugging.
            /// 
            /// The Cortana UI is dismissed if Cortana loses focus. 
            /// The background task is also dismissed even if being debugged. 
            /// Use of Remote Debugging is recommended in order to debug background task behaviors. 
            /// Open the project properties for the app package (not the background task project), 
            /// and enable Debug -> "Do not launch, but debug my code when it starts". 
            /// Alternatively, add a long initial progress screen, and attach to the background task process while it runs.
            /// </summary>
            /// <param name="taskInstance">Connection to the hosting background service process.</param>
            public void Run(IBackgroundTaskInstance taskInstance)
            {
              //
              // TODO: Insert code 
              //
              //
        }
      }
    }
    
  7. Declara la tarea en segundo plano como AppService en el manifiesto de la aplicación.

    1. En Explorador de soluciones, haga clic con el botón derecho en el Package.appxmanifest archivo y seleccione Ver código.
    2. Busque el elemento Application .
    3. Agregue un Extensions elemento al Application elemento .
    4. Agregue un elemento uap:Extension al elemento Extensions.
    5. Agregue un Category atributo al uap:Extension elemento y establezca el valor del Category atributo en windows.appService.
    6. Agregue un EntryPoint atributo al uap: Extension elemento y establezca el valor del EntryPoint atributo en el nombre de la clase que implementa IBackgroundTask.
      Ejemplo: AdventureWorks.VoiceCommands.AdventureWorksVoiceCommandService.
    7. Agregue un elemento uap:AppService al elemento uap:Extension.
    8. Agregue un Name atributo al uap:AppService elemento y establezca el valor del Name atributo en un nombre para el servicio de aplicaciones, en este caso AdventureWorksVoiceCommandService.
    9. Agregue un segundo uap:Extension elemento al Extensions elemento .
    10. Agregue un Category atributo a este uap:Extension elemento y establezca el valor del Category atributo en windows.personalAssistantLaunch.

    Ejemplo: un manifiesto de la aplicación Adventure Works.

    <Package>
        <Applications>
            <Application>
    
                <Extensions>
                    <uap:Extension Category="windows.appService" EntryPoint="CortanaBack1.VoiceCommands.AdventureWorksVoiceCommandService">
                        <uap:AppService Name="AdventureWorksVoiceCommandService"/>
                    </uap:Extension>
                    <uap:Extension Category="windows.personalAssistantLaunch"/>
                </Extensions>
    
            <Application>
        <Applications>
    </Package>
    
  8. Agrega este proyecto de servicio de la aplicación como referencia en el proyecto principal.

    1. Haga clic con el botón derecho en referencias.
    2. Seleccione Agregar referencia....
    3. En el cuadro de diálogo Administrador de referencias, expande Proyectos y selecciona el proyecto de servicio de la aplicación.
    4. Haga clic en el botón Aceptar .

Crear un archivo VCD

  1. En Visual Studio, haga clic con el botón derecho en el nombre del proyecto principal y seleccione Agregar > nuevo elemento. Agregar un archivo XML.
  2. Escriba un nombre para el archivo VCD .
    Ejemplo: AdventureWorksCommands.xml.
  3. Haga clic en el botón Agregar .
  4. En el Explorador de soluciones, selecciona el archivo VCD.
  5. En la ventana Propiedades, establece Acción de compilación en Contenido y luego establece Copiar en el directorio de salida en Copiar si es posterior.

Edición del archivo VCD

  1. Agregue un VoiceCommands elemento con un xmlns atributo que apunte a https://schemas.microsoft.com/voicecommands/1.2.

  2. Para cada idioma compatible con la aplicación, cree un CommandSet elemento que incluya los comandos de voz admitidos por la aplicación.
    Puedes declarar varios CommandSet elementos, cada uno con un atributo diferente xml:lang para que tu aplicación se use en distintos mercados. Por ejemplo, una aplicación para el Estados Unidos podría tener un CommandSet para inglés y un CommandSet para español.

    Importante

    Para activar una aplicación e iniciar una acción mediante un comando de voz, la aplicación debe registrar un archivo VCD que incluya un elemento con un CommandSet idioma que coincida con el idioma de voz indicado en el dispositivo del usuario. El idioma de voz se encuentra en Configuración > Idioma de voz > del sistema>.

  3. Agregue un Command elemento para cada comando que quiera admitir.
    Cada Command declarado en un archivo VCD debe incluir esta información:

    • Atributo Name que la aplicación usa para identificar el comando de voz en tiempo de ejecución.

    • Elemento Example que incluye una frase que describe cómo un usuario invoca el comando. Cortana muestra el ejemplo cuando el usuario dice What can I say?, Helpo pulsa Ver más.

    • Elemento ListenFor que incluye las palabras o frases que la aplicación reconoce como un comando. Cada ListenFor elemento puede contener referencias a uno o varios PhraseList elementos que contienen palabras específicas relevantes para el comando.

      Nota

      ListenFor Los elementos no deben modificarse mediante programación. Sin embargo, PhraseList los elementos asociados a ListenFor los elementos se pueden modificar mediante programación. Las aplicaciones deben modificar el contenido del PhraseList elemento en tiempo de ejecución en función del conjunto de datos generado a medida que el usuario usa la aplicación.

      Para obtener más información, vea Modificar dinámicamente listas de frases de Cortana VCD.

    • Elemento Feedback que incluye el texto para que Cortana se muestre y hable mientras se inicia la aplicación.

Un Navigate elemento indica que el comando de voz activa la aplicación en primer plano. En este ejemplo, el comando showTripToDestination es una tarea en primer plano.

Un VoiceCommandService elemento indica que el comando de voz activa la aplicación en segundo plano. El valor del Target atributo de este elemento debe coincidir con el Name valor del atributo del uap:AppService elemento en el archivo package.appxmanifest. En este ejemplo, los whenIsTripToDestination comandos y cancelTripToDestination son tareas en segundo plano que especifican el nombre del servicio de aplicaciones como AdventureWorksVoiceCommandService.

Para obtener más detalles, consulta la referencia VCD elements and attributes v1.2.

Ejemplo: parte del archivo VCD que define los en-us comandos de voz para la aplicación Adventure Works .

<?xml version="1.0" encoding="utf-8" ?>
<VoiceCommands xmlns="https://schemas.microsoft.com/voicecommands/1.2">
<CommandSet xml:lang="en-us" Name="AdventureWorksCommandSet_en-us">
    <AppName> Adventure Works </AppName>
    <Example> Show trip to London </Example>
    
    <Command Name="showTripToDestination">
        <Example> Show trip to London </Example>
        <ListenFor RequireAppName="BeforeOrAfterPhrase"> show [my] trip to {destination} </ListenFor>
        <ListenFor RequireAppName="ExplicitlySpecified"> show [my] {builtin:AppName} trip to {destination} </ListenFor>
        <Feedback> Showing trip to {destination} </Feedback>
        <Navigate />
    </Command>
      
    <Command Name="whenIsTripToDestination">
        <Example> When is my trip to Las Vegas?</Example>
        <ListenFor RequireAppName="BeforeOrAfterPhrase"> when is [my] trip to {destination}</ListenFor>
        <ListenFor RequireAppName="ExplicitlySpecified"> when is [my] {builtin:AppName} trip to {destination} </ListenFor>
        <Feedback> Looking for trip to {destination}</Feedback>
        <VoiceCommandService Target="AdventureWorksVoiceCommandService"/>
    </Command>
    
    <Command Name="cancelTripToDestination">
        <Example> Cancel my trip to Las Vegas </Example>
        <ListenFor RequireAppName="BeforeOrAfterPhrase"> cancel [my] trip to {destination}</ListenFor>
        <ListenFor RequireAppName="ExplicitlySpecified"> cancel [my] {builtin:AppName} trip to {destination} </ListenFor>
        <Feedback> Cancelling trip to {destination}</Feedback>
        <VoiceCommandService Target="AdventureWorksVoiceCommandService"/>
    </Command>

    <PhraseList Label="destination">
        <Item>London</Item>
        <Item>Las Vegas</Item>
        <Item>Melbourne</Item>
        <Item>Yosemite National Park</Item>
    </PhraseList>
</CommandSet>

Instalación de los comandos de VCD

La aplicación debe ejecutarse una vez para instalar el VCD.

Nota:

No se conservan datos de comandos de voz en las instalaciones de la aplicación. Para garantizar que los datos de comandos de voz de la aplicación permanecen intactos, considera la posibilidad de inicializar el archivo VCD cada vez que la aplicación se inicie o active, o bien mantener una configuración que indique si el VCD está instalado actualmente.

En el archivo app.xaml.cs:

  1. Agrega la siguiente directiva de uso:

    using Windows.Storage;
    
  2. Marque el OnLaunched método con el modificador async.

    protected async override void OnLaunched(LaunchActivatedEventArgs e)
    
  3. Llame al InstallCommandDefinitionsFromStorageFileAsync método en el OnLaunched controlador para registrar los comandos de voz que se deben reconocer.
    Ejemplo: La aplicación Adventure Works define un StorageFile objeto .
    Ejemplo: llame al GetFileAsync método para inicializar el StorageFile objeto con el AdventureWorksCommands.xml archivo .
    A continuación, el StorageFile objeto se pasa al InstallCommandDefinitionsFromStorageFileAsync método .

    try {
       // Install the main VCD. 
       StorageFile vcdStorageFile = await Package.Current.InstalledLocation.GetFileAsync(
             @"AdventureWorksCommands.xml"
       );
    
       await Windows.ApplicationModel.VoiceCommands.VoiceCommandDefinitionManager.InstallCommandDefinitionsFromStorageFileAsync(vcdStorageFile);
    
       // Update phrase list.
       ViewModel.ViewModelLocator locator = App.Current.Resources["ViewModelLocator"] as ViewModel.ViewModelLocator;
       if(locator != null) {
             await locator.TripViewModel.UpdateDestinationPhraseList();
         }
     }
     catch (Exception ex) {
         System.Diagnostics.Debug.WriteLine("Installing Voice Commands Failed: " + ex.ToString());
     }
    

Controlar la activación

Especifique cómo responde la aplicación a las activaciones de comandos de voz posteriores.

Nota

Debes iniciar la aplicación al menos una vez después de instalar los conjuntos de comandos de voz.

  1. Comprobar que la aplicación se haya activado mediante un comando de voz.

    Invalide el Application.OnActivated evento y compruebe si IActivatedEventArgs.Kind es VoiceCommand.

  2. Determinar el nombre del comando y lo que se ha dicho.

    Obtenga una referencia a un VoiceCommandActivatedEventArgs objeto de IActivatedEventArgs y consulte la Result propiedad de un SpeechRecognitionResult objeto .

    Para determinar lo que dijo el usuario, compruebe el valor de Text o las propiedades semánticas de la frase reconocida en el SpeechRecognitionSemanticInterpretation diccionario.

  3. Realizar la acción apropiada en la aplicación como, por ejemplo, ir a la página que quieras.

    Nota

    Si necesita consultar su VCD, visite la sección Editar el archivo VCD .

    Después de recibir el resultado del reconocimiento de voz para el comando de voz, obtendrá el nombre del comando del primer valor de la RulePath matriz. Dado que el archivo VCD define más de un comando de voz posible, debe comprobar que el valor coincide con los nombres de comando del VCD y realizar la acción adecuada.

    La acción más común para una aplicación es navegar a una página con contenido relevante para el contexto del comando de voz.
    Ejemplo: abra la página TripPage y pase el valor del comando de voz, cómo se ha introducido el comando y la frase de destino reconocida (si procede). Como alternativa, la aplicación puede enviar un parámetro de navegación a SpeechRecognitionResult al navegar a la página TripPage .

    Puedes averiguar si el comando de voz que inició la aplicación se habló realmente, o si se ha escrito como texto, desde el SpeechRecognitionSemanticInterpretation.Properties diccionario con la clave commandMode . El valor de esa clave será voice o text. Si el valor de la clave es voice, considere la posibilidad de usar la síntesis de voz (Windows.Media.SpeechSynthesis) en la aplicación para proporcionar al usuario comentarios hablados.

    Use SpeechRecognitionSemanticInterpretation.Properties para averiguar el contenido hablado en las PhraseList restricciones o PhraseTopic de un ListenFor elemento. La clave de diccionario es el valor del Label atributo del PhraseList elemento o PhraseTopic . Ejemplo: el código siguiente para Obtener acceso al valor de la frase {destination} .

    /// <summary>
    /// Entry point for an application activated by some means other than normal launching. 
    /// This includes voice commands, URI, share target from another app, and so on. 
    /// 
    /// NOTE:
    /// A previous version of the VCD file might remain in place 
    /// if you modify it and update the app through the store. 
    /// Activations might include commands from older versions of your VCD. 
    /// Try to handle these commands gracefully.
    /// </summary>
    /// <param name="args">Details about the activation method.</param>
    protected override void OnActivated(IActivatedEventArgs args) {
        base.OnActivated(args);
    
        Type navigationToPageType;
        ViewModel.TripVoiceCommand? navigationCommand = null;
    
        // Voice command activation.
        if (args.Kind == ActivationKind.VoiceCommand) {
            // Event args may represent many different activation types. 
            // Cast the args so that you only get useful parameters out.
            var commandArgs = args as VoiceCommandActivatedEventArgs;
    
            Windows.Media.SpeechRecognition.SpeechRecognitionResult speechRecognitionResult = commandArgs.Result;
    
            // Get the name of the voice command and the text spoken.
            // See VoiceCommands.xml for supported voice commands.
            string voiceCommandName = speechRecognitionResult.RulePath[0];
            string textSpoken = speechRecognitionResult.Text;
    
            // commandMode indicates whether the command was entered using speech or text.
            // Apps should respect text mode by providing silent (text) feedback.
            string commandMode = this.SemanticInterpretation("commandMode", speechRecognitionResult);
    
            switch (voiceCommandName) {
                case "showTripToDestination":
                    // Access the value of {destination} in the voice command.
                    string destination = this.SemanticInterpretation("destination", speechRecognitionResult);
    
                    // Create a navigation command object to pass to the page.
                    navigationCommand = new ViewModel.TripVoiceCommand(
                        voiceCommandName,
                        commandMode,
                        textSpoken,
                        destination
                    );
    
                    // Set the page to navigate to for this voice command.
                    navigationToPageType = typeof(View.TripDetails);
                    break;
                default:
                    // If not able to determine what page to launch, then go to the default entry point.
                    navigationToPageType = typeof(View.TripListView);
                    break;
            }
        }
        // Protocol activation occurs when a card is selected within Cortana (using a background task).
        else if (args.Kind == ActivationKind.Protocol) {
            // Extract the launch context. In this case, use the destination from the phrase set (passed
            // along in the background task inside Cortana), which makes no attempt to be unique. A unique id or 
            // identifier is ideal for more complex scenarios. The destination page is left to check if the 
            // destination trip still exists, and navigate back to the trip list if it does not.
            var commandArgs = args as ProtocolActivatedEventArgs;
            Windows.Foundation.WwwFormUrlDecoder decoder = new Windows.Foundation.WwwFormUrlDecoder(commandArgs.Uri.Query);
            var destination = decoder.GetFirstValueByName("LaunchContext");
    
            navigationCommand = new ViewModel.TripVoiceCommand(
                "protocolLaunch",
                "text",
                "destination",
                destination
            );
    
            navigationToPageType = typeof(View.TripDetails);
        }
        else {
            // If launched using any other mechanism, fall back to the main page view.
            // Otherwise, the app will freeze at a splash screen.
            navigationToPageType = typeof(View.TripListView);
        }
    
        // Repeat the same basic initialization as OnLaunched() above, taking into account whether
        // or not the app is already active.
        Frame rootFrame = Window.Current.Content as Frame;
    
        // Do not repeat app initialization when the Window already has content,
        // just ensure that the window is active.
        if (rootFrame == null) {
            // Create a frame to act as the navigation context and navigate to the first page.
            rootFrame = new Frame();
            App.NavigationService = new NavigationService(rootFrame);
    
            rootFrame.NavigationFailed += OnNavigationFailed;
    
            // Place the frame in the current window.
            Window.Current.Content = rootFrame;
        }
    
        // Since the expectation is to always show a details page, navigate even if 
        // a content frame is in place (unlike OnLaunched).
        // Navigate to either the main trip list page, or if a valid voice command
        // was provided, to the details page for that trip.
        rootFrame.Navigate(navigationToPageType, navigationCommand);
    
        // Ensure the current window is active
        Window.Current.Activate();
    }
    
    /// <summary>
    /// Returns the semantic interpretation of a speech result. 
    /// Returns null if there is no interpretation for that key.
    /// </summary>
    /// <param name="interpretationKey">The interpretation key.</param>
    /// <param name="speechRecognitionResult">The speech recognition result to get the semantic interpretation from.</param>
    /// <returns></returns>
    private string SemanticInterpretation(string interpretationKey, SpeechRecognitionResult speechRecognitionResult) {
        return speechRecognitionResult.SemanticInterpretation.Properties[interpretationKey].FirstOrDefault();
    }
    

Controlar el comando de voz en el App Service

Procesar el comando de voz en el servicio de aplicaciones.

  1. Agregue las siguientes directivas using al archivo de servicio de comandos de voz.
    Ejemplo: AdventureWorksVoiceCommandService.cs.

        using Windows.ApplicationModel.VoiceCommands;
        using Windows.ApplicationModel.Resources.Core;
        using Windows.ApplicationModel.AppService;
    
  2. Aplica un aplazamiento de servicio para que el servicio de aplicaciones no finalice mientras se controla el comando de voz.

  3. Confirma que tu tarea en segundo plano se ejecuta como un servicio de aplicaciones que se activó mediante un comando de voz.

    1. Convierte IBackgroundTaskInstance.TriggerDetails a Windows.ApplicationModel.AppService.AppServiceTriggerDetails.
    2. Compruebe que IBackgroundTaskInstance.TriggerDetails.Name es el nombre del servicio de aplicaciones en el Package.appxmanifest archivo.
  4. Usa IBackgroundTaskInstance.TriggerDetails para crear un VoiceCommandServiceConnection en Cortana para recuperar el comando de voz.

  5. Registre un controlador de eventos para VoiceCommandServiceConnection. VoiceCommandCompleted para recibir una notificación cuando el servicio de aplicaciones se cierra debido a una cancelación de usuario.

  6. Registra un controlador de eventos de IBackgroundTaskInstance.Canceled para recibir notificaciones cuando el servicio de la aplicación se cierre por un error inesperado.

  7. Determinar el nombre del comando y lo que se ha dicho.

    1. Usa la propiedad VoiceCommand.CommandName para determinar el nombre del comando de voz.
    2. Para determinar lo que dijo el usuario, compruebe el valor de Text o las propiedades semánticas de la frase reconocida en el SpeechRecognitionSemanticInterpretation diccionario.
  8. Realiza la acción adecuada en el servicio de aplicaciones.

  9. Muestra y habla los comentarios al comando de voz mediante Cortana.

    1. Determine las cadenas que desea que Cortana muestre y hable con el usuario en respuesta al comando de voz y cree un VoiceCommandResponse objeto. Para obtener instrucciones sobre cómo seleccionar las cadenas de comentarios que Cortana muestra y dice, consulta las Directrices de diseño de Cortana.
    2. Use la instancia de VoiceCommandServiceConnection para notificar el progreso o la finalización a Cortana llamando a ReportProgressAsync o ReportSuccessAsync con el VoiceCommandServiceConnection objeto .

    Nota

    Si necesita consultar su VCD, visite la sección Editar el archivo VCD .

    public sealed class VoiceCommandService : IBackgroundTask {
        private BackgroundTaskDeferral serviceDeferral;
        VoiceCommandServiceConnection voiceServiceConnection;
    
        public async void Run(IBackgroundTaskInstance taskInstance) {
            //Take a service deferral so the service isn&#39;t terminated.
            this.serviceDeferral = taskInstance.GetDeferral();
    
            taskInstance.Canceled += OnTaskCanceled;
    
            var triggerDetails = taskInstance.TriggerDetails as AppServiceTriggerDetails;
    
            if (triggerDetails != null &amp;&amp; 
                triggerDetails.Name == "AdventureWorksVoiceServiceEndpoint") {
                try {
                    voiceServiceConnection = 
                    VoiceCommandServiceConnection.FromAppServiceTriggerDetails(
                        triggerDetails);
                    voiceServiceConnection.VoiceCommandCompleted += 
                    VoiceCommandCompleted;
    
                    VoiceCommand voiceCommand = await 
                    voiceServiceConnection.GetVoiceCommandAsync();
    
                    switch (voiceCommand.CommandName) {
                        case "whenIsTripToDestination":
                            {
                                var destination = 
                                voiceCommand.Properties["destination"][0];
                                SendCompletionMessageForDestination(destination);
                                break;
                            }
    
                            // As a last resort, launch the app in the foreground.
                        default:
                            LaunchAppInForeground();
                            break;
                    }
                }
                finally {
                    if (this.serviceDeferral != null) {
                        // Complete the service deferral.
                        this.serviceDeferral.Complete();
                    }
                }
            }
        }
    
        private void VoiceCommandCompleted(VoiceCommandServiceConnection sender,
            VoiceCommandCompletedEventArgs args) {
            if (this.serviceDeferral != null) {
                // Insert your code here.
                // Complete the service deferral.
                this.serviceDeferral.Complete();
            }
        }
    
        private async void SendCompletionMessageForDestination(
            string destination) {
            // Take action and determine when the next trip to destination
            // Insert code here.
    
            // Replace the hardcoded strings used here with strings 
            // appropriate for your application.
    
            // First, create the VoiceCommandUserMessage with the strings 
            // that Cortana will show and speak.
            var userMessage = new VoiceCommandUserMessage();
            userMessage.DisplayMessage = "Here's your trip.";
            userMessage.SpokenMessage = "Your trip to Vegas is on August 3rd.";
    
            // Optionally, present visual information about the answer.
            // For this example, create a VoiceCommandContentTile with an 
            // icon and a string.
            var destinationsContentTiles = new List<VoiceCommandContentTile>();
    
            var destinationTile = new VoiceCommandContentTile();
            destinationTile.ContentTileType = 
                VoiceCommandContentTileType.TitleWith68x68IconAndText;
            // The user taps on the visual content to launch the app. 
            // Pass in a launch argument to enable the app to deep link to a 
            // page relevant to the item displayed on the content tile.
            destinationTile.AppLaunchArgument = 
                string.Format("destination={0}", "Las Vegas");
            destinationTile.Title = "Las Vegas";
            destinationTile.TextLine1 = "August 3rd 2015";
            destinationsContentTiles.Add(destinationTile);
    
            // Create the VoiceCommandResponse from the userMessage and list    
            // of content tiles.
            var response = VoiceCommandResponse.CreateResponse(
                userMessage, destinationsContentTiles);
    
            // Cortana displays a "Go to app_name" link that the user 
            // taps to launch the app. 
            // Pass in a launch to enable the app to deep link to a page 
            // relevant to the voice command.
            response.AppLaunchArgument = string.Format(
                "destination={0}", "Las Vegas");
    
            // Ask Cortana to display the user message and content tile and 
            // also speak the user message.
            await voiceServiceConnection.ReportSuccessAsync(response);
        }
    
        private async void LaunchAppInForeground() {
            var userMessage = new VoiceCommandUserMessage();
            userMessage.SpokenMessage = "Launching Adventure Works";
    
            var response = VoiceCommandResponse.CreateResponse(userMessage);
    
            // When launching the app in the foreground, pass an app 
            // specific launch parameter to indicate what page to show.
            response.AppLaunchArgument = "showAllTrips=true";
    
            await voiceServiceConnection.RequestAppLaunchAsync(response);
        }
    }
    

Una vez activado, app service tiene 0,5 segundos para llamar a ReportSuccessAsync. Cortana muestra y dice una cadena de comentarios.

Nota

Puede declarar una cadena de comentarios en el archivo VCD. La cadena no afecta al texto de la interfaz de usuario que se muestra en el lienzo de Cortana, solo afecta al texto hablado por Cortana.

Si la aplicación tarda más de 0,5 segundos en realizar la llamada, Cortana inserta una pantalla de entrega, como se muestra aquí. Cortana muestra la pantalla de entrega hasta que la aplicación llama a ReportSuccessAsync, durante un máximo 5 segundos. Si el servicio de aplicaciones no llama a ReportSuccessAsync o a cualquiera de los VoiceCommandServiceConnection métodos que proporcionan a Cortana información, el usuario recibe un mensaje de error y se cancela el servicio de aplicaciones.

Captura de pantalla de Cortana y una consulta básica con pantallas de progreso y resultados mediante la aplicación AdventureWorks en segundo plano