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通用应用开发中,有关语 ...
随机推荐
- UIKit - scrollView缩放、滚动
UIScrollView滚动 三大属性: self.scrollView.pageEnabled = NO 是否分页:n只要将UIScrollView的pageEnabled属性设置为YES,UIS ...
- PHP多条件搜索ShopNc实例
控制器部分代码: if (trim($_GET['keyword']) != '') { //echo $_GET['search_type']; exit(); switch ($_GET['sea ...
- 记一次联想A820t救砖线刷
因为是看着教程刷的(有大神放出教程,只管伸手拿来就好啦)但是照着教程做的过程中出现了一些问题还是值得注意的,在这里总结一下,给新手提供一点建议 教程比较长,我放到博客的文件中,需要的自己下载一下.或者 ...
- springMVC中实现servlet依赖注入
记录一下开发过程中遇到的问题: 首先看一下这个帖子: http://blog.csdn.net/gaogaoshan/article/details/23540129 由于我使用的是springMVC ...
- 驱动插ring3线程执行代码
近日有在写一个小东西 需要在内核态中运行一个WIN32程序 之前提到的插入APC可以满足部分要求 但是一到WIN7 x86平台下就崩溃了WIN7下只能插入第三方的进程 一插入系统进程就崩溃,但是这样满 ...
- 一次DB服务器性能低下引发的对Nonpaged Pool Leak问题的诊断
1. 问题表象+分析 最开始是DB访问性能下降,某个不用Cache.直接到DB的查询10s+都不返回.上去一看,DB Server内存97%,可用内存才100多M. Windows毕竟不是iOS,不留 ...
- node模块系统常用命令
node模块系统常用命令 命令 示例 备注 安装模块 npm install commander 最新版本 npm install commander@1.0.0 指定版本 npm install c ...
- 让powershell同时只能运行一个脚本(进程互斥例子)
powershell,mutex,互斥,进程互斥,脚本互斥 powershell脚本互斥例子,在powershell类别文章中,声明原创唯一. powershell 传教士 原创文章 2016-07- ...
- win10下安装USB-Blaster哈希值错误
插入usb-blaster后,无法安装驱动,一直显示感叹号,更新驱动后显示“文件的哈希值不在指定的目录”这样的错误提示,解决方法如下:1.Windows键+ R,输入shutdown.exe /r / ...
- 会游走的TextView
//自定义的TextView package com.bwie.androidtest; import android.content.Context; import android.graphics ...