Condividi tramite


Attivare un'app in primo piano con comandi vocali tramite Cortana

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 le funzionalità dell'app. Usando i comandi vocali, è possibile attivare l'app in primo piano ed eseguire un'azione o un comando all'interno dell'app.

Quando un'app gestisce un comando vocale in primo piano, assume lo stato attivo e Cortana viene ignorato. Se si preferisce, è possibile attivare l'app ed eseguire un comando come attività in background. In questo caso, Cortana mantiene lo stato attivo e l'app restituisce il feedback e i risultati tramite l'area di disegno di Cortana e la voce di Cortana.

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 background usando i comandi vocali, vedere Attivare un'app in background in Cortana usando i comandi vocali.

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à.

Per illustrare le funzionalità dell'app in primo piano, si userà un'app di pianificazione e gestione dei viaggi di nome Adventure Works tratta dall'esempio di comando vocale di Cortana.

Per creare un nuovo viaggio Adventure Works senza Cortana, un utente deve avviare l'app e andare alla pagina Nuovo viaggio. Per visualizzare un viaggio esistente, un utente avvia l'app, va alla pagina Prossimi viaggi e seleziona il viaggio.

Usando i comandi vocali tramite Cortana, l'utente può semplicemente pronunciare "Adventure Works aggiungi un viaggio" o "Aggiungi un viaggio su Adventure Works" per avviare l'app e andare alla pagina Nuovo viaggio. A sua volta, la frase pronunciata "Adventure Works, mostrami il mio viaggio a Londra" avvierà l'app e andrà alla pagina dei dettagli Viaggio mostrata qui.

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

Questi sono i passaggi di base per aggiungere funzionalità di comando vocale e integrare Cortana con l'app usando l'input vocale o da tastiera:

  1. Creare un file VCD. Si tratta di 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.
  2. Registrare i set di comandi nel file VCD all'avvio dell'app.
  3. Gestire l'attivazione tramite comando vocale, la navigazione all'interno dell'app e l'esecuzione del comando.

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 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, ma non contiene dati o controlli dell'interfaccia utente. È possibile aggiungere controlli all'app nel corso di questa esercitazione.

  5. Nella casella di testo Nome digitare il nome del progetto. Per questo esempio si userà "AdventureWorks".

  6. Fare clic su OK per creare il progetto.

    Microsoft Visual Studio crea il progetto e lo visualizza in Esplora soluzioni.

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

Le app UWP possono selezionare automaticamente le immagini più appropriate in base a funzionalità del dispositivo e a impostazioni specifiche (contrasto elevato, pixel effettivi, impostazioni locali e così via). È sufficiente 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'accessibilità, la localizzazione e la qualità dell'immagine possono risentirne a seconda delle preferenze, delle capacità, del tipo di dispositivo e della posizione dell'utente.

Per altri dettagli sulle risorse delle immagini per fattori quali contrasto elevato e scala, vedere Linee guida per le risorse riquadri e icone.

Assegnare un nome 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. Ad esempio, images/logo.scale-100_contrast-white.png, a cui è possibile fare riferimento nel codice usando solo la cartella radice e il nome file: images/logo.png. Vedere Come assegnare nomi alle risorse usando i qualificatori.

Si 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, si 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".

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 (per questo esempio "AdventureWorksCommands.xml"), quindi fare clic su Aggiungi.
  3. In Esplora soluzioni, selezionare il file VCD.
  4. 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

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

  1. Per ogni lingua supportata dall'app, creare un elemento CommandSet che contenga i comandi vocali supportati dall'app.

    È possibile dichiarare più elementi CommandSet, ognuno con un attributo xml:lang diverso in modo che l'app venga usato 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.

    Attenzione

    Per attivare un'app e avviare un'azione usando un comando vocale, l'app deve registrare un file VCD contenente un oggetto CommandSet con una lingua corrispondente alla lingua di riconoscimento vocale selezionata dall'utente per il dispositivo. La lingua di riconoscimento vocale si trova in Impostazioni > Sistema > Riconoscimento vocale > Lingua di riconoscimento.

  2. Aggiungere un elemento Command per ogni comando da supportare. Ogni elemento Command dichiarato in un file VCD deve includere le seguenti informazioni:

    • Un attributo AppName che l'applicazione usa per identificare il comando vocale al runtime.
    • Un elemento Example che contiene una frase che descrive il modo in cui un utente può richiamare il comando. Cortana mostra questo esempio quando l'utente pronuncia la frase "Cosa posso dire?", "Aiuto" o tocca Altre informazioni.
    • Un elemento ListenFor che contiene le parole o le frasi riconosciute dall'app come comando. Ogni elemento ListenFor può contenere riferimenti a uno o più elementi PhraseList che contengono parole specifiche pertinenti al comando.

Nota

Gli elementi ListenFor non possono essere modificati a livello di codice. Tuttavia, gli elementi PhraseList associati a 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. Vedere Modificare in modo dinamico gli elenchi frasi VCD di Cortana.

Un elemento Feedback che contiene il testo che Cortana deve visualizzare e pronunciare all'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.

Ecco una parte 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 InstallCommandDefinitionsFromStorageFileAsync nel gestore OnLaunched per registrare i comandi vocali che il sistema dovrebbe riconoscere.

Nell'esempio Adventure Works si definisce prima un oggetto StorageFile.

Si chiama quindi GetFileAsync per inizializzarlo con il file "AdventureWorksCommands.xml".

Questo oggetto StorageFile viene quindi passato a 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 ed eseguire comandi vocali

Specificare il modo in cui l'app risponde alle attivazioni dei comandi vocali successive (dopo che è stata avviata almeno una volta e i set di comandi vocali sono stati installati).

  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.

Per questo esempio, si fa riferimento al VCD nel passaggio 3: Modificare il file VCD.

Dopo aver ottenuto il risultato del riconoscimento vocale per il comando vocale, si ottiene il nome del comando dal primo valore nella matrice RulePath. Poiché il file VCD ha definito più di un possibile comando vocale, è necessario confrontare il valore ai nomi dei comandi nel VCD ed eseguire l'azione appropriata.

L'azione più comune per un'applicazione consiste nel navigare a una pagina con contenuto pertinente al contesto del comando vocale. Per questo esempio, si passa a una pagina TripPage e si passa il valore del comando vocale, il modo in cui il comando è stato immesso e la frase di "destinazione" riconosciuta (se applicabile). In alternativa, l'app può inviare un parametro di navigazione a SpeechRecognitionResult quando si naviga alla pagina.

È possibile capire se il comando vocale che ha avviato l'app è stata pronunciata o se è stato digitato come testo, dal dizionario SpeechRecognitionSemanticInterpretation.Properties usando la chiave commandMode. Il valore di quella chiave sarà "voce" o "testo". Se il valore della chiave è "voce", valutare la possibilità di usare la sintesi vocale (Windows.Media.SpeechSynthesis) nell'app per fornire all'utente feedback pronunciato.

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. Qui viene illustrato 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 can represent many different activation types. 
        // Cast it so we can get the parameters we care about 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 we can't determine what page to launch, go to the default entry point.
                navigationToPageType = typeof(View.TripListView);
                break;
        }
    }
    // Protocol activation occurs when a card is clicked within Cortana (using a background task).
    else if (args.Kind == ActivationKind.Protocol)
    {
        // Extract the launch context. In this case, we're just using 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. We let the destination page check if the 
        // destination trip still exists, and navigate back to the trip list if it doesn't.
        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 we were launched via any other mechanism, fall back to the main page view.
        // Otherwise, we'll hang 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 we're expecting 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();
}