Поделиться через


Активация приложения переднего плана с помощью голосовых команд в Кортане

Предупреждение

Эта функция больше не поддерживается с обновления Windows 10 за май 2020 г. (версия 2004, кодовое имя "20H1").

Сведения о том, как Кортана преобразует современные возможности для повышения производительности, см. в статье Кортана в Microsoft 365 .

Помимо использования голосовых команд в Кортане для доступа к системным функциям, вы также можете расширить Кортану функциями и функциями из приложения. С помощью голосовых команд приложение можно активировать на переднем плане и выполнить действие или команду в приложении.

Когда приложение обрабатывает голосовую команду на переднем плане, оно получает фокус, и Кортана закрывается. При желании вы можете активировать приложение и выполнить команду в качестве фоновой задачи. В этом случае Кортана сохраняет фокус, и ваше приложение возвращает все отзывы и результаты через холст Кортаны и голос Кортаны .

Голосовые команды, требующие дополнительного контекста или ввода пользователем (например, отправки сообщения определенному контакту), лучше всего обрабатывать в приложении переднего плана, в то время как основные команды (например, перечисление предстоящих поездок) можно обрабатывать в Кортане через фоновое приложение.

Если вы хотите активировать приложение в фоновом режиме с помощью голосовых команд, см. статью Активация фонового приложения в Кортане с помощью голосовых команд.

Примечание

Голосовая команда — это один речевой фрагмент с определенным намерением, определенный в файле определения голосовых команд (VCD), направленный на установленное приложение через Кортану.

VCD-файл определяет одну или несколько голосовых команд, каждая из которых имеет уникальное намерение.

Определения голосовых команд могут отличаться по сложности. Они могут поддерживать все, от одного ограниченного речевого фрагмента до коллекции более гибких высказываний на естественном языке, которые обозначают одно и то же намерение.

Чтобы продемонстрировать функции приложения переднего плана, мы будем использовать приложение для планирования поездок и управления ими с именем Adventure Works из примера голосовых команд Кортаны.

Чтобы создать новую поездку Adventure Works без Кортаны, пользователь запускает приложение и переходит на страницу Новая поездка . Чтобы просмотреть существующую поездку, пользователь запустит приложение, перейдите на страницу Предстоящие поездки и выберите поездку.

Используя голосовые команды через Кортану, пользователь может просто сказать "Adventure Works добавить поездку" или "Добавить поездку в Adventure Works", чтобы запустить приложение и перейти на страницу Новая поездка . В свою очередь, сказав "Adventure Works, show my trip to London" запустит приложение и перейдите на страницу сведений о поездке , показанную здесь.

Снимок экрана: кортана запускает приложение переднего плана

Ниже приведены основные шаги по добавлению функций голосовых команд и интеграции Кортаны с приложением с помощью голосового или клавиатурного ввода.

  1. Создайте VCD-файл. Это XML-документ, в котором определяются все произнесенные команды, которые пользователь может сказать для запуска действий или вызова команд при активации приложения. См. статью Элементы и атрибуты VCD версии 1.2.
  2. Зарегистрируйте наборы команд в VCD-файле при запуске приложения.
  3. Обработка голосовой команды активации, навигации в приложении и выполнения команды.

Совет

Предварительные требования

Если вы — начинающий разработчик приложений универсальной платформы Windows (UWP), прочитайте указанные ниже статьи, чтобы ознакомиться с описанными здесь технологиями.

Рекомендации по взаимодействию с пользователем

Полезные советы по разработке полезных и привлекательных приложений с поддержкой речи см. в статье Рекомендации по проектированию Кортаны для интеграции приложения с Кортаной и взаимодействие с речью .

Создание нового решения с помощью проекта в Visual Studio

  1. Запустите Microsoft Visual Studio 2015.

    Откроется начальная страница Visual Studio 2015.

  2. В меню Файл выберите Создать>Проект.

    Откроется диалоговое окно Создание проекта. В левой области диалогового окна можно выбрать тип отображаемых шаблонов.

  3. В области слева разверните узел Установленные > шаблоны > Visual C# > Windows, а затем выберите группу Универсальные шаблоны. В центральной области диалогового окна отображается список шаблонов проектов для приложений универсальная платформа Windows (UWP).

  4. В центральной области выберите шаблон Пустое приложение (универсальное приложение для Windows).

    Шаблон Пустое приложение создает минимальное приложение UWP, которое компилируется и выполняется, но не содержит элементов управления или данных пользовательского интерфейса. Вы добавите элементы управления в приложение в ходе работы с этим руководством.

  5. В текстовом поле Имя введите имя проекта. В этом примере мы используем AdventureWorks.

  6. Чтобы создать проект, нажмите кнопку ОК .

    Microsoft Visual Studio создает проект и отображает его в Обозреватель решений.

