Cortana の音声コマンドを使ったバックグラウンド アプリのアクティブ化

警告

この機能は、Windows 10 May 2020 Update (バージョン 2004、コードネーム "20H1") ではサポートされなくなりました。

Cortana が最新の生産性エクスペリエンスをどのように変革させているかについては、「Microsoft 365 の Cortana」を参照してください。

Cortana 内で音声コマンドを使ってシステム機能にアクセスするだけでなく、実行するアクションやコマンドを指定する音声コマンドを使うアプリの機能 (バックグラウンド タスク) によって Cortana を拡張することもできます。 アプリがバックグラウンドで音声コマンドを処理する場合、フォーカスは取りません。 代わりに、 Cortana キャンバスと Cortana 音声を通じて、すべてのフィードバックと結果が返されます。

アプリは、操作の複雑さに応じて、フォアグラウンド (アプリがフォーカスを取得します) またはバックグラウンド (Cortana がフォーカスを維持します) でアクティブ化することができます。 たとえば、追加のコンテキストやユーザー入力 (特定の連絡先へのメッセージの送信など) が必要な音声コマンドはフォアグラウンド アプリで処理するのが最適ですが、基本的なコマンド (旅行の予定の一覧表示など) はバックグラウンド アプリを介して Cortana で処理できます。

音声コマンドを使用してフォアグラウンドにアプリをアクティブ化する場合は、「 Cortana を使用して音声コマンドを使用してフォアグラウンド アプリをアクティブ化するを参照してください。

Note

音声コマンドは、特定の意図を持つ 1 つの発話であり、音声コマンド定義 (VCD) ファイルで定義されています。Cortana を通じてインストール済みアプリに指示が伝えられます。

VCD ファイルでは、1 つ以上の音声コマンドが定義されており、各音声コマンドは固有の目的を持っています。

音声コマンド定義は複雑さが異なる場合があります。 制約のある 1 つの発話から、より柔軟な自然言語の発話のコレクションまで、すべて同じ意図を示すあらゆるものをサポートできます。

ここでは、ここで示す Adventure Works Cortana UI に統合された旅行計画および管理アプリを使用して、説明する多くの概念と機能を示します。 詳細については、「Cortana 音声コマンドのサンプル」を参照してください。

フォアグラウンド アプリを起動している Cortana のスクリーンショット

Cortana を使用せずに Adventure Works の乗車を表示するには、アプリを起動し、Upcoming trip ページに移動します。

Cortana の音声コマンドを使ってアプリをバックグラウンドで起動する場合、ユーザーは代わりに「Adventure Works, when is my trip to Las Vegas? (Adventure Works に登録されている次のラスベガス旅行はいつですか)」と言うことができます。 アプリがコマンドを処理し、 Cortana によって結果がアプリ アイコンやその他のアプリ情報と共に表示されます (指定されている場合)。

バックグラウンドで AdventureWorks アプリを使用した基本的なクエリと結果画面を含む Cortana のスクリーンショット

以下は、音声コマンド機能を追加し、音声またはキーボード入力を使うアプリのバックグラウンド機能によって Cortana を拡張する基本的な手順です。

  1. Cortana がバックグラウンドで呼び出すアプリ サービス (Windows.ApplicationModel.AppService を参照) を作成します。
  2. VCD ファイルを作成します。 VCD ファイルは、アプリをアクティブ化して操作を開始するかコマンドを呼び出すためにユーザーが発声できる音声コマンドをすべて定義する XML ドキュメントです。 VCD 要素と属性 v1.2 を参照してください。
  3. アプリの起動時に VCD ファイルにコマンド セットを登録します。
  4. アプリ サービスのバックグラウンド アクティブ化と音声コマンドの実行を処理します。
  5. Cortana 内の音声コマンドに適切なフィードバックを表示して話します。

ヒント

必要条件

ユニバーサル Windows プラットフォーム (UWP) アプリを開発するのが初めての場合は、以下のトピックに目を通して、ここで説明されているテクノロジをよく理解できるようにしてください。

