Attivare un'app in background in Cortana usando i comandi vocali

Avviso

Questa funzionalità non è più supportata a partire dall'aggiornamento di Windows 10 di maggio 2020 (versione 2004, nome codice "20H1").

Per informazioni sul modo in cui Cortana trasforma le esperienze di produttività moderne, vedere Cortana in Microsoft 365.

Oltre a usare i comandi vocali all'interno di Cortana per accedere alle funzionalità di sistema, è anche possibile estendere Cortana con funzionalità dell'app (come attività in background) usando comandi vocali che specificano un'azione o un comando da eseguire. Quando un'app gestisce un comando vocale in background, non ottiene lo stato attivo. Restituisce invece il feedback e i risultati tramite l'area di disegno di Cortana e la voce di Cortana.

Le app possono essere attivate in primo piano (l'app assume lo stato attivo) o attivate in background (Cortana mantiene lo stato attivo), a seconda della complessità dell'interazione. Ad esempio, i comandi vocali che richiedono un contesto o input dell'utente aggiuntivo (ad esempio l'invio di un messaggio a un contatto specifico) vengono gestiti meglio in un'app in primo piano, mentre i comandi di base (ad esempio la presentazione dei prossimi viaggi) possono essere gestiti in Cortana tramite un'app in background.

Se si vuole attivare un'app in primo piano usando i comandi vocali, vedere Attivare un'app in primo piano con comandi vocali tramite Cortana.

Nota

Un comando vocale è una singola espressione con una finalità specifica, definita in un file VCD (Voice Command Definition), indirizzata a un'app installata tramite Cortana.

Un file VCD definisce uno o più comandi vocali, ognuno con una finalità univoca.

Le definizioni dei comandi vocali possono variare in termini di complessità. Possono supportare qualsiasi elemento, da una sola espressione limitata a una raccolta di espressioni del linguaggio naturale più flessibili, tutte con la stessa finalità.

Si usa un'app per la pianificazione e la gestione dei viaggi di nome Adventure Works integrata nell'interfaccia utente di Cortana, mostrata qui, per illustrare molti dei concetti e delle funzionalità discussi. Per altre informazioni, vedere l'esempio di comando vocale di Cortana.

Screenshot dell'avvio dell'app in primo piano di Cortana

Per visualizzare un viaggio Adventure Works senza Cortana, un utente deve avviare l'app e andare alla pagina Prossimi viaggi.

Usando i comandi vocali tramite Cortana per avviare l'app in background, l'utente potrebbe semplicemente dire Adventure Works, when is my trip to Las Vegas?. L'app gestisce il comando e Cortana visualizza i risultati con l'icona dell'app e a altre informazioni pertinenti, se specificate.

Screenshot di Cortana con una query di base e una schermata dei risultati usando l'app AdventureWorks in background

I seguenti passaggi di base aggiungono funzionalità di comando vocale ed estendono Cortana con funzionalità in background dell'app usando l'input vocale o da tastiera.

  1. Creare un servizio app (vedere Windows.ApplicationModel.AppService) richiamato da Cortana in background.
  2. Creare un file VCD. Il file VCD è un documento XML che definisce tutti i comandi vocali che l'utente può pronunciare per avviare azioni o richiamare comandi durante l'attivazione dell'app. Vedere Elementi VCD e attributi v1.2.
  3. Registrare i set di comandi nel file VCD all'avvio dell'app.
  4. Gestire l'attivazione in background del servizio app e l'esecuzione del comando vocale.
  5. Visualizzare e pronunciare il feedback appropriato al comando vocale all'interno di Cortana.

Suggerimento

Prerequisiti

Se non si ha familiarità con lo sviluppo di app UWP (Universal Windows Platform), vedere questi argomenti per acquisire familiarità con le tecnologie descritte qui.

Linee guida sull'esperienza utente

