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

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

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

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

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

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

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

Примечание

Голосовая команда — это один речевой фрагмент с определенным намерением, определенный в файле определения голосовых команд (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 в файле .
Можно также указать значок для каждой записи в области содержимого холста Кортаны . Допустимые размеры изображений для значков результатов:

  • 68 вт x 68 ч
  • 68 Вт x 92 ч
  • 280 вт x 140 ч

Плитка содержимого не проверяется до тех пор, пока объект 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. Пример. Adventure Works использует .AdventureWorksVoiceCommandService.cs

  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 элемент и задайте для атрибута Categorywindows.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 элемент и задайте для атрибута Categorywindows.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. В окне Свойства установите для параметра Действие сборки значениеСодержимое, а затем для параметра Копировать в выходной каталог значение Копировать, если новее.

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