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


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

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

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

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

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

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

Примечание.

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

Файл VCD определяет одну или несколько голосовых команд с уникальным намерением.

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

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

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

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

Используя голосовые команды через Кортана для запуска приложения в фоновом режиме, пользователь может просто сказать. Adventure Works, when is my trip to Las Vegas? Приложение обрабатывает команду, и Кортана отображает результаты вместе со значком приложения и другими сведениями о приложении, если они указаны.

Снимок экрана: Кортана с основным запросом и результатом экрана с помощью приложения AdventureWorks в фоновом режиме

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

  1. Создайте службу приложений (см. Раздел Windows.ApplicationModel.AppService), которая Кортана вызывается в фоновом режиме.
  2. Создайте VCD-файл. VCD-файл — это XML-документ, определяющий все произнесенные команды, которые пользователь может сказать инициировать действия или вызывать команды при активации приложения. См . элементы и атрибуты VCD версии 1.2.
  3. Зарегистрируйте наборы команд в VCD-файле при запуске приложения.
  4. Обработка фоновой активации службы приложений и выполнения голосовой команды.
  5. Отображайте и произнесите соответствующие отзывы о голосовой команде в Кортаны.

Совет

Необходимые условия

Если вы не знакомы с разработкой приложений универсальная платформа 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 должны автоматически выбирать наиболее подходящие изображения. Выбор основан на определенных параметрах и возможностях устройства (высокая контрастность, эффективные пиксели, языковой стандарт и т. д.). Необходимо предоставить изображения и убедиться, что для различных версий ресурсов используется соответствующее соглашение об именовании и организация папок в проекте приложения.
Если вы не предоставляете рекомендуемые версии ресурсов, взаимодействие с пользователем может страдать следующим образом.

  • Специальные возможности
  • Локализация
  • Качество изображения
    Версии ресурсов используются для адаптации следующих изменений в пользовательском интерфейсе.
  • Настройки пользователя
  • Способности
  • Тип устройства
  • Расположение

Дополнительные сведения о ресурсах изображений для факторов высокой контрастности и масштабирования см. на странице "Рекомендации по ресурсам плиток и значков", расположенной на msdn.microsoft.com/windows/uwp/controls-and-patterns/tiles-and-notifications-app-assets.

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

Стандартное соглашение об именовании .foldername/qualifiername-value[_qualifiername-value]/filename.qualifiername-value[_qualifiername-value].ext
Пример: images/logo.scale-100_contrast-white.pngкод может ссылаться только на корневую папку и имя файла: images/logo.png
Дополнительные сведения см. на странице "Как именовать ресурсы с помощью квалификаторов", расположенной на msdn.microsoft.com/library/windows/apps/xaml/hh965324.aspx.

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

Внимание

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

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

Плитка содержимого не проверяется, пока объект VoiceCommandResponse не передается в класс VoiceCommandServiceConnection. Если передать объект VoiceCommandResponse в Кортана, который включает плитку содержимого с изображением, которое не соответствует этим соотношениям размера, может возникнуть исключение. 

Пример. Приложение Adventure Works (VoiceCommandService\\AdventureWorksVoiceCommandService.cs) задает простой серый квадрат (GreyTile.png) в классе VoiceCommandContentTile с помощью шаблона плитки TitleWith68x68IconAndText. Варианты логотипа находятся VoiceCommandService\\Imagesи извлекаются с помощью метода GetFileFromApplicationUriAsync .

var destinationTile = new VoiceCommandContentTile();  

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