Vedere Linee guida di progettazione per Cortana per informazioni sull'integrazione dell'app con Cortana e Interazioni vocali per suggerimenti utili sulla progettazione di un'app di riconoscimento vocale utile e coinvolgente.

Creare una nuova soluzione con un progetto primario in Visual Studio

  1. Avviare Microsoft Visual Studio 2015.
    Viene visualizzata la pagina di avvio di Visual Studio 2015.

  2. Nel menu File selezionare Nuovo>Progetto.
    Verrà visualizzata la finestra di dialogo Nuovo progetto. Il riquadro sinistro della finestra di dialogo consente di selezionare il tipo di modello da visualizzare.

  3. Nel riquadro sinistro, espandere Modelli > installati > Visual C# > Windows, quindi scegliere il gruppo di modelli Universal. Il riquadro centrale della finestra di dialogo visualizza un elenco di modelli di progetto per le app UWP (Universal Windows Platform).

  4. Nel riquadro centrale selezionare il modello App vuota (Universal Windows).
    Il modello App vuota crea un'app UWP minima che viene compilata ed eseguita. Il modello App vuota non include dati o controlli dell'interfaccia utente. Si aggiungono controlli all'app usando questa pagina come guida.

  5. Nella casella di testo Nome digitare il nome del progetto. Esempio: usare AdventureWorks.

  6. Fare clic sul pulsante OK per creare il progetto.
    Microsoft Visual Studio crea il progetto e lo visualizza in Esplora soluzioni.

Aggiungere asset di immagini al progetto primario e specificarli nel manifesto dell'app

Le app UWP devono selezionare automaticamente le immagini più appropriate. La selezione si basa su funzionalità del dispositivo e impostazioni specifiche (contrasto elevato, pixel effettivi, impostazioni locali e così via). È necessario fornire le immagini e assicurarsi di usare la convenzione di denominazione e l'organizzazione delle cartelle appropriate all'interno del progetto dell'app per le diverse versioni delle risorse.
Se non si forniscono le versioni delle risorse consigliate, l'esperienza utente potrebbe risentirne nei modi seguenti.

  • Accessibilità
  • Localizzazione
  • Qualità dell'immagine
    Le versioni delle risorse vengono usate per adattare le seguenti modifiche nell'esperienza utente.
  • Preferenze utente
  • Capacità
  • Tipo di dispositivo
  • Ufficio

Per altri dettagli sulle risorse immagini per fattori quali contrasto elevato e scala, visitare la pagina Linee guida per le risorse riquadri e icone disponibile in msdn.microsoft.com/windows/uwp/controls-and-patterns/tiles-and-notifications-app-assets.

È necessario assegnare nomi alle risorse usando qualificatori. I qualificatori di risorse sono tasti di modifica di cartelle e nomi file che identificano il contesto in cui deve essere usata una determinata versione di una risorsa.

La convenzione di denominazione standard è foldername/qualifiername-value[_qualifiername-value]/filename.qualifiername-value[_qualifiername-value].ext.
Esempio: images/logo.scale-100_contrast-white.png, che può fare riferimento al codice usando solo la cartella radice e il nome file: images/logo.png.
Per altre informazioni, visitare la pagina Come assegnare nomi alle risorse usando i qualificatori disponibile in msdn.microsoft.com/library/windows/apps/xaml/hh965324.aspx.

Microsoft consiglia di contrassegnare la lingua predefinita nei file di risorse stringa (ad esempio en-US\resources.resw) e il fattore di scala predefinito sulle immagini (ad esempio logo.scale-100.png), anche se non si prevede di fornire risorse localizzate o con risoluzione multipla. Tuttavia, come minimo, Microsoft consiglia di fornire risorse per 100, 200 e 400 fattori di scala.

Importante