ユーザー エクスペリエンス ガイドライン

アプリと Cortana を統合する方法については「Cortana の設計ガイドライン」を、便利で魅力的な音声認識対応アプリの設計に役立つヒントについては「音声操作」を参照してください。

Visual Studio でのプライマリ プロジェクトを使った新しいソリューションの作成

  1. Microsoft Visual Studio 2015 を起動します。
    Visual Studio 2015 のスタート ページが表示されます。

  2. [ファイル] メニューで、 [新規作成]>[プロジェクト] の順に選択します
    [新しいプロジェクト] ダイアログ ボックスが表示されます。 ダイアログの左側のウィンドウでは、表示するテンプレートの種類を選択できます。

  3. 左側のウィンドウで、[インストール済み] > [テンプレート] > [Visual C#] > [Windows] を展開した後、[ユニバーサル] テンプレート グループを選びます。 ユニバーサル Windows プラットフォーム (UWP) アプリで使うことができるプロジェクト テンプレートの一覧がダイアログの中央のウィンドウに表示されます。

  4. 中央のウィンドウで、 Blank アプリ (ユニバーサル Windows) テンプレートを選択します。
    [空のアプリ] テンプレートは、コンパイルして実行できる最小限の UWP アプリを作成します。 [空のアプリ] テンプレートにユーザー インターフェイス コントロールやデータは含まれていません。 このページをガイドとして使用して、アプリにコントロールを追加します。

  5. [ Name テキスト ボックスに、プロジェクト名を入力します。 例: AdventureWorks を使用します。

  6. [OK] ボタンをクリックすると、プロジェクトが作成されます。
    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) を参照してください。

Microsoft では、ローカライズされたリソースや複数の解像度のリソースの提供を現在計画していない場合でも、文字列リソース ファイルに既定の言語をマークし (en-US\resources.resw など)、画像に既定のスケール ファクターをマークする (logo.scale-100.png など) ことをお勧めします。 ただし、Microsoft では少なくとも倍率 100、200、400 のアセットを提供することをお勧めしています。

重要

Cortana キャンバスのタイトル領域で使用するアプリ アイコンは、Square44x44Logo アイコンであり、Package.appxmanifest ファイルで指定されます。
Cortana キャンバスのコンテンツ領域で各エントリのアイコンを指定することもできます。 結果アイコンの有効な画像サイズは次のとおりです。

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

コンテンツ タイルは、VoiceCommandResponse オブジェクトが VoiceCommandServiceConnection クラスに渡されるまで検証されません。 画像がこれらのサイズ比率に準拠していないコンテンツ タイルを含む VoiceCommandResponse オブジェクトを Cortana に渡した場合、例外が発生する可能性があります。 

例: Adventure Works アプリ (VoiceCommandService\\AdventureWorksVoiceCommandService.cs) は、VoiceCommandContentTile クラスで TitleWith68x68IconAndText タイル テンプレートを使用して、シンプルな灰色の四角形 (GreyTile.png) を指定します。 ロゴのバリアントは 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] > [ユニバーサル] で、[Windows ランタイム コンポーネント] を選択します。 Windows ランタイム コンポーネントは、アプリ サービス (Windows.ApplicationModel.AppService) を実装するコンポーネントです。

  3. プロジェクトの名前を入力し、[OK] ボタンをクリックします。
    例: VoiceCommandService

  4. ソリューション エクスプローラーで、VoiceCommandService プロジェクトを選択し、Visual Studio によって生成された Class1.cs ファイルの名前を変更します。 例: Adventure Works では AdventureWorksVoiceCommandService.cs を使用します。

  5. Class1.cs のすべての出現箇所の名前を変更するかどうかを確認するメッセージが表示されたら、[はい] ボタンをクリックします。

  6. AdventureWorksVoiceCommandService.cs ファイルで次の操作を行います。

    1. 次の using ディレクティブを追加します。
      using Windows.ApplicationModel.Background;
    2. 新しいプロジェクトを作成すると、プロジェクト名がすべてのファイルの既定のルート名前空間として使用されます。 名前空間の名前を変更して、プライマリ プロジェクトの下に App Service コードを入れ子にします。 例: namespace AdventureWorks.VoiceCommands
    3. ソリューション エクスプローラーでアプリ サービスのプロジェクト名を右クリックし、[プロパティ] を選択します。
    4. [ライブラリ] タブで、[既定の名前空間] フィールドをこの同じ値で更新します。
      例: AdventureWorks.VoiceCommands
    5. IBackgroundTask インターフェイスを実装する新しいクラスを作成します。 このクラスには Run メソッドが必要です。これは、Cortana が音声コマンドを認識するときのエントリ ポイントです。

    例: Adventure Works アプリの基本的なバックグラウンド タスク クラス。

    Note

    バックグラウンド タスク クラス自体と、バックグラウンド タスク プロジェクト内のすべてのクラスは、sealed public クラスである必要があります。

    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. 2 つ目の uap:Extension 要素を Extensions 要素に追加します。
    10. この uap:Extension 要素に Category 属性を追加し、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. この App Service プロジェクトをプライマリ プロジェクトの参照として追加します。

    1. [参照設定] を右クリックします。
    2. [参照の追加...] を選択します。
    3. Reference Manager ダイアログで、Projectsを展開し、App Service プロジェクトを選択します。
    4. [OK] ボタンをクリックします。