Создание проекта Служба приложений

  1. Щелкните правой кнопкой мыши имя решения и выберите новый > проект.

  2. В разделе "Установленные > шаблоны > Visual C# Windows > Universal" > выберите компонент среда выполнения Windows. Компонент среда выполнения Windows — это компонент, реализующий службу приложений (Windows.ApplicationModel.AppService).

  3. Введите имя проекта и нажмите кнопку "ОК ".
    Пример: VoiceCommandService.

  4. В Обозреватель решений выберите проект и переименуйте VoiceCommandService Class1.cs файл, созданный Visual Studio. Пример: используетСя AdventureWorksVoiceCommandService.csAdventure Works.

  5. Нажмите кнопку "Да"; если вы хотите переименовать все вхожденияClass1.cs.

  6. В файле AdventureWorksVoiceCommandService.cs:

    1. Добавьте следующую директиву using.
      using Windows.ApplicationModel.Background;
    2. При создании проекта имя проекта используется в качестве корневого пространства имен по умолчанию во всех файлах. Переименуйте пространство имен, чтобы вложить код службы приложений в основной проект. Пример: namespace AdventureWorks.VoiceCommands.
    3. Щелкните правой кнопкой мыши имя проекта службы приложений в Обозреватель решений и выберите "Свойства".
    4. На вкладке "Библиотека" обновите поле пространства имен по умолчанию с таким же значением.
      Например, AdventureWorks.VoiceCommands.
    5. Создайте новый класс, реализующий интерфейс IBackgroundTask . Для этого класса требуется метод Run , который является точкой входа, когда Кортана распознает голосовую команду.

    Пример. Базовый класс фоновой задачи из приложения Adventure Works .

    Примечание.

    Сам класс фоновой задачи, а также все классы в фоновом проекте задачи должны быть запечатаны общедоступными классами.

    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. Объявите фоновую задачу как appService в манифесте приложения.

    1. В Обозреватель решений щелкните файл правой Package.appxmanifest кнопкой мыши и выберите "Просмотреть код".
    2. Найдите элемент Application.
    3. Extensions Добавьте элемент в Application элемент.
    4. Добавьте элемент uap:Extension в элемент Extensions.
    5. Category Добавьте атрибут в uap:Extension элемент и задайте значение атрибута Category windows.appService.
    6. EntryPoint Добавьте атрибут в uap: Extension элемент и задайте для EntryPoint атрибута имя класса, реализующегоIBackgroundTask.
      Пример: AdventureWorks.VoiceCommands.AdventureWorksVoiceCommandService.
    7. Добавьте элемент uap:AppService в элемент uap:Extension.
    8. Name Добавьте атрибут в uap:AppService элемент и задайте для этого атрибута Name имя службы приложений.AdventureWorksVoiceCommandService
    9. Добавьте второй uap:Extension элемент в Extensions элемент.
    10. Category Добавьте атрибут в этот uap:Extension элемент и задайте значение атрибута Category windows.personalAssistantLaunch.

    Пример: манифест из приложения 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. Добавьте этот проект службы приложений в качестве ссылки в основном проекте.

    1. Щелкните правой кнопкой мыши ссылки.
    2. Выберите " Добавить ссылку...".
    3. В диалоговом окне "Диспетчер ссылок" разверните "Проекты" и выберите проект службы приложений.
    4. Нажмите кнопку "ОК ".

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

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

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

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

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

    Внимание

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

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

    • Атрибут Name , который используется приложением для идентификации голосовой команды во время выполнения.

    • Элемент Example , содержащий фразу, описывающую вызов команды пользователем. Кортана показывает пример, когда пользователь говоритWhat can I say?, Helpили касается дополнительных сведений.

    • Элемент ListenFor , содержащий слова или фразы, которые приложение распознает как команду. Каждый ListenFor элемент может содержать ссылки на один или несколько PhraseList элементов, содержащих определенные слова, относящиеся к команде.

      Примечание.

      ListenFor элементы не должны быть программным образом изменены. Однако элементы, связанные с ListenFor элементами, PhraseList могут быть программно изменены. Приложения должны изменять содержимое PhraseList элемента во время выполнения на основе набора данных, созданного при использовании приложения.

      Дополнительные сведения см. в статье Динамическое изменение списков фраз Кортаны VCD.

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

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

