Win10/UWP开发—使用Cortana语音与App后台Service交互
上篇文章中我们介绍了使用Cortana调用前台App,不熟悉的移步到:Win10/UWP开发—使用Cortana语音指令与App的前台交互,这篇我们讲讲如何使用Cortana调用App的后台任务,相比调用前台的App,调用后台任务有个有点就是App不用被启动即可为用户提供服务。
要想使用Cortana调用App后台任务,首先我们需要定义VCD文件,我们依旧使用上篇中的代码,让它支持Cortana调用后台任务。
创建后台任务
新增一个[Windows运行时组件]项目,暂时起名叫做:XiaoMiBackgroundTask
创建一个类,暂且叫做XiaoMiTask,并继承IBackgroundTask
完成如下代码:
//------------------------------------------------------
//
// FileName: XiaoMiTask.cs
// Namespace: XiaoMiBackgroundTask
// Assembly: XiaoMiBackgroundTask
// Description:
// Author: aran_wang
// Created On: 2015-09-10
//------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Windows.ApplicationModel.AppService;
using Windows.ApplicationModel.Background;
using Windows.ApplicationModel.VoiceCommands;
using Windows.Storage; namespace XiaoMiBackgroundTask
{
/*
VoiceCommandServiceConnection 类是接受Cortana传递过来的信息以及给Cortana回应信息的
里面有几个重要的方法:
GetVoiceCommandAsync 检索用户的语音命令提交Cortana通过语音或文本。
ReportFailureAsync 发送一个响应,表明Cortana语音命令处理失败了。
ReportProgressAsync 发送一个响应,Cortana在处理语音命令。
ReportSuccessAsync 发送一个响应,Cortana语音命令已成功了。
RequestAppLaunchAsync 发送一个响应,要求Cortana启动前台应用
RequestConfirmationAsync 发送一个响应,指示Cortana语音命令需要确认。
RequestDisambiguationAsync 发送一个响应,表示Cortana语音命令返回多个结果,需要用户选择一个。
*/ public sealed class XiaoMiTask : IBackgroundTask
{
BackgroundTaskDeferral _taskDerral;
VoiceCommandServiceConnection _serviceConnection;
public async void Run(IBackgroundTaskInstance taskInstance)
{
_taskDerral = taskInstance.GetDeferral();
var details = taskInstance.TriggerDetails as AppServiceTriggerDetails; // 验证是否调用了正确的app service
if (details == null || details.Name != "XiaoMiService")
{
_taskDerral.Complete();
return;
}
_serviceConnection = VoiceCommandServiceConnection.FromAppServiceTriggerDetails(details);
// 获取被识别的语音命令
var cmd = await _serviceConnection.GetVoiceCommandAsync();
switch (cmd.CommandName)
{
case "QueryTrain":
var date = cmd.Properties["DateTime"][];
var from = cmd.Properties["From"][];
var to = cmd.Properties["To"][];
await QueryTrain(date, from, to);
break;
case "CancelTrain":
var cancelTrain = cmd.Properties["City"][];
CancelTrain(cancelTrain);
break;
}
_taskDerral.Complete();
} private void CancelTrain(string cancelTrain)
{
//取消火车 交互类似
Debug.WriteLine(cancelTrain);
} private async Task QueryTrain(string date, string from, string to)
{
// msgback是返回给Cortana 要显示的内容
var msgback = new VoiceCommandUserMessage();
// msgRepeat是指当cortana对用户语音指令不明确的时候显示的,一般用来消除用户歧义
// 比如存在让用户选择某个选项时,用户没有按照预期的操作方式去操作,cortana会显示第二消息来告诉一些操作提示信息
var msgRepeat = new VoiceCommandUserMessage(); //模拟火车列表,真实情况下需要调用api获取火车信息
var trainList = new List<VoiceCommandContentTile>();
for (var i = ; i < ; i++)
{
trainList.Add(new VoiceCommandContentTile
{
AppContext = i, //用来存储该条Tile的标识 一般存储数据id
ContentTileType = VoiceCommandContentTileType.TitleWith68x68IconAndText,
Image = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Images/300300.jpg")),
Title = $"D{i + 3}8{i * 2}",
TextLine1 = $"出发:{DateTime.Now.AddHours(i)} - 到达:{DateTime.Now.AddHours(i + 2)}"
});
} TrainList: msgback.DisplayMessage = msgback.SpokenMessage = $"我找到了{date}从{from}到{to}的火车列表,请选择:";
msgRepeat.DisplayMessage = msgRepeat.SpokenMessage = "你要告诉我你想预定哪个车次的火车:";
// 把查询到的火车列表发回到Cortana ,注意 列表最多显示10个
var response = VoiceCommandResponse.CreateResponseForPrompt(msgback, msgRepeat, trainList); // 用户选择了哪个项
var selectedRes = await _serviceConnection.RequestDisambiguationAsync(response); //创建咨询用户是否确定要预定该车次的信息
msgback.DisplayMessage = msgback.SpokenMessage = $"您确定要预定 {selectedRes.SelectedItem.Title} 次列车吗?";
msgRepeat.DisplayMessage = msgRepeat.SpokenMessage = "请选择是或者不是";
response = VoiceCommandResponse.CreateResponseForPrompt(msgback, msgRepeat); //返回让用户选择 是 或者 不是 的信息给cortana
var result = await _serviceConnection.RequestConfirmationAsync(response);
//如果用户选择是
if (result.Confirmed)
{
//提示预定成功
msgback.DisplayMessage = msgback.SpokenMessage = $"您成功预定了 {selectedRes.SelectedItem.Title} 次列车,{date}从{from}到{date},{selectedRes.SelectedItem.TextLine1}!";
msgRepeat.DisplayMessage = msgRepeat.SpokenMessage = $"您成功预定了 {selectedRes.SelectedItem.Title} 次列车。";
response = VoiceCommandResponse.CreateResponseForPrompt(msgback, msgRepeat);
}
else
{
goto TrainList;
}
// 返回一个操作成功的指令
await _serviceConnection.ReportSuccessAsync(response);
}
}
}
代码意思就不解释了,写的一手详细的注释不是吗?
回到我们的主程序中,在引用里添加该后台应用服务的引用。
注册App后台服务
打开Package.appxmanifest文件,切换到"声明"选项卡,添加一个应用服务的声明,名称随便填,一会VCD文件里要用到这个名字,这里填写XiaoMiService,别以为是小米的意思哈,哥是米黑,是小秘。入口点填写上面创建的后台服务的"命名空间.类名",截图如下:

