かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

コルタナさんでアプリを起動する

「コルタナさん、サンプルアプリ起動」といったらアプリが起動するそんな感じです。

コルタナさんは、Voice Command Fileというので音声に対して何をするか定義します。アプリを作ってVoiceCommands.xmlとかいう名前でファイルを作って以下のようなXMLを定義します。

<?xml version="1.0" encoding="utf-8" ?>
<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.2">
  <CommandSet xml:lang="ja-jp" Name="HolCommandSet_ja-jp">
    <CommandPrefix>サンプルアプリ</CommandPrefix>
    <Example>起動</Example>

    <Command Name="LaunchApp">
      <Example>起動</Example>
      <ListenFor>起動</ListenFor>
      <Feedback>サンプルアプリを起動しています</Feedback>
      <Navigate />
    </Command>
  </CommandSet>
</VoiceCommands>

xmlnsを定義したら、インテリセンスがきくのでいい感じで書けます。CommandSetにlangでja-jpを定義すると日本語のものになります。

CommandにListenForで指定した文字列が来たら何をするという感じで定義します。Navigateタグはアプリを起動するという定義になります。

このVoice Command Fileは、なんとプログラムで登録します。ということで、アプリが最低でも1度は起動して登録処理を走らせないといけないってことになります。OnLaunchedの先頭に以下のコードを書いて登録します。

var storageFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///VoiceCommands.xml"));
await VoiceCommandDefinitionManager.InstallCommandDefinitionsFromStorageFileAsync(storageFile);

因みに名前空間書いてませんのでCtrl + .あたりで名前空間はusingしてください。

こうしてVoice Command Fileが登録されると、ついにコルタナさん対応ができます。コルタナさんからアプリが起動されるとOnActivatedが呼ばれます。こんな感じのコードを書くとコルタナさんから起動したときの処理が書けます。

protected override void OnActivated(IActivatedEventArgs args)
{
    var rootFrame = Window.Current.Content as Frame;
    if (rootFrame == null)
    {
        rootFrame = new Frame();
        rootFrame.NavigationFailed += this.OnNavigationFailed;

        Window.Current.Content = rootFrame;
    }

    if (args.Kind == ActivationKind.VoiceCommand)
    {
        this.HandleVoiceCommand(args as VoiceCommandActivatedEventArgs, rootFrame);
    }

    Window.Current.Activate();
    base.OnActivated(args);
}

private void HandleVoiceCommand(VoiceCommandActivatedEventArgs args, Frame rootFrame)
{
    var result = args.Result;
    var command = result.Text;
    var voiceCommandName = result.RulePath[0];
    Debug.WriteLine($"command {command}, voiceCommandName {voiceCommandName}");
    if (voiceCommandName == "LaunchApp")
    {
        rootFrame.Navigate(typeof(VoiceCommandPage));
    }
}

これでコルタナさんに「サンプルアプリ起動」と話しかけるとアプリが起動します。以外とお手軽ではありますね。