L'icona dell'app usata nell'area del titolo dell'area di disegno di Cortana è l'icona Square44x44Logo specificata nel file Package.appxmanifest.
È anche possibile specificare un'icona per ogni voce nell'area del contenuto dell'area di disegno di Cortana. Le dimensioni valide delle immagini per le icone dei risultati sono:

  • 68w x 68h
  • 68w x 92h
  • 280w x 140h

Il riquadro di contenuto non viene confermato finché un oggetto VoiceCommandResponse non viene passato alla classe VoiceCommandServiceConnection. Se si passa un oggetto VoiceCommandResponse a Cortana che include un riquadro di contenuto con un'immagine che non rispetta queste proporzioni, può verificarsi un'eccezione. 

Esempio: l'app Adventure Works (VoiceCommandService\\AdventureWorksVoiceCommandService.cs) specifica un quadrato grigio semplice (GreyTile.png) sulla classe VoiceCommandContentTile usando il modello di riquadro TitleWith68x68IconAndText. Le varianti del logo si trovano in VoiceCommandService\\Images e vengono recuperate usando il metodo GetFileFromApplicationUriAsync.

var destinationTile = new VoiceCommandContentTile();  

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

Creare un progetto di servizio app

  1. Fare clic con il pulsante destro del mouse sul nome della soluzione e selezionare Nuovo > progetto.

  2. In Modelli > installati > Visual C# > Windows > Universal, selezionare il componente Windows Runtime. Windows Runtime è il componente che implementa il servizio app (Windows.ApplicationModel.AppService).

  3. Digitare un nome per il progetto e fare clic sul pulsante OK.
    Esempio: VoiceCommandService.

  4. In Esplora soluzioni selezionare il progetto VoiceCommandService e rinominare il file Class1.cs generato da Visual Studio. Esempio: Adventure Works usa AdventureWorksVoiceCommandService.cs.

  5. Fare clic sul pulsante . Quando viene chiesto se si desidera rinominare tutte le occorrenze di Class1.cs.

  6. Nel file AdventureWorksVoiceCommandService.cs:

    1. Aggiungere la seguente direttiva using.
      using Windows.ApplicationModel.Background;
    2. Quando si crea un nuovo progetto, il nome del progetto viene usato come spazio dei nomi radice predefinito in tutti i file. Rinominare lo spazio dei nomi per annidare il codice del servizio app nel progetto primario. Esempio: namespace AdventureWorks.VoiceCommands.
    3. Fare clic con il pulsante destro del mouse sul nome del progetto del servizio app in Esplora soluzioni e selezionare Proprietà.
    4. Nella scheda Libreria aggiornare il campo Spazio dei nomi predefinito con questo stesso valore.
      Esempio: AdventureWorks.VoiceCommands).
    5. Creare una nuova classe che implementa l'interfaccia IBackgroundTask. Questa classe richiede un metodo Run, ovvero il punto di ingresso in cui Cortana riconosce il comando vocale.

    Esempio: classe di attività in background di base dall'app Adventure Works.

    Nota

    La classe di attività in background stessa, nonché tutte le classi nel progetto di attività in background, deve essere una classe pubblica sealed.

    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. Dichiarare l'attività in background come AppService nel manifesto dell'app.

    1. In Esplora soluzioni, fare clic con il pulsante destro del mouse sul file Package.appxmanifest e selezionare View Code.
    2. Trovare l'elemento Application.
    3. Aggiungere un elemento Extensions all'elemento Application.
    4. Aggiungere un elemento uap:Extension all'elemento Extensions.
    5. Aggiungere un attributo Category all'elemento uap:Extension e impostare il valore dell'attributo Category su windows.appService.
    6. Aggiungere un attributo EntryPoint sull'elemento uap: Extension e impostare il valore dell'attributo EntryPoint sul nome della classe che implementa IBackgroundTask.
      Esempio: AdventureWorks.VoiceCommands.AdventureWorksVoiceCommandService.
    7. Aggiungere un elemento uap:AppService all'elemento uap:Extension.
    8. Aggiungere un attributo Name sull'elemento uap:AppService e impostare il valore dell'attributo Name su un nome per il servizio app, in questo caso AdventureWorksVoiceCommandService.
    9. Aggiungere un secondo elemento uap:Extension all'elemento Extensions.
    10. Aggiungere un attributo Category a questo elemento uap:Extension e impostare il valore dell'attributo Category su windows.personalAssistantLaunch.

    Esempio: un manifesto dell'app 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. Aggiungere questo progetto del servizio app come riferimento nel progetto primario.

    1. Fare clic con il pulsante destro del mouse su Riferimenti.
    2. Selezionare Aggiungi riferimento....
    3. Nella finestra di dialogo Reference Manager espandere Projects e selezionare il progetto del servizio app.
    4. Fare clic sul pulsante OK.

