Aktivieren einer Vordergrund-App mit Sprachbefehlen über Cortana

Warnung

Diese Funktion wird seit dem Windows 10 Mai 2020 Update (Version 2004, Codename „20H1“) nicht mehr unterstützt.

Unter Cortana in Microsoft 365 erfahren Sie, wie Cortana die moderne Produktivität verändert.

Zusätzlich zur Verwendung von Sprachbefehlen in Cortana für den Zugriff auf Systemfeatures können Sie Cortana auch mit Features und Funktionen aus Ihrer App erweitern. Mithilfe von Sprachbefehlen kann Ihre App im Vordergrund und einer Aktion oder eines Befehls aktiviert werden, die in der App ausgeführt wird.

Wenn eine App einen Sprachbefehl im Vordergrund verarbeitet, wird der Fokus verwendet, und Cortana wird geschlossen. Wenn Sie es vorziehen, können Sie Ihre App aktivieren und einen Befehl als Hintergrundaufgabe ausführen. In diesem Fall behält Cortana den Fokus bei, und Ihre App gibt alle Feedback und Ergebnisse über die Cortana-Canvas und die Cortana-Stimme zurück.

Sprachbefehle, die zusätzlichen Kontext oder Benutzereingaben erfordern (z. B. das Senden einer Nachricht an einen bestimmten Kontakt), werden in einer Vordergrund-App am besten behandelt, während grundlegende Befehle (z. B. das Auflisten anstehender Reisen) in Cortana über eine Hintergrund-App verarbeitet werden können.

Wenn Sie eine App im Hintergrund mithilfe von Sprachbefehlen aktivieren möchten, lesen Sie " Aktivieren einer Hintergrund-App in Cortana mithilfe von Sprachbefehlen".

Hinweis

Ein Sprachbefehl ist eine einzelne Äußerung mit einer bestimmten Absicht, die in einer VCD-Datei (Voice Command Definition) definiert ist, die an eine installierte App über Cortana gerichtet ist.

Eine VCD-Datei definiert einen oder mehrere Sprachbefehle, jeweils mit einer eindeutigen Absicht.

Sprachbefehlsdefinitionen können in der Komplexität variieren. Sie können alles von einer einzigen, eingeschränkten Äußerung bis zu einer Sammlung flexiblerer, natürlicher Sprache Ausdrücke unterstützen, die denselben Zweck bezeichnen.

Um Vordergrund-App-Features zu veranschaulichen, verwenden wir eine Reiseplanungs- und Verwaltungs-App namens Adventure Works aus dem Cortana-Sprachbefehlsbeispiel.

Um eine neue Adventure Works-Reise ohne Cortana zu erstellen, startet ein Benutzer die App und navigiert zur Seite "Neue Reise ". Um eine vorhandene Reise anzuzeigen, startet ein Benutzer die App, navigiert zur Seite "Anstehende Reisen ", und wählen Sie die Reise aus.

Mithilfe von Sprachbefehlen über Cortana kann der Benutzer stattdessen einfach "Adventure Works eine Reise hinzufügen" oder "Eine Reise auf Adventure Works hinzufügen" sagen, um die App zu starten und zur Seite "Neue Reise" zu navigieren. Wenn Sie "Adventure Works, meine Reise nach London anzeigen" sagen, wird die App gestartet und zur Detailseite "Reise " navigiert, die hier gezeigt wird.

Screenshot der Cortana-Start-Vordergrund-App

Dies sind die grundlegenden Schritte zum Hinzufügen von Sprachbefehlsfunktionen und die Integration von Cortana in Ihre App mithilfe von Sprach- oder Tastatureingaben:

  1. Erstellen Sie eine VCD-Datei. Dies ist ein XML-Dokument, das alle gesprochenen Befehle definiert, die der Benutzer sagen kann, um Aktionen zu initiieren oder Befehle aufzurufen, wenn Sie Ihre App aktivieren. Siehe VCD-Elemente und Attribute v1.2.
  2. Registrieren Sie die Befehlssätze in der VCD-Datei, wenn die App gestartet wird.
  3. Behandeln Sie den Aktivierungsbefehl, die Navigation innerhalb der App und die Ausführung des Befehls.

Tipp

Voraussetzungen

Wenn Sie noch nicht mit der Entwicklung von Universelle Windows-Plattform(UWP)-Apps vertraut sind, schauen Sie sich diese Themen an, um sich mit den hier erläuterten Technologien vertraut zu machen.