VCD ファイルの作成

  1. Visual Studio で、プライマリ プロジェクト名を右クリックし、[追加] > [新しい項目] を選択します。 XML ファイルを追加します。
  2. VCD ファイルの名前を入力します。
    例: AdventureWorksCommands.xml
  3. [追加] ボタンをクリックします。
  4. ソリューション エクスプローラーで、VCD ファイルを選択します。
  5. Properties ウィンドウで、Build アクションContent に設定し、Copy を出力ディレクトリに設定し新しい場合は Copy に設定

VCD ファイルの編集

  1. https://schemas.microsoft.com/voicecommands/1.2 を指す xmlns 属性を指定した VoiceCommands 要素を追加します。

  2. アプリがサポートする各言語に対して、アプリがサポートする音声コマンドを含む CommandSet 要素を作成します。
    複数の CommandSet 要素を宣言し、それぞれに異なる xml:lang 属性を指定することで、アプリをさまざまな市場で使うことができるようにします。 たとえば、米国用のアプリに、英語の CommandSet とスペイン語の CommandSet を含めることができます。

    重要

    音声コマンドを使ってアプリをアクティブ化して操作を開始するには、ユーザーのデバイスで指定された音声の言語に一致する言語を含む CommandSet を格納している VCD ファイルをアプリで登録する必要があります。 音声の言語は、[設定] > [システム] > [音声認識] > [音声認識の言語] にあります。

  3. サポートする各コマンドの Command 要素を追加します。
    VCD ファイルで宣言された各 Command は、次の情報を含む必要があります。

    • アプリケーションが実行時に音声コマンドを識別するために使用する Name 属性。

    • ユーザーがコマンドを呼び出す方法を説明する語句を含む Example 要素。 ユーザーが「What can I say?」(何と言ったらよいですか)、「Help」(ヘルプ) と言ったときや、[もっと見る]をタップしたときに、Cortana にこの例が表示されます。

    • アプリがコマンドとして認識する単語または語句を含む ListenFor 要素。 各 ListenFor 要素には、コマンドに関連する特定の単語を含む 1 つまたは複数の PhraseList 要素への参照を格納できます。

      Note

      ListenFor 要素はプログラムで変更できません。 ただし、ListenFor 要素に関連付けられた PhraseList 要素はプログラムで変更できます。 アプリケーションは、ユーザーがアプリを使うときに生成されたデータ セットに基づいて実行時に PhraseList 要素の内容を変更する必要があります。

      詳細については、「Cortana VCD の語句一覧の動的な変更」を参照してください。

    • アプリケーションが起動したときに Cortana に表示されて読み上げられるテキストを含む Feedback 要素。