Creare un file VCD

  1. In Visual Studio, fare clic con il pulsante destro del mouse sul nome del progetto primario, selezionare Aggiungi > Nuovo elemento. Aggiungere un file XML.
  2. Digitare un nome per il file VCD.
    Esempio: AdventureWorksCommands.xml.
  3. Fare clic sul pulsante Aggiungi.
  4. In Esplora soluzioni, selezionare il file VCD.
  5. Nella finestra Proprietà, impostare l'azione Compilazione su Contenuto, quindi impostare Copia nella directory di output su Copia se più recente.

Modificare il file VCD

  1. Aggiungere un elemento VoiceCommands con un attributo xmlns che fa riferimento a https://schemas.microsoft.com/voicecommands/1.2.

  2. Per ogni lingua supportata dall'app, creare un elemento CommandSet che includa i comandi vocali supportati dall'app.
    Si è in grado di dichiarare più elementi CommandSet, ognuno con un attributo xml:lang diverso in modo che l'app possa essere usata in mercati diversi. Ad esempio, un'app per gli Stati Uniti potrebbe avere un valore CommandSet per l'inglese e un valore CommandSet per lo spagnolo.

    Importante

    Per attivare un'app e avviare un'azione usando un comando vocale, l'app deve registrare un file VCD che include un elemento CommandSet con una lingua corrispondente alla lingua indicata nel dispositivo dell'utente. La lingua di riconoscimento vocale si trova in Impostazioni > Sistema > Riconoscimento vocale > Lingua di riconoscimento.

  3. Aggiungere un elemento Command per ogni comando da supportare.
    Ogni Command dichiarato in un file VCD deve includere queste informazioni:

    • Un attributo Name che l'applicazione usa per identificare il comando vocale al runtime.

    • Un elemento Example che include una frase che descrive il modo in cui un utente richiama il comando. Cortana mostra l'esempio quando l'utente pronuncia What can I say?, Help o tocca Vedere altro.

    • Un elemento ListenFor che include le parole o le frasi che l'app riconosce come comando. Ogni elemento ListenFor può contenere riferimento a uno o più elementi PhraseList che contengono parole specifiche pertinenti al comando.

      Nota

      Gli elementi ListenFor non devono essere modificati a livello di codice. Tuttavia, gli elementi PhraseList associati agli elementi ListenFor possono essere modificati a livello di codice. Le applicazioni devono modificare il contenuto dell'elemento PhraseList al runtime in base al set di dati generato mentre l'utente usa l'app.

      Per altre informazioni, vedere Modificare in modo dinamico gli elenchi frasi VCD di Cortana.

    • Un elemento Feedback che include il testo che Cortana visualizza e pronunciare durante l'avvio dell'applicazione.

Un elemento Navigate indica che il comando vocale attiva l'app in primo piano. In questo esempio il comando showTripToDestination è un'attività in primo piano.

Un elemento VoiceCommandService indica che il comando vocale attiva l'app in background. Il valore dell'attributo Target di questo elemento deve corrispondere al valore dell'attributo Name dell'elemento uap:AppService nel file package.appxmanifest. In questo esempio, i comandi whenIsTripToDestination e cancelTripToDestination sono attività in background che specificano il nome del servizio app come AdventureWorksVoiceCommandService.