Richtlinien für die Benutzeroberfläche

Informationen zum Integrieren Ihrer App in Cortana- und Sprachinteraktionen finden Sie in den Entwurfsrichtlinien für Cortana und Spracherkennung.

Erstellen einer neuen Projektmappe mit Projekt in Visual Studio

  1. Starten Sie Microsoft Visual Studio 2015.

    Die Visual Studio 2015-Startseite wird angezeigt.

  2. Wählen Sie im Menü Datei die Option Neu>Projekt.

    Das Dialogfeld Neues Projekt wird geöffnet. Im linken Bereich des Dialogfelds können Sie den Typ der anzuzeigenden Vorlagen auswählen.

  3. Erweitern Sie im linken Bereich installierte > Vorlagen > Visual C# > Windows, und wählen Sie dann die Gruppe " Universelle Vorlagen" aus. Im mittleren Bereich des Dialogfelds wird eine Liste der Projektvorlagen für Universelle Windows-Plattform-Apps (UWP) angezeigt.

  4. Wählen Sie im mittleren Bereich die Vorlage "Leere App" (Universelle Windows-App) aus.

    Die Vorlage "Leere App " erstellt eine minimale UWP-App, die kompiliert und ausgeführt wird, enthält jedoch keine Steuerelemente oder Daten der Benutzeroberfläche. Im Verlauf dieses Lernprogramms fügen Sie der App Steuerelemente hinzu.

  5. Geben Sie im Textfeld "Name " den Projektnamen ein. In diesem Beispiel verwenden wir "AdventureWorks".

  6. Klicken Sie auf OK, um das Projekt zu erstellen.

    Microsoft Visual Studio erstellt Ihr Projekt und zeigt es im Projektmappen-Explorer an.

Hinzufügen von Bildressourcen zum Projekt und Angeben im App-Manifest

UWP-Apps können automatisch die am besten geeigneten Bilder basierend auf bestimmten Einstellungen und Gerätefunktionen auswählen (hoher Kontrast, effektive Pixel, Gebietsschema usw.). Sie müssen lediglich die Bilder bereitstellen und sicherstellen, dass Sie die entsprechende Benennungskonvention und Ordnerorganisation innerhalb des App-Projekts für die verschiedenen Ressourcenversionen verwenden. Wenn Sie nicht die empfohlenen Ressourcenversionen, Barrierefreiheit, Lokalisierung und Bildqualität bereitstellen, kann abhängig von den Vorlieben, Fähigkeiten, Gerätetyp und Standort des Benutzers leiden.

Weitere Details zu Bildressourcen für hohe Kontrast- und Skalierungsfaktoren finden Sie in den Richtlinien für Kachel- und Symbolressourcen.

Sie benennen Ressourcen mithilfe von Qualifizierern. Ressourcenqualifizierer sind Ordner- und Dateinamenmodifizierer, die den Kontext identifizieren, in dem eine bestimmte Version einer Ressource verwendet werden soll.

Die Standardbenennungskonvention lautet foldername/qualifiername-value[_qualifiername-value]/filename.qualifiername-value[_qualifiername-value].ext. Beispiel: , images/logo.scale-100_contrast-white.pngdie im Code mit nur dem Stammordner und dem Dateinamen bezeichnet werden kann: images/logo.png. Informationen zum Benennen von Ressourcen mithilfe von Qualifizierern.

Es wird empfohlen, die Standardsprache für Zeichenfolgenressourcendateien (z en-US\resources.resw. B. ) und den Standardskalierungsfaktor für Bilder (z logo.scale-100.png. B. ) zu markieren, auch wenn Sie derzeit keine lokalisierten oder mehrere Auflösungsressourcen bereitstellen möchten. Es wird jedoch empfohlen, Ressourcen für 100, 200 und 400 Skalierungsfaktoren bereitzustellen.

Wichtig

Das app-Symbol, das im Titelbereich der Cortana-Canvas verwendet wird, ist das in der Datei "Package.appxmanifest" angegebene Symbol "Square44x44Logo".