Элемент VoiceCommandService указывает, что голосовая команда активирует приложение в фоновом режиме. Значение атрибута этого элемента должно соответствовать значению Target Name атрибута uap:AppService элемента в файле package.appxmanifest. В этом примере whenIsTripToDestination cancelTripToDestination команды — это фоновые задачи, которые указывают имя службы приложений как 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 модификатора.

    protected async override void OnLaunched(LaunchActivatedEventArgs e)
    
  3. InstallCommandDefinitionsFromStorageFileAsync Вызовите метод в обработчикеOnLaunched, чтобы зарегистрировать голосовые команды, которые должны быть распознаны.
    Пример. Приложение Adventure Works определяет StorageFile объект.
    Пример. Вызов GetFileAsync метода для инициализации StorageFile объекта с 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 объекта.

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

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

    Примечание.

    Если вам нужно обратиться к VCD, перейдите в раздел "Изменить файл VCD ".

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

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

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

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

Обработка голосовой команды в Служба приложений

Обработайте голосовую команду в службе приложений.

  1. Добавьте следующие директивы с помощью в файл службы голосовой команды.
    Пример: AdventureWorksVoiceCommandService.cs.

        using Windows.ApplicationModel.VoiceCommands;
        using Windows.ApplicationModel.Resources.Core;
        using Windows.ApplicationModel.AppService;
    
  2. Примите отсрочку службы, чтобы служба приложений не была завершена при обработке голосовой команды.

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

    1. Приведение IBackgroundTaskInstance.TriggerDetails к Windows.ApplicationModel.AppService.AppServiceTriggerDetails.
    2. Убедитесь, что IBackgroundTaskInstance.TriggerDetails.Name — это имя службы приложений в Package.appxmanifest файле.
  4. Используйте IBackgroundTaskInstance.TriggerDetails, чтобы создать VoiceCommandServiceConnection в Кортана, чтобы получить голосовую команду.

  5. Зарегистрируйте обработчик событий для VoiceCommandServiceConnection. VoiceCommandCompleted для получения уведомлений при закрытии службы приложений из-за отмены пользователя.

  6. Зарегистрируйте обработчик событий для IBackgroundTaskInstance.Canceled для получения уведомлений при закрытии службы приложений из-за неожиданного сбоя.

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

    1. Используйте VoiceCommand. Свойство CommandName для определения имени голосовой команды.
    2. Чтобы определить, что сказал пользователь, проверьте значение текста или семантические свойства распознанной фразы в SpeechRecognitionSemanticInterpretation словаре.
  8. Выполните соответствующее действие в службе приложений.

  9. Отображение и разговор обратной связи с голосовой командой с помощью Кортаны.

    1. Определите строки, которые требуется , чтобы Кортана отображала и говорила с пользователем в ответ на голосовую команду и создайте VoiceCommandResponse объект. Инструкции по выбору строк обратной связи, отображаемых Кортана и говорящих, см . в рекомендациях по проектированию Кортаны.
    2. Используйте экземпляр VoiceCommandServiceConnection, чтобы сообщить о ходе выполнения или завершении Кортаны путем вызова ReportProgressAsync или ReportSuccessAsync с VoiceCommandServiceConnection объектом.

    Примечание.

    Если вам нужно обратиться к VCD, перейдите в раздел "Изменить файл 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);
        }
    }
    

После активации служба приложений имеет 0,5 секунды для вызова ReportSuccessAsync. Кортана показывает и говорит строку обратной связи.

Примечание.

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

Если приложение занимает больше 0,5 секунды для вызова, Кортана вставляет экран с рукой, как показано здесь. Кортана отображает экран выключения, пока приложение не вызывает ReportSuccessAsync или не более 5 секунд. Если служба приложений не вызывает ReportSuccessAsync или какой-либо из VoiceCommandServiceConnection методов, которые предоставляют Кортана с информацией, пользователь получает сообщение об ошибке и служба приложений отменяется.

Снимок экрана: Кортана и базовый запрос с экранами хода выполнения и результатов с помощью приложения AdventureWorks в фоновом режиме