Per ulteriori dettagli, vedere il riferimento Elementi VCD e attributi v1.2.

Esempio: una porzione del file VCD che definisce i comandi vocali en-us per l'app 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>

Installare i comandi VCD

L'app deve essere eseguita una volta per installare il VCD.

Nota

I dati dei comandi vocali non vengono mantenuti tra le installazioni dell'app. Per assicurarsi che i dati dei comandi vocali per l'app rimangano intatti, è consigliabile inizializzare il file VCD ogni volta che l'app viene avviata o attivata o mantenere un'impostazione che indichi se il VCD è attualmente installato.

Nel file app.xaml.cs:

  1. Aggiungere la seguente direttiva using:

    using Windows.Storage;
    
  2. Contrassegnare il metodo OnLaunched con il tasto di modifica async.

    protected async override void OnLaunched(LaunchActivatedEventArgs e)
    
  3. Chiamare il metodo InstallCommandDefinitionsFromStorageFileAsync nel gestore OnLaunched per registrare i comandi vocali da riconoscere.
    Esempio: l'app Adventure Works definisce un oggetto StorageFile.
    Esempio: chiamare il metodo GetFileAsync per inizializzare l'oggetto StorageFile con il file AdventureWorksCommands.xml.
    L'oggetto StorageFile viene quindi passato al metodo InstallCommandDefinitionsFromStorageFileAsync.

    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());
     }
    

Gestire l'attivazione

Specificare la modalità di risposta dell'app alle attivazioni dei comandi vocali successive.

Nota

È necessario avviare l'app almeno una volta dopo l'installazione dei set di comandi vocali.

  1. Verificare che l'app è stata attivata da un comando vocale.

    Eseguire l'override dell'evento Application.OnActivated e verificare se IActivatedEventArgs.Kind è VoiceCommand.

  2. Determinare il nome del comando e ciò che si è pronunciato.

    Ottenere un riferimento a un oggetto VoiceCommandActivatedEventArgs da IActivatedEventArgs ed eseguire una query sulla proprietà Result per un oggetto SpeechRecognitionResult.

    Per determinare quanto detto dall'utente, verificare il valore di Text o le proprietà semantiche della frase riconosciuta nel dizionario SpeechRecognitionSemanticInterpretation.

  3. Eseguire l'azione appropriata nell'app, ad esempio navigare alla pagina desiderata.

    Nota

    Se è necessario fare riferimento al VCD, visitare la sezione Modificare il file VCD.

    Dopo aver ricevuto il risultato del riconoscimento vocale per il comando vocale, si ottiene il nome del comando dal primo valore della matrice RulePath. Poiché il file VCD definisce più comandi vocali possibili, è necessario verificare che il valore corrisponda ai nomi dei comandi nel VCD ed eseguire l'azione appropriata.

    L'azione più comune per un'applicazione consiste nel passare a una pagina con contenuto pertinente al contesto del comando vocale.
    Esempio: aprire la pagina TripPage e passare il valore del comando vocale, la modalità di input del comando e la frase di destinazione riconosciuta (se applicabile). In alternativa, l'app può inviare un parametro di navigazione a SpeechRecognitionResult quando si va alla pagina TripPage.

    Si può capire se il comando vocale che ha avviato l'app è stato pronunciato o se è stato digitato come testo, dal dizionario SpeechRecognitionSemanticInterpretation.Properties usando la chiave commandMode. Il valore della chiave sarà voice o text. Se il valore della chiave è voice, valutare di usare la sintesi vocale (Windows.Media.SpeechSynthesis) nell'app per fornire all'utente feedback vocale.

    Usare SpeechRecognitionSemanticInterpretation.Properties per capire il contenuto pronunciato nei vincoli PhraseList o PhraseTopic di un elemento ListenFor. La chiave del dizionario è il valore dell'attributo Label dell'elemento PhraseList o PhraseTopic. Esempio: il codice seguente per Come accedere al valore della 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();
    }
    

