集成Cortana到你的应用中

Windows Phone 8.1 GDR1 + Cortana 中文版的发布后相信很多中国的朋友正在happy的调戏着小娜同学。关于Cortana的应用场景也可参看我之前的文章。
那么如何让用户通过小娜来和你的应用来进行交互呢?下面我们来通过一个例子来学习如何使用小娜。

环境

首先是VS一定要是Visual Studio 2013 Update 2 或者 更新的,我这里使用的Update3

vs2013下载地址

然后需要安装 Windows Phone 8.1 Update and Emulators.

Windows Phone 8.1 Update and Emulators下载地址

如何开启模拟的小娜请看我之前的博文:Cortana(小娜)那些事儿

 ps. 建议安装vs的时候使用英文版,因为本人在之前安装的中文版中出现了在创建vcd文件时找不到https://schemas.microsoft.com/voicecommands/1.1 的情况,如果有类似情况的同学,可是尝试重新安装VS的英文版。然后再安装Windows Phone 8.1 Update and Emulators 问题应该就解决了. 建议使用真机进行调试。因为本人在使用模拟器调试时,无论使用任何命令都会跳转到bing搜索。所以本人改用真机。 

开始搞!

应用功能

这里我打算开发一个图片搜索应用来作为一个例子。 功能很简单将用户的语音命令直接到bing去搜索相应的图片。然后返回给用户。 (为了更专注于Cortana的功能- -就没写搜索功能,仅仅是简单的将用户的语音识别结果传送出来)

创建VCD文件

VCD(Voice Command Definition)文件是一个xml文档,用来定义所有你可以使用的语音命令。具体的使用请参考如下两个连接

Quickstart: Voice commands

Voice Command Definition (VCD) elements and attributes

首先在项目上右击选择添加新的项目如下图所示。

 

选择vcd文件

 

创建好文件后打开文件发现里面如下图已经有了很多代码,好我们先全部都删掉。

 

替换为我们的代码

 <?xml version="1.0" encoding="utf-8"?> <VoiceCommands xmlns="https://schemas.microsoft.com/voicecommands/1.1"> <CommandSet xml:lang="zh-cn" Name="englishCommands"> <CommandPrefix> Image </CommandPrefix> <Example> Image </Example> <Command Name="ImageSearch"> <Example> find 'something' </Example> <ListenFor> Search </ListenFor> <ListenFor> Search [for] {dictatedSearchTerms} </ListenFor> <ListenFor> Find {dictatedSearchTerms} </ListenFor> <ListenFor> Find </ListenFor> <Feedback> Searching on Bing...</Feedback> <Navigate Target="MainPage.xaml" /> </Command> <PhraseTopic Label="dictatedSearchTerms" Scenario="Search"> <Subject> ImageName </Subject> </PhraseTopic> </CommandSet> </VoiceCommands> 

安装VCD文件

创建好VCD文件是不够的,你必须安装你的VCD文件到你的系统上。如何安装呢?其实很简单就是在启动你的应用时能够执行一句安装vcd文件的命令即可。这里我们在Mainpage的OnNavigatedTo方法中来注册。复制下面的代码即可(别忘记把xml文件的地址改成自己的哦)

  protected override async void OnNavigatedTo(NavigationEventArgs e) { if (e.NavigationMode == NavigationMode.New) { var storageFile = await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///VoiceCommandDefinition.xml")); await Windows.Media.SpeechRecognition.VoiceCommandManager.InstallCommandSetsFromStorageFileAsync(storageFile); } } 

如果上面的都做完的你就可以尝试的运行下程序了,为了确定你vcd是否安装成功你可以打开小娜的查看更多选项然后拉倒最下面。看看你的应用是不是在下面(如下图所示),如果有了说明你的vcd文件已经注册成功,如果没有请确认的你vcd文件中的语言是否和你的设备的语言环境是相同的,如果不同也可能会无法安装你的vcd文件。

     

ps.         注意你一定要在package.appxmanifest中开启Microphone不然运行会出现问题(语音功能不开mic怎么能行呢是吧^_^)

获取语音命令与控制

做完上面所有的事情后就剩下处理我们的语音命令了。

首先我们需要重写Application.OnActivated事件。确定是不是语音命令来启动我们的应用 的(通过判断IActivatedEventArgs.Kind 是不是 VoiceCommand)

然后我们获取我们语音命令的结果。

我尝试改写MSDN的例子并应用到我们的例子上:

  protected override void OnActivated(IActivatedEventArgs args) { Frame rootFrame = Window.Current.Content as Frame; // 判断是否由语音命令启动 if (args.Kind == Windows.ApplicationModel.Activation.ActivationKind.VoiceCommand) { var commandArgs = args as Windows.ApplicationModel.Activation.VoiceCommandActivatedEventArgs; Windows.Media.SpeechRecognition.SpeechRecognitionResult speechRecognitionResult = commandArgs.Result; // 如果是的话获取语音命令的名字(vcd文件中的Command Name), 命令后用户说出的信息 以及 vcd Command/Navigate@Target 的值. string voiceCommandName = speechRecognitionResult.RulePath[0]; string textSpoken = speechRecognitionResult.Text; string navigationTarget = speechRecognitionResult.SemanticInterpretation.Properties["NavigationTarget"][0]; //判断当前命令式什么 <del>T_T 这里只有一个</del><del> switch (voiceCommandName) { case "ImageSearch": //跳转到相应的page,并将所有说的东西都传过去。(为什么这么跳转?因为写的快- -|||) rootFrame.Navigate(typeof(ShowImage), textSpoken); break; default: rootFrame.Navigate(typeof(ShowImage), "nothing"); break; } } } 

然后创建一个新的page c# 

 <Page x:Class="ImageFinder.ShowImage" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:ImageFinder" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBlock x:Name="textBlock" FontSize="50" Text="nothing"></TextBlock> </Grid> </Page> 

Xaml 

 using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices.WindowsRuntime; using Windows.Foundation; using Windows.Foundation.Collections; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkID=390556 namespace ImageFinder { /// <summary> /// An empty page that can be used on its own or navigated to within a Frame. /// </summary> public sealed partial class ShowImage : Page { public ShowImage() { this.InitializeComponent(); } /// <summary> /// Invoked when this page is about to be displayed in a Frame. /// </summary> /// <param name="e">Event data that describes how this page was reached. /// This parameter is typically used to configure the page.</param> protected override void OnNavigatedTo(NavigationEventArgs e) { textBlock.Text = e.Parameter.ToString(); } } } 

运行试试

打开小娜对着她说 ImageFinder Search 测试   (呵呵中英混合看看她识别的怎么样) 非常nice她打开了我的应用并跳转到相应的页面,也将我的话打印出来了。

 ps 注意测试时尽量使用语音,使用文字可能会出现直接跳转到bing的情况,也许是因为小娜现在还是bete版本的情况吧。