Erstellen einer VCD-Datei

  1. Klicken Sie in Visual Studio mit der rechten Maustaste auf ihren primären Projektnamen, und wählen Sie "Neues Element hinzufügen" > aus. Fügen Sie eine XML-Datei hinzu.
  2. Geben Sie einen Namen für die VCD-Datei ein (z. B. "AdventureWorksCommands.xml"), und klicken Sie auf "Hinzufügen".
  3. Wählen Sie in Projektmappen-Explorer die VCD-Datei aus.
  4. Legen Sie im Fenster "Eigenschaften" die Buildaktion auf "Inhalt" fest, und legen Sie dann "Kopieren" auf "Ausgabeverzeichnis" auf "Kopieren" fest, wenn neuer.

Bearbeiten der VCD-Datei

Fügen Sie ein VoiceCommands-Element mit einem xmlns-Attribut hinzu, das auf https://schemas.microsoft.com/voicecommands/1.2.

  1. Erstellen Sie für jede sprache, die von Ihrer App unterstützt wird, ein CommandSet-Element , das die sprachbefehle enthält, die von Ihrer App unterstützt werden.

    Sie können mehrere CommandSet-Elemente deklarieren, jeweils mit einem anderen xml:lang-Attribut, damit Ihre App in verschiedenen Märkten verwendet werden kann. Beispielsweise kann eine App für die USA über ein CommandSet für Englisch und ein CommandSet für Spanisch verfügen.

    Achtung

    Um eine App zu aktivieren und eine Aktion mithilfe eines Sprachbefehls zu initiieren, muss die App eine VCD-Datei registrieren, die ein CommandSet mit einer Sprache enthält, die der vom Benutzer für sein Gerät ausgewählten Sprachsprache entspricht. Die Sprache befindet sich in der Spracherkennungssprache "Einstellungen>">>.

  2. Fügen Sie ein Command-Element für jeden Befehl hinzu, den Sie unterstützen möchten. Jeder in einer VCD-Datei deklarierte Befehl muss die folgenden Informationen enthalten:

    • Ein AppName-Attribut , das Ihre Anwendung zum Identifizieren des Sprachbefehls zur Laufzeit verwendet.
    • Ein Example-Element, das einen Ausdruck enthält, der beschreibt, wie ein Benutzer den Befehl aufrufen kann. Cortana zeigt dieses Beispiel an, wenn der Benutzer "Was kann ich sagen?", "Hilfe" sagen oder auf "Mehr anzeigen" tippen.
    • Ein ListenFor-Element, das die Wörter oder Ausdrücke enthält, die ihre App als Befehl erkennt. Jedes ListenFor-Element kann Verweise auf ein oder mehrere PhraseList-Elemente enthalten, die bestimmte Wörter enthalten, die für den Befehl relevant sind.

Hinweis

ListenFor-Elemente können nicht programmgesteuert geändert werden. PhraseList-Elemente, die ListenFor-Elementen zugeordnet sind, können jedoch programmgesteuert geändert werden. Anwendungen sollten den Inhalt der PhraseList zur Laufzeit basierend auf dem von dem Benutzer generierten Dataset ändern. Siehe Dynamisches Ändern von Cortana VCD-Begriffslisten.

Ein Feedback-Element , das den Text enthält, der Cortana anzeigt und spricht, während die Anwendung gestartet wird.

Ein Navigate-Element gibt an, dass der Sprachbefehl die App im Vordergrund aktiviert. In diesem Beispiel ist der showTripToDestination Befehl eine Vordergrundaufgabe.

Ein VoiceCommandService-Element gibt an, dass der Sprachbefehl die App im Hintergrund aktiviert. Der Wert des Target-Attributs dieses Elements sollte mit dem Wert des Namens-Attributs des uap:AppService-Elements in der Datei "package.appxmanifest" übereinstimmen. In diesem Beispiel sind die whenIsTripToDestination Und cancelTripToDestination Befehle Hintergrundaufgaben, die den Namen des App-Diensts als "AdventureWorksVoiceCommandService" angeben.

Weitere Details finden Sie in der VCD-Element- und Attributreferenz v1.2.

Hier ist ein Teil der VCD-Datei , der die en-us-Sprachbefehle für die Adventure Works-App definiert.

<?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>

Installieren der VCD-Befehle

Ihre App muss einmal ausgeführt werden, um die VCD zu installieren.

Hinweis

Sprachbefehlsdaten werden nicht für App-Installationen beibehalten. Um sicherzustellen, dass die Sprachbefehlsdaten für Ihre App intakt bleiben, sollten Sie die VCD-Datei jedes Mal initialisieren, wenn die App gestartet oder aktiviert wird, oder eine Einstellung beibehalten, die angibt, ob die VCD derzeit installiert ist.