Navigate 要素は、音声コマンドにアプリをフォアグラウンドでアクティブ化するように指示します。 この例では、 showTripToDestination コマンドはフォアグラウンド タスクです。

VoiceCommandService 要素は、音声コマンドにアプリをバックグラウンドでアクティブ化するように指示します。 この要素の Target 属性の値は、package.appxmanifest ファイルにある uap:AppService 要素の Name 属性の値に一致する必要があります。 この例では、whenIsTripToDestination および cancelTripToDestination コマンドは、アプリ サービス名を AdventureWorksVoiceCommandService として指定するバックグラウンド タスクです。

詳細については、 VCD 要素と属性 v1.2 リファレンスを参照してください。

例: Adventure Works アプリ向けの en-us 音声コマンドを定義する VCD ファイルの一部。

<?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 をインストールするには、アプリを 1 回実行する必要があります。

Note

音声コマンド データは、アプリのインストール間で保持されません。 アプリの音声コマンド データをそのまま維持するには、アプリが起動またはアクティブ化されるたびに VCD ファイルを初期化するか、VCD が現在インストールされているかどうかを示す設定を維持することを検討してください。

app.xaml.cs ファイルで次の操作を行います。

  1. 次の using ディレクティブを追加します。

    using Windows.Storage;
    
  2. OnLaunched メソッドを async 修飾子でマークします。

    protected async override void OnLaunched(LaunchActivatedEventArgs e)
    
  3. OnLaunched ハンドラーで InstallCommandDefinitionsFromStorageFileAsync メソッドを呼び出して、認識する必要がある音声コマンドを登録します。
    例: Adventure Works アプリで StorageFile オブジェクトを定義します。
    例: GetFileAsync メソッドを呼び出して、AdventureWorksCommands.xml ファイルを使用して StorageFile オブジェクトを初期化します。
    その後、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());
     }
    

アクティブ化の処理

アプリがそれ以降の音声コマンドのアクティブ化にどのように応答するかを指定します。

Note

音声コマンド セットがインストールされた後、少なくとも 1 回はアプリを起動する必要があります。

  1. 音声コマンドによってアプリがアクティブ化されたことを確認します。

    Application.OnActivated イベントをオーバーライドし、IActivatedEventArgs.KindVoiceCommand かどうかを確認します。

  2. コマンドの名前と話された内容を決定します。

    VoiceCommandActivatedEventArgs オブジェクトへの参照を IActivatedEventArgs から取得し、SpeechRecognitionResult オブジェクトの Result プロパティを照会します。

    ユーザーが声に出した内容を判断するには、Text の値か、SpeechRecognitionSemanticInterpretation ディクショナリ内の認識された語句のセマンティクス プロパティを確認します。

  3. 目的のページに移動するなど、アプリで適切なアクションを実行します。

    Note

    VCD を参照する必要がある場合は、「VCD ファイルの編集」セクションを参照してください。

    音声コマンドの音声認識の結果を受け取った後、RulePath 配列の最初の値からコマンド名を取得します。 VCD ファイルでは考えられる複数の音声コマンドが定義されたため、その値が VCD 内のコマンド名と一致することを確認し、適切なアクションを実行する必要があります。

    アプリケーションの最も一般的なアクションは、音声コマンドのコンテキストに関連するコンテンツを含むページへの移動です。
    例: TripPage ページを開き、音声コマンドの値、コマンドがどのように入力されたか、認識された destination 語句 (該当する場合) を渡します。 または、TripPage ページに移動するときにアプリがナビゲーション パラメーターを SpeechRecognitionResult に送ることができます。

    アプリを起動した音声コマンドが実際に発声されたか、またはテキストとして入力されたかを、SpeechRecognitionSemanticInterpretation.Properties ディクショナリから commandMode キーを使って確認できます。 このキーの値は、voice または text のいずれかです。 キーの値が voice の場合、音声合成 (Windows.Media.SpeechSynthesis) を使って、発声されたフィードバックをアプリでユーザーに示すことを検討してください。

    SpeechRecognitionSemanticInterpretation.Properties を使って、ListenFor 要素の PhraseList または PhraseTopic 制約で発声されたコンテンツを調べます。 ディクショナリのキーは、PhraseList 要素または PhraseTopic 要素の Label 属性値です。 例: {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();
    }
    