Gestire il comando vocale nel servizio app

Elaborare il comando vocale nel servizio app.

  1. Aggiungere le direttive using seguenti al file del servizio comandi vocali.
    Esempio: AdventureWorksVoiceCommandService.cs.

        using Windows.ApplicationModel.VoiceCommands;
        using Windows.ApplicationModel.Resources.Core;
        using Windows.ApplicationModel.AppService;
    
  2. Differire il servizio in modo che il servizio app non venga terminato durante la gestione del comando vocale.

  3. Verificare che l'attività in background sia in esecuzione come servizio app attivato da un comando vocale.

    1. Eseguire il cast di IBackgroundTaskInstance.TriggerDetails in Windows.ApplicationModel.AppService.AppServiceTriggerDetails.
    2. Verificare che IBackgroundTaskInstance.TriggerDetails.Name sia il nome del servizio app nel file Package.appxmanifest.
  4. Usare IBackgroundTaskInstance.TriggerDetails per creare un elemento VoiceCommandServiceConnection in Cortana per recuperare il comando vocale.

  5. Registrare un gestore dell'evento per VoiceCommandServiceConnection. VoiceCommandCompleted per ricevere una notifica quando il servizio app viene chiuso in seguito a una cancellazione utente.

  6. Registrare un gestore dell'evento per IBackgroundTaskInstance.Canceled per ricevere una notifica quando il servizio app viene chiuso in seguito a un errore imprevisto.

  7. Determinare il nome del comando e ciò che si è pronunciato.

    1. Usare la proprietà VoiceCommand.CommandName per determinare il nome del comando vocale.
    2. Per determinare quanto detto dall'utente, verificare il valore di Text o le proprietà semantiche della frase riconosciuta nel dizionario SpeechRecognitionSemanticInterpretation.
  8. Eseguire l'azione appropriata nel servizio app.

  9. Visualizzare e pronunciare il feedback al comando vocale usando Cortana.

    1. Determinare le stringhe che Cortana deve visualizzare e pronunciare all'utente in risposta al comando vocale e creare un oggetto VoiceCommandResponse. Per indicazioni su come selezionare le stringhe di feedback che Cortana deve visualizzare e pronunciare, vedere Linee guida sulla progettazione di Cortana.
    2. Usare l'istanza di VoiceCommandServiceConnection per segnalare lo stato o il completamento a Cortana chiamando ReportProgressAsync o ReportSuccessAsync con l'oggetto VoiceCommandServiceConnection.

    Nota

    Se è necessario fare riferimento al VCD, visitare la sezione Modificare il file 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);
        }
    }
    

Dopo l'attivazione, il servizio app ha 0,5 secondi per chiamare ReportSuccessAsync. Cortana mostra e pronuncia una stringa di feedback.

Nota

È possibile dichiarare una stringa Feedback nel file VCD. La stringa non condiziona il testo dell'interfaccia utente visualizzato nell'area di disegno di Cortana, ma solo il testo pronunciato da Cortana.

Se l'app richiede più di 0,5 secondi per effettuare la chiamata, Cortana inserisce una schermata di handoff, come illustrato di seguito. Cortana visualizza la schermata di handoff finché l'applicazione non chiama ReportSuccessAsync o per un massimo di 5 secondi. Se il servizio app non chiama ReportSuccessAsync o qualsiasi dei metodi VoiceCommandServiceConnection che forniscono a Cortana informazioni, l'utente riceve un messaggio di errore e il servizio app viene annullato.

Screenshot di Cortana e di una query di base con lo stato di avanzamento e le schermate dei risultati usando l'app AdventureWorks in background