In der Datei "app.xaml.cs":

  1. Fügen Sie die folgende Using-Direktive hinzu:

    using Windows.Storage;
    
  2. Markieren Sie die "OnLaunched"-Methode mit dem asynchronen Modifizierer.

    protected async override void OnLaunched(LaunchActivatedEventArgs e)
    
  3. Rufen Sie InstallCommandDefinitionsFromStorageFileAsync im OnLaunched-Handler auf, um die Sprachbefehle zu registrieren, die vom System erkannt werden sollen.

Im Adventure Works-Beispiel definieren wir zunächst ein StorageFile-Objekt.

Anschließend rufen wir GetFileAsync auf, um sie mit unserer Datei "AdventureWorksCommands.xml" zu initialisieren.

Dieses StorageFile-Objekt wird dann an InstallCommandDefinitionsFromStorageFileAsync übergeben.

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

Behandeln der Aktivierung und Ausführen von Sprachbefehlen

Geben Sie an, wie Ihre App auf nachfolgende Sprachbefehlsaktivierungen reagiert (nachdem sie mindestens einmal gestartet wurde und die Sprachbefehlssätze installiert wurden).

  1. Vergewissern Sie sich, dass Ihre App durch einen Sprachbefehl aktiviert wurde.

    Überschreiben Sie das Application.OnActivated-Ereignis, und überprüfen Sie, ob IActivatedEventArgs.Kind ist VoiceCommand.

  2. Bestimmen Sie den Namen des Befehls und was gesprochen wurde.

    Rufen Sie einen Verweis auf ein VoiceCommandActivatedEventArgs -Objekt aus dem IActivatedEventArgs-Objekt ab, und fragen Sie die Result-Eigenschaft für ein SpeechRecognitionResult -Objekt ab.

    Um zu bestimmen, was der Benutzer sagte, überprüfen Sie den Wert von Text oder die semantischen Eigenschaften des erkannten Ausdrucks im SpeechRecognitionSemanticInterpretation-Wörterbuch.

  3. Ergreifen Sie die entsprechende Aktion in Ihrer App, z. B. das Navigieren zur gewünschten Seite.

In diesem Beispiel verweisen wir auf die VCD in Schritt 3: Bearbeiten der VCD-Datei.

Sobald das Spracherkennungsergebnis für den Sprachbefehl abgerufen wurde, wird der Befehlsname aus dem ersten Wert im RulePath-Array abgerufen. Da die VCD-Datei mehrere mögliche Sprachbefehle definiert hat, müssen wir den Wert mit den Befehlsnamen in der VCD vergleichen und die entsprechende Aktion ausführen.

Die häufigste Aktion, die eine Anwendung ausführen kann, besteht darin, zu einer Seite zu navigieren, die für den Kontext des Sprachbefehls relevant ist. In diesem Beispiel navigieren wir zu einer TripPage-Seite und übergeben den Wert des Sprachbefehls, die Eingabe des Befehls und den erkannten "Ziel"-Ausdruck (falls zutreffend). Alternativ kann die App beim Navigieren zur Seite einen Navigationsparameter an das SpeechRecognitionResult senden.

Sie können herausfinden, ob der Sprachbefehl, der Ihre App gestartet hat, tatsächlich gesprochen wurde oder ob sie als Text eingegeben wurde, aus dem Wörterbuch SpeechRecognitionSemanticInterpretation.Properties mithilfe der Befehlstaste. Der Wert dieser Taste lautet entweder "Voice" oder "text". Wenn der Wert des Schlüssels "Stimme" lautet, sollten Sie die Verwendung der Sprachsynthese (Windows.Media.SpeechSynthesis) in Ihrer App in Betracht ziehen, um dem Benutzer gesprochenes Feedback zu geben.

Verwenden Sie die SpeechRecognitionSemanticInterpretation.Properties, um den Inhalt zu ermitteln, der in der PhraseList- oder PhraseTopic-Einschränkung eines ListenFor-Elements gesprochen wird. Der Wörterbuchschlüssel ist der Wert des Label-Attributs des PhraseList- oder PhraseTopic-Elements. Hier erfahren Sie, wie Sie auf den Wert des {destination}-Ausdrucks zugreifen.

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