Добавление ресурсов изображений в проект и их указание в манифесте приложения

Приложения UWP могут автоматически выбирать наиболее подходящие изображения на основе определенных параметров и возможностей устройства (высокая контрастность, эффективные пиксели, языковой стандарт и т. д.). Все, что вам нужно сделать, это предоставить образы и убедиться, что вы используете соответствующее соглашение об именовании и организацию папок в проекте приложения для различных версий ресурсов. Если вы не предоставляете рекомендуемые версии ресурсов, могут возникнуть проблемы с доступностью, локализацией и качеством изображения в зависимости от предпочтений, возможностей пользователя, типа устройства и расположения.

Дополнительные сведения о ресурсах изображений для высокой контрастности и масштабируемых факторов см. в разделе Рекомендации по ресурсам плиток и значков.

Имена ресурсов используются с помощью квалификаторов. Квалификаторы ресурсов — это модификаторы папок и имен файлов, которые определяют контекст, в котором должна использоваться определенная версия ресурса.

Стандартное соглашение об именовании — foldername/qualifiername-value[_qualifiername-value]/filename.qualifiername-value[_qualifiername-value].ext. Например, images/logo.scale-100_contrast-white.png, на который можно ссылаться в коде, используя только корневую папку и имя файла: images/logo.png. См. раздел Присвоение имен ресурсам с помощью квалификаторов.

Рекомендуется пометить язык по умолчанию в файлах строковых ресурсов (например en-US\resources.resw, ) и коэффициент масштабирования по умолчанию для изображений (например logo.scale-100.png, ), даже если в настоящее время вы не планируете предоставлять локализованные или несколько ресурсов разрешения. Однако как минимум рекомендуется предоставить ресурсы для 100, 200 и 400 коэффициентов масштабирования.

Важно!

Значок приложения, используемый в области заголовка холста Кортаны , — это значок Square44x44Logo, указанный в файле Package.appxmanifest.

Создание VCD-файла

  1. В Visual Studio щелкните правой кнопкой мыши имя основного проекта и выберите Добавить > новый элемент. Добавьте XML-файл.
  2. Введите имя VCD-файла (в данном примере "AdventureWorksCommands.xml") и нажмите кнопку Добавить.
  3. В Обозреватель решений выберите VCD-файл.
  4. В окне Свойства установите для параметра Действие сборки значениеСодержимое, а затем для параметра Копировать в выходной каталог значение Копировать, если новее.

Изменение VCD-файла

Добавьте элемент VoiceCommands с атрибутом xmlns, указывающим на https://schemas.microsoft.com/voicecommands/1.2.

  1. Для каждого языка, поддерживаемого приложением, создайте элемент CommandSet , содержащий голосовые команды, поддерживаемые вашим приложением.

    Вы можете объявить несколько элементов CommandSet , каждый из которых имеет свой атрибут xml:lang , чтобы приложение использовалось на разных рынках. Например, приложение для США может иметь CommandSet для английского языка и CommandSet для испанского языка.

    Внимание!

    Чтобы активировать приложение и инициировать действие с помощью голосовой команды, приложение должно зарегистрировать VCD-файл, содержащий набор команд с языком, который соответствует языку речи, выбранному пользователем для устройства. Язык речи находится в разделе Параметры > Язык речи системы>.>

  2. Добавьте элемент Command для каждой команды, которую вы хотите поддерживать. Каждая команда , объявленная в VCD-файле , должна содержать следующие сведения:

    • Атрибут AppName , который приложение использует для идентификации голосовой команды во время выполнения.
    • Элемент Example , содержащий фразу, описывающую, как пользователь может вызвать команду. Кортана показывает этот пример, когда пользователь говорит "Что можно сказать?", "Справка" или нажимает кнопку Подробнее.
    • Элемент ListenFor , содержащий слова или фразы, которые приложение распознает как команду. Каждый элемент ListenFor может содержать ссылки на один или несколько элементов PhraseList , содержащих определенные слова, относящиеся к команде.

Примечание