编写VCD文件
在vcd语音指令中添加两个新的Command节点,以及定义需要的PhraseTopic,对VCD文件不熟悉的移步到:Win10/UWP开发—使用Cortana语音指令与App的前台交互
添加的代码如下:
<Command Name="QueryTrain">
<Example> 查询去某地的火车 </Example>
<ListenFor >查询{DateTime}从{From}到{To}的火车</ListenFor>
<Feedback> 正在查询{DateTime}从{From}到{To}的火车 </Feedback>
<VoiceCommandService Target="XiaoMiService"/>
</Command> <Command Name="CancelTrain">
<Example> 取消去某地的火车 </Example>
<ListenFor >取消去{City}的火车</ListenFor>
<Feedback> 正取消去{City}的火车 </Feedback>
<VoiceCommandService Target="XiaoMiService"/>
</Command> <!--PhraseTopic 可以提高识别率,内部属性Subject可指定该关键字类型,比如 城市名 姓名 地址 等类型-->
<PhraseTopic Label="City" Scenario="Natural Language">
<Subject>City/State</Subject>
</PhraseTopic>
<PhraseTopic Label="From" Scenario="Natural Language">
<Subject>City/State</Subject>
</PhraseTopic>
<PhraseTopic Label="To" Scenario="Natural Language">
<Subject>City/State</Subject>
</PhraseTopic>
<PhraseTopic Label="DateTime" Scenario="Natural Language">
<Subject>Date/Time</Subject>
</PhraseTopic>
上面的Command节点中,使用了VoiceCommandService元素来标注该语音指令是要启动后台任务服务,而后台任务服务名称为XiaoMiService。
注册VCD文件
注册vcd文件上篇文章一毛一样:
/// <summary>
/// 注册语音指令
/// </summary>
private async Task InsertVoiceCommands()
{
await VoiceCommandDefinitionManager.InstallCommandDefinitionsFromStorageFileAsync(
await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///VoiceCommandsFile.xml")));
}
Ok,打开一次App完成VCD语音指令的注册,然后尽情的使用Cortana吧:

推荐一个UWP开发群:53078485 大家可以进来一起学习
Win10/UWP开发—使用Cortana语音与App后台Service交互的更多相关文章
- Win10/UWP开发—使用Cortana语音指令与App的前台交互
Win10开发中最具有系统特色的功能点绝对少不了集成Cortana语音指令,其实Cortana语音指令在以前的wp8/8.1时就已经存在了,发展到了Win10,Cortana最明显的进步就是开始支持调 ...
- Win10/UWP开发—使用Cortana语音指令启动前台App
这两天进群(53078485)找大咖的童鞋比较多,只是大咖比较忙,目前Demo还没有要到,这里先给大家转载一篇Aran大咖的博客学习下,以下是原文: Win10开发中最具有系统特色的功能点绝对少不了集 ...
- Win10 UWP开发系列:使用VS2015 Update2+ionic开发第一个Cordova App
安装VS2015 Update2的过程是非常曲折的.还好经过不懈的努力,终于折腾成功了. 如果开发Cordova项目的话,推荐大家用一下ionic这个框架,效果还不错.对于Cordova.PhoneG ...
- Win10 UWP开发系列:实现Master/Detail布局
在开发XX新闻的过程中,UI部分使用了Master/Detail(大纲/细节)布局样式.Win10系统中的邮件App就是这种样式,左侧一个列表,右侧是详情页面.关于这种 样式的说明可参看MSDN文档: ...
- Win10 UWP开发实现Bing翻译
微软在WP上的发展从原来的Win7到Win8,Win8.1,到现在的Win10 UWP,什么是UWP,UWP即Windows 10 中的Universal Windows Platform简称.即Wi ...
- Win10/UWP开发—凭据保险箱PasswordVault
PasswordVault用户凭据保险箱其实并不算是Win10的新功能,早在Windows 8.0时代就已经存在了,本文仅仅是介绍在UWP应用中如何使用凭据保险箱进行安全存储和检索用户凭据. 那么什么 ...
- Win10 UWP 开发系列:使用SQLite
在App开发过程中,肯定需要有一些数据要存储在本地,简单的配置可以序列化后存成文件,比如LocalSettings的方式,或保存在独立存储中.但如果数据多的话,还是需要本地数据库的支持.在UWP开发中 ...
- Win10/UWP开发-Ink墨迹书写
在UWP开发中,微软提供了一个新型的InkCanvas控件用来让用户能书写墨迹,在新版的Edga浏览器中微软自己也用到了该控件使用户很方便的可以在web上做笔记. InkCanvas控件使用很简单,从 ...
- 【Win10 应用开发】集成语音命令
记得老周以前在写WP8应用开发的文章时,曾经写过语音命令集成的文章,后来8.1的时候“小娜”问世,但考虑到其变化不大,故老周没有补写相应的文章. 今天,老周打算补一下Win 10通用应用开发中,有关语 ...
随机推荐
- HTML <span> 标签
定义和用法: <span>标签被用来组合文档中的行内元素.在行内定义一个区域,也就是一行内可以被<span>划分成好几个区域,从而实现某种特定效果.<span>本身 ...
- Windows Store App JavaScript 开发:选取文件和文件夹
前面提到过,文件打开选取器由FileOpenPicker类表示,用于选取或打开文件,而文件夹选取器由FolderPicker类表示,用来选取文件夹.在FileOpenPicker类中,pickSing ...
- BZOJ3143 [Hnoi2013]游走
首先高斯消元解出每个点被走到的概率 注意到这里走到$n$就停下来了,所以$P(n) = 0$ 解出来以后,给每条边$(u, v)$赋边权$P(u) + P(v)$即可,然后直接贪心 /******** ...
- C#读写config配置文件
应用程序配置文件(App.config)是标准的 XML 文件,XML 标记和属性是区分大小写的.它是可以按需要更改的,开发人员可以使用配置文件来更改设置,而不必重编译应用程序. 对于一个config ...
- navicat 创建的表,username字段不能接受中文名字。
用navicat 创建的表,username(varchar)字段不能接受中文名字. 解决方法如下: 选中所创建的users表,打开“设计表”,选中username字段,看到下面是字符集latin1, ...
- asp.net ajax控件tab扩展,极品啊,秒杀其它插件
说明:asp.net ajax控件tab要设置width和height,而且在线文本编辑器放能够放入tab中,也必须是asp.net的控件型在线文本,例如fckeditor,下面是我设置好的配置. & ...
- DIV的不能包住子集解决办法
在div的样式中加上:overflow:hidden,或者float:left或right
- Mac的最小化和隐藏的区别
Mac 中应用程序窗口的最小化和隐藏的快捷键: CMD + H 隐藏应用程序 CMD + M 最小化应用程序 重点在于两点的区别: 最小化会隐藏当前应用程序的窗口,不切换当前的应用程序:隐藏应用程序会 ...
- linux下查看tomcat和jdk版本号
linux下查看tomcat和jdk版本号的命令: 这个需要进入到bin目录下面 ,执行"./version.sh"命令 [root@hncsweb bin]# ./version ...
- 50个C/C++源代码网站
C/C++是最主要的编程语言.这里列出了50名优秀网站和网页清单,这些网站提供c/c++源代码 .这份清单提供了源代码的链接以及它们的小说明.我已尽力包括最佳的C/C++源代码的网站.这不是一个完整的 ...