アプリ サービスでの音声コマンドの処理

App Service で音声コマンドを処理します。

  1. 次の using ディレクティブを音声コマンド サービス ファイルに追加します。
    例: AdventureWorksVoiceCommandService.cs

        using Windows.ApplicationModel.VoiceCommands;
        using Windows.ApplicationModel.Resources.Core;
        using Windows.ApplicationModel.AppService;
    
  2. 音声コマンドの処理中にアプリ サービスが終了しないように、サービスの遅延を取ります。

  3. バックグラウンド タスクが、音声コマンドによってアクティブ化されたアプリ サービスとして実行されていることを確認します。

    1. IBackgroundTaskInstance.TriggerDetailsWindows.ApplicationModel.AppService.AppServiceTriggerDetails にキャストします。
    2. IBackgroundTaskInstance.TriggerDetails.NamePackage.appxmanifest ファイル内のアプリ サービスの名前であることを確認します。
  4. IBackgroundTaskInstance.TriggerDetails を使用してVoiceCommandServiceConnectionを作成しCortana音声コマンドを取得します。

  5. VoiceCommandServiceConnection. VoiceCommandCompleted のイベント ハンドラーを登録して、ユーザーによるキャンセルのためにアプリ サービスが閉じたときに、通知を受け取ることができるようにします。

  6. IBackgroundTaskInstance.Canceled のイベント ハンドラーを登録して、予期しないエラーが原因でアプリ サービスが閉じられたときに通知を受け取ります。

  7. コマンドの名前と話された内容を決定します。

    1. VoiceCommand.を使用するCommandName プロパティを使用して、音声コマンドの名前を決定します。
    2. ユーザーが声に出した内容を判断するには、Text の値か、SpeechRecognitionSemanticInterpretation ディクショナリ内の認識された語句のセマンティクス プロパティを確認します。
  8. アプリ サービスで適切なアクションを実行します。

  9. Cortana を使って、音声コマンドに対するフィードバックを表示して読み上げます。

    1. 音声コマンドに対する応答として Cortana がユーザーに表示して読み上げる文字列を決定し、VoiceCommandResponse オブジェクトを作成します。 Cortana が表示および読み上げるフィードバック文字列を選択する方法のガイダンスについては、Cortana の設計ガイドラインを参照してください。
    2. VoiceCommandServiceConnection オブジェクトで ReportProgressAsync または ReportSuccessAsync を呼び出して、VoiceCommandServiceConnection インスタンスを使って Cortana に進行状況または完了を報告します。

    Note

    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 を呼び出すことができます。 Cortana がフィードバック文字列を表示して読み上げます。

Note

フィードバック文字列は、VCD ファイル内で宣言できます。 この文字列は、Cortana のキャンバスに表示される UI テキストには影響しません。Cortana によって読み上げられるテキストにのみ影響します。

アプリが呼び出しに 0.5 秒以上かかる場合、次に示すように Cortana はハンドオフ画面を挿入します。 Cortana は、アプリケーションが ReportSuccessAsync を呼び出すか、最大 5 秒間、ハンドオフ画面を表示します。 ReportSuccessAsync、または Cortana に情報を提供するどの VoiceCommandServiceConnection メソッドもアプリ サービスが呼び出さない場合、エラー メッセージが表示されてアプリ サービスがキャンセルされます。

Cortana のスクリーンショットと、バックグラウンドで AdventureWorks アプリを使用した進行状況と結果画面を含む基本的なクエリ