Элементы ListenFor нельзя изменять программным способом. Однако элементы PhraseList , связанные с элементами ListenFor , можно изменять программными средствами. Приложения должны изменять содержимое PhraseList во время выполнения на основе набора данных, созданного при использовании приложения пользователем. См . раздел Динамическое изменение списков фраз VCD Кортаны.

Элемент Feedback , содержащий текст, который Кортана будет отображать и произносить при запуске приложения.

Элемент Navigate указывает, что голосовая команда активирует приложение на переднем плане. В этом примере showTripToDestination команда является задачей переднего плана.

Элемент VoiceCommandService указывает, что голосовая команда активирует приложение в фоновом режиме. Значение атрибута Target этого элемента должно совпадать со значением атрибута Name элемента uap:AppService в файле package.appxmanifest. В этом примере команды и cancelTripToDestination являются фоновыми задачами, whenIsTripToDestination указывающими имя службы приложений AdventureWorksVoiceCommandService.

Дополнительные сведения см. в справочнике по элементам и атрибутам VCD версии 1.2 .

Ниже приведена часть VCD-файла , в которой определяются голосовые команды en-us для приложения 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>

Установка команд VCD

Чтобы установить VCD, приложение должно запуститься один раз.

Примечание

Данные голосовых команд не сохраняются в разных установках приложений. Чтобы обеспечить сохранение данных голосовых команд для приложения, рассмотрите возможность инициализации VCD-файла при каждом запуске или активации приложения или оставьте параметр, указывающий, установлен ли VCD в данный момент.

В файле app.xaml.cs:

  1. Добавьте следующую директиву using:

    using Windows.Storage;
    
  2. Пометьте метод OnLaunched модификатором async.

    protected async override void OnLaunched(LaunchActivatedEventArgs e)
    
  3. Вызовите Метод InstallCommandDefinitionsFromStorageFileAsync в обработчике OnLaunched , чтобы зарегистрировать голосовые команды, которые система должна распознать.

В примере Adventure Works сначала определяется объект StorageFile .

Затем мы вызываем GetFileAsync , чтобы инициализировать его с помощью файла AdventureWorksCommands.xml.

Затем этот объект StorageFile передается в 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());
}

Обработка активации и выполнение голосовых команд

Укажите, как приложение реагирует на последующие активации голосовых команд (после запуска хотя бы один раз и установки наборов голосовых команд).

  1. Убедитесь, что приложение было активировано с помощью голосовой команды.

    Переопределите событие Application.OnActivated и проверка, является ли IActivatedEventArgs.Тип— VoiceCommand.

  2. Определите имя команды и то, что было произнесено.

    Получите ссылку на объект VoiceCommandActivatedEventArgs из IActivatedEventArgs и запросите свойство Result для объекта SpeechRecognitionResult .

    Чтобы определить, что сказал пользователь, проверка значение Text или семантические свойства распознанной фразы в словаре SpeechRecognitionSemanticInterpretation.

  3. Выполните соответствующее действие в приложении, например переход на нужную страницу.

В этом примере мы ссылаемся на VCD в шаге 3. Изменение VCD-файла.

Получив результат распознавания речи для голосовой команды, мы получаем имя команды из первого значения в массиве RulePath . Так как VCD-файл определяет несколько возможных голосовых команд, необходимо сравнить значение с именами команд в VCD и выполнить соответствующее действие.

Наиболее распространенным действием, которое может предпринять приложение, является переход на страницу с содержимым, соответствующим контексту голосовой команды. В этом примере мы переходим на страницу TripPage и передадим значение голосовой команды, способ ввода команды и распознаваемую фразу "назначение" (если применимо). Кроме того, приложение может отправить параметр навигации в SpeechRecognitionResult при переходе на страницу.

Вы можете узнать, была ли голосовая команда, которая запустила приложение, на самом деле произнесено, или она была введена в виде текста, из словаря SpeechRecognitionSemanticInterpretation.Properties с помощью клавиши commandMode . Значение этого ключа будет иметь значение "voice" или "text". Если значение ключа — "голос", рассмотрите возможность использования синтеза речи (Windows.Media.SpeechSynthesis) в приложении для предоставления пользователю устной обратной связи.

Используйте SpeechRecognitionSemanticInterpretation.Properties , чтобы узнать содержимое, произнесенное в ограничениях PhraseList или PhraseTopic элемента ListenFor . Ключ словаря — это значение атрибута Label элемента PhraseList или PhraseTopic . Здесь мы покажем, как получить доступ к значению фразы {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();
}