当前位置: 首页 > 编程日记 > 正文

【Win10 应用开发】语音命令与App Service集成

昨天,老周演示了语音命令集成这一高大上功能,今天咱们来点更高级的语音命令。

在昨天的例子中,响应语音命令是需要启动应用程序的,那么如果可以不启动应用程序,就直接在小娜面板上进行交互,是不是会更高大小呢。

面向Win 10的API给应用程序增加了一种叫App Service的技术,应用程序可以通过App Service公开服务来让其他应用程序调用。App Service是通过后台任务来处理的,故不需要启动应用程序,调用者只需要知道提供服务的应用程序的程序包名称,以及要调用的服务名称即可以进行调用了。关于App Service,老周曾做过相关视频,有时间的话再补上博文。

正因为App Service是通过后台任务来处理的,再与小娜语音命令一集成,应用程序就可以在后台响应语音操作,而不必在前台启动。

好了,基本理论依据有了,接下来,老规矩,老周向来不喜欢讲XYZ理论的,还是直接说说如何用吧。

1、定义语音命令文件。老周写了个新的文件。

<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.2"><CommandSet xml:lang="zh-hans"><AppName>乐器收藏</AppName><Example>“乐器收藏 展现列表”,或者“乐器收藏 显示列表”</Example><Command Name="show"><Example>展现列表,或者 显示列表</Example><ListenFor>[展现]列表</ListenFor><ListenFor>显示列表</ListenFor><VoiceCommandService Target="vcfav"/></Command></CommandSet>
</VoiceCommands>

其他元素我在上一篇烂文中已经介绍过,不过大家会发现有个家伙比较陌生——VoiceCommandService元素。对,实现语音命令和App Service集成,这个元素的配很关键,Target属性就是你要集成的App Service的名字,本例子应用待会要公开的一个App Service名字叫vcfav,记好了。

这个应用的用途是向大家Show一下老周收藏的几款乐器,都是高大上的乐器,能奏出醉人心弦的仙乐。注意,这里的命令文件用了VoiceCommandService元素,就不需要用Navigate元素。

2、实现后台任务。在解决方案中添加一个Runtime组件项目,记得老周N年前说过,实现后台的类型是放到一个运行时组件项目中的。

    public sealed class BTask : IBackgroundTask{BackgroundTaskDeferral taskDerral = null;VoiceCommandServiceConnection serviceConnection = null;public async void Run(IBackgroundTaskInstance taskInstance){


后台任务的功能当然是响应小娜收到的语音命令,因为可以通过App service来触发,所以我们就能在后台任务中进行交互。

要与小娜面板进行交互,我们需要一个连接类——VoiceCommandServiceConnection类,它的实例可以从后台任务实例的触发器数据中获得,就是这样:

        public async void Run(IBackgroundTaskInstance taskInstance){taskDerral = taskInstance.GetDeferral();AppServiceTriggerDetails details = taskInstance.TriggerDetails as AppServiceTriggerDetails;// 验证是否调用了正确的app serviceif (details == null || details.Name != "vcfav"){taskDerral.Complete();return;}serviceConnection = VoiceCommandServiceConnection.FromAppServiceTriggerDetails(details);

关键是这句:serviceConnection = VoiceCommandServiceConnection.FromAppServiceTriggerDetails(details);
连接对象就是这样获取的。

3、之后,我们就可以在代码中与小娜交互了。在交互过程中,发送到小娜面板的消息都由VoiceCommandUserMessage类来封装,它有两个属性:

DisplayMessage:要显示在小娜面板上的文本。

SpokenMessage:希望小娜说出来的文本。

如果你希望小娜说出的内容和面板上显示的内容相同,也可以把这两个属性设置为相同的文本。

与小娜交互的操作自然是由VoiceCommandServiceConnection实例来完成了,不然我们上面获取它干吗呢,就是为了在后面的交互操作中使用。

VoiceCommandServiceConnection通过以下几个方法来跟小娜交互:

ReportSuccessAsync:告诉小娜,处理已经完成,并返回一条消息,传递给小娜面板。

ReportFailureAsync:向小娜反馈错误信息。

ReportProgressAsync:报告进度,不指定具体进度值,只是在小娜面板上会显示长达5秒钟的进度条,你的代码处理不应该超过这个时间,不然用户体验不好。最好控制在2秒钟之内。

RequestAppLaunchAsync:请求小娜启动当前应用。

RequestConfirmationAsync:向小娜面板发送一条需要用户确认的消息。比如让小娜问用户:“你确定还没吃饭?”或者:“你认为老周很帅吗?”,用户只需回答Yes or No。后台任务会等待用户的确认结果,以决定下一步做什么。

RequestDisambiguationAsync:同样,也是向用户发出一条询问消息,与上面的方法不同的是,这个方法会在小娜面板上列出一串东西,让用户说出选择哪一项。比如,“请选择你要看的电影:”,然后选项有:《弱智仙侠》、《花钱骨》、《烧脑时代》、《菊花传奇》,你说出要选择的项,或者点击对应的项,小娜会把用户选择的项返回给应用程序后台任务,以做进一步处理。

在老周这个示例中,如果语音命令被识别,就会在小娜面板上列出老周收藏的五件乐器,然后你可以选择一件进行收藏,当然是不包邮的,你还要付等价费。

            if (serviceConnection != null){serviceConnection.VoiceCommandCompleted += ServiceConnection_VoiceCommandCompleted;// 获取被识别的语音命令VoiceCommand cmd = await serviceConnection.GetVoiceCommandAsync();if (cmd.CommandName == "show"){// 获取测试数据,用于生成磁块列表var tiles = await BaseData.GetData();// 定义返回给小娜面板的消息VoiceCommandUserMessage msgback = new VoiceCommandUserMessage();msgback.DisplayMessage = msgback.SpokenMessage = "请选择要收藏的乐器。";// 第二消息,必须项VoiceCommandUserMessage msgRepeat = new VoiceCommandUserMessage();msgRepeat.DisplayMessage = msgRepeat.SpokenMessage = "请选择你要收藏的乐器。";// 把消息发回到小娜面板,待用户选择VoiceCommandResponse response = VoiceCommandResponse.CreateResponseForPrompt(msgback, msgRepeat, tiles);VoiceCommandDisambiguationResult selectedRes = await serviceConnection.RequestDisambiguationAsync(response);// 看看用户选了什么VoiceCommandContentTile selecteditem = selectedRes.SelectedItem;// 保存已选择的乐器
                    SaveSettings(selecteditem.Title);// 回传给小娜面板,报告本次操作完成msgback.DisplayMessage = msgback.SpokenMessage = "好了,你收藏了" + selecteditem.Title + "";response = VoiceCommandResponse.CreateResponse(msgback);await serviceConnection.ReportSuccessAsync(response);taskDerral.Complete();}}

SaveSettings方法是把用户选择的收藏保存到应用程序本地设置中,以便在前台应用中访问。

        private void SaveSettings(object value){ApplicationDataContainer data = ApplicationData.Current.LocalSettings;data.Values["fav"] = value;}

在调用RequestDisambiguationAsync方法向小娜面板添加可供选择的列表项时,一定要注意一点,作为方法参数的VoiceCommandResponse实例一定要使用CreateResponseForPrompt静态方法来创建,因为上面说过,提供有待用户确认的交互有两类:一类是yes or no,另一类就是从列表中选一项。此处就是后者。

这里老周也定义了一个BaseData类,用来产生显示在小娜面板上的项的图标,用VoiceCommandContentTile类来封装,每个VoiceCommandContentTile实例就是一个列表项,显示的格式由ContentTileType属性来指定,比如显示纯文本,还是显示图标加文本,为了让大家看清楚老周的收藏品,此处选用图标 + 文本的方式呈现。

    internal class BaseData{public static async Task<IEnumerable<VoiceCommandContentTile>> GetData(){IList<VoiceCommandContentTile> tiles = new List<VoiceCommandContentTile>();// 获取数据var filedatas = await GetFiles();// 添加磁块列表for (uint n = 0; n < filedatas.Length; n++){if (tiles.Count >= VoiceCommandResponse.MaxSupportedVoiceCommandContentTiles){break;}VoiceCommandContentTile tile = new VoiceCommandContentTile();tile.ContentTileType = VoiceCommandContentTileType.TitleWith68x68IconAndText;tile.Image = filedatas[n].Item1;tile.Title = filedatas[n].Item2;tile.TextLine1 = filedatas[n].Item3;tiles.Add(tile);}return tiles.ToArray(); ;}private async static Task<Tuple<StorageFile, string, string>[]> GetFiles(){string uh = "ms-appx:///Assets/";// 笛子Uri u1 = new Uri(uh + "笛子.png");//Uri u2 = new Uri(uh + "鼓.png");// 大提琴Uri u3 = new Uri(uh + "大提琴.png");// 二胡Uri u4 = new Uri(uh + "二胡.png");// 古琴Uri u5 = new Uri(uh + "古琴.png");// 获取文件对象StorageFile imgFile1 = await StorageFile.GetFileFromApplicationUriAsync(u1);StorageFile imgFile2 = await StorageFile.GetFileFromApplicationUriAsync(u2);StorageFile imgFile3 = await StorageFile.GetFileFromApplicationUriAsync(u3);StorageFile imgFile4 = await StorageFile.GetFileFromApplicationUriAsync(u4);StorageFile imgFile5 = await StorageFile.GetFileFromApplicationUriAsync(u5);// 创建三元组列表Tuple<StorageFile, string, string> item1 = new Tuple<StorageFile, string, string>(imgFile1, "笛子", "声音空远悠扬,灵动飘逸。");Tuple<StorageFile, string, string> item2 = new Tuple<StorageFile, string, string>(imgFile2, "", "乐声雄浑,劲力深透。");Tuple<StorageFile, string, string> item3 = new Tuple<StorageFile, string, string>(imgFile3, "大提琴", "音质宏厚。");Tuple<StorageFile, string, string> item4 = new Tuple<StorageFile, string, string>(imgFile4, "二胡", "意绵绵,略带凄婉。");Tuple<StorageFile, string, string> item5 = new Tuple<StorageFile, string, string>(imgFile5, "古琴", "音质沉厚,古朴淡雅,可传情达意。");return new Tuple<StorageFile, string, string>[] { item1, item2, item3, item4, item5 };}}


4、回到主项目,引用刚才写完的后台任务。有的朋友说后台任务不起作用,如果后台类没问题的话,可能的两个问题是:a、主项目没有引用后台任务类所在的项目;b、清单文件没有配置好。

5、最后,不要忘了配置清单文件,打开Package.appxmanifest文件,找到Application节点。

      <Extensions><uap:Extension Category="windows.appService" EntryPoint="BgService.BTask"><uap:AppService Name="vcfav"/></uap:Extension></Extensions>

扩展点的Category属性要指定windows.appService,表示扩展类型为App Service,EntryPoint指定入口点,即后台任务类的名字,包括命名空间和类型名。

在App类的OnLaunched方法中,记得安装VCD文件。

            StorageFile vcdfile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///vcd.xml"));await VoiceCommandDefinitionManager.InstallCommandDefinitionsFromStorageFileAsync(vcdfile);


现在,你可以测试了。运行应用程序,然后对着小娜说“收藏乐器 显示列表”,然后给出选择列表。

识别后,显示操作结果。

源代码下载地址:http://files.cnblogs.com/files/tcjiaan/VoicecmdWithrespApp.zip

相关文章:

Maya 2022中的硬表面建模技术学习视频教程

Maya 2022中的硬表面建模 信息: 使用正确的拓扑和边流在Maya中建模硬曲面对象。 你会学到什么 硬质表面工具和技术 细分工作流程 边缘流动控制 正确拓扑 材料设置 Studio Lightning 渲染 持续时间16小时30分钟 1280X720 MP4 大小解压后&#xff1a;11.5G 语言&#xff1a;英…

六年级小学python第四讲_python第四讲

列表的排序 升序&#xff1a;从小到大的排序 降序:从大到小的排序 示例&#xff1a; num_list [120,250,11,44,77,45,22,390] num_list.sort() # 升序 - 从小到大 print(num_list) # 对列表本身做了修改 num_list.sort(reverseTrue)#降序 为False#升序 print(num_list) 反转 p…

android之AlertDialog 点击其它区域自己主动消失

遇到一个问题记录下来&#xff0c;在开发中使用了AlertDialog&#xff0c;想点击屏幕其它区域的时候让这个dialog消失&#xff0c;一開始不做不论什么设置&#xff0c;在小米手机能够正常显示&#xff0c;可是在三星中却有问题。后来发现少了一个属性&#xff1a; View dilaogV…

中级实训第一天的自学报告

目录【阅读时间&#xff1a;约10分钟】中级实训第一天的自学报告姓名&#xff1a;隐藏敏感信息 学号&#xff1a;隐藏敏感信息一、Vi/Vim二、Java三、Ant四、Junit【附加】五、SonarQube【附加】六、 编译运行BugRunner七、 总结中级实训第一天的自学报告 姓名&#xff1a;隐藏…

完整的Blender三维课程:素描到三维艺术的初学者

使用Blender创建3D艺术。初级课程 你会学到什么 使用Blender并理解它的界面 创建3D模型 创建您自己的材料 布料仿真、纹理和雕刻 第三种解释的相机法则 照相机景深 灯光设置 渲染 如何使用参考素材进行3D素描和建模&#xff1f;参考镜头也包括在内。 课程中包含所有章节场景文…

VirtualBox: Effective UID is not root

为什么80%的码农都做不了架构师&#xff1f;>>> 桌面上运行virtualbox出错: The virtual machine xp has terminated unexpectedly during startup with exit code 1 (0x1). Effective UID is not root(euid1000 egid482 uid1000 gid482)(rc-10) Please try reinst…

ironpython 教程_「ironpython」VS2017 IronPython做界面

本人开始做毕设了&#xff0c;但老师说工具要有界面&#xff0c;所以就开始找Python做界面的东西……之前做过C#的界面&#xff0c;脱拉拽很快界面就完成了&#xff0c;后来我查了下IronPython是用C#写的python解释器&#xff0c;也可以脱拉拽做界面&#xff0c;于是就开始尝试…

4、jQuery实现的全选、反选和不选功能

2019独角兽企业重金招聘Python工程师标准>>> 这个地址更权威&#xff1a;最好的选择&#xff1a;http://www.sucaihuo.com/js/10.html <html><head><title>TODO supply a title</title><meta charset"UTF-8"><meta name…

构建自己的PHP框架--构建缓存组件(1)

作为一个框架&#xff0c;我们还没有相应的缓存组件&#xff0c;下面我们就来构建我们的缓存组件。 先来定义一下接口&#xff0c;在 src 文件夹下创建 cache 文件夹&#xff0c;在cache文件夹下创建 CacheInterface.php 文件&#xff0c;其中定义 Cache 相应的接口&#xff0c…

基于Golang的CLI 命令行程序开发

基于Golang的CLI 命令行程序开发 【阅读时间&#xff1a;约15分钟】一. CLI 命令行程序概述二. 系统环境&项目介绍&开发准备1.系统环境2.项目介绍3.开发准备三.具体程序设计及Golang代码实现1.selpg的程序结构2.导入的库3.sp_args结构体4.全局变量4.main函数5.process_…

Photoshop创造氛围照片合成视频教程含素材

数百个高分辨率工具和9个完整项目&#xff01; 这个包包含开始创建史诗大气合成所需的一切-超过四个小时的基于项目的深入教程和超过400个合成工具。 大小解压后&#xff1a;10.7G 含课程素材文件 1920X1080 mp4 语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机…

java c++的区别_Java语言与C、C++之间的区别?

小伙伴你知道吗&#xff1f;Java是由C开发而来的&#xff0c;并且在当时一直被搁置。随着Java语言的崛起那么Java和C/C有什么不同和相同之处呢&#xff1f;通过上述我们知道那Java前身是C&#xff0c;并且保留了C的大部分内容&#xff0c;其编程方式也类似于C。但Java的句法更清…

Android编程获取网络连接状态及调用网络配置界面

获取网络连接状态 随着3G和Wifi的推广&#xff0c;越来越多的Android应用程序需要调用网络资源&#xff0c;检测网络连接状态也就成为网络应用程序所必备的功能。 Android平台提供了ConnectivityManager 类&#xff0c;用于网络连接状态的检测。 Android开发文档这样描述Connec…

学习在Unity中创建一个动作RPG游戏

游戏开发变得简单。使用Unity学习C#并创建您自己的动作角色扮演游戏&#xff01; 你会学到什么 学习C#&#xff0c;一种现代通用的编程语言。 了解Unity中2D发展的能力。 发展强大的和可移植的解决问题的技能。 了解游戏开发流程。 了解面向对象编程在实践中是如何工作的。 Le…

python数组对应元素相乘_python的几种矩阵相乘的公式详解

1. 同线性代数中矩阵乘法的定义&#xff1a; np.dot() np.dot(A, B)&#xff1a;对于二维矩阵&#xff0c;计算真正意义上的矩阵乘积&#xff0c;同线性代数中矩阵乘法的定义。对于一维矩阵&#xff0c;计算两者的内积。见如下Python代码&#xff1a; import numpy as np # 2-D…

c#属性中的get和set属性

get是给属性赋值&#xff0c;set是取属性的值。 get、set用法&#xff1a; 一是隐藏组件或类内部的真是成员&#xff1b; 二是用来建立约束的&#xff0c;比如&#xff0c;实现“有我没你”这种约束&#xff1b; 三是用来响应属性变化事件&#xff0c;当属性变化是做某事&#…

基于Golang的监听读取配置文件的程序包开发——simpleConfig_v1

基于Golang的监听&读取配置文件的程序包开发——simpleConfig_v1 【阅读时间&#xff1a;约10分钟】 一、配置文件概述二、系统环境&项目介绍1.系统环境2.项目的任务要求三、具体程序设计及Golang代码实现1. 数据结构2. init函数模块3.listen函数模块4.watch函数模块四…

如何在Mac环境下搭建svn服务器端环境

为什么80%的码农都做不了架构师&#xff1f;>>> 在Windows环境中&#xff0c;我们一般使用TortoiseSVN来搭建svn环境。在Mac环境下&#xff0c;由于Mac自带了svn的服务器端和客户端功能&#xff0c;所以我们可以在不装任何第三方软件的前提下使用svn功能&#xff0…

kitbash贫民区三维场景模型 Kitbash3d – Favelas

参观临时城市中心 想象一下新兴的后世界末日城市中心&#xff0c;这里有大量的临时住所、建筑群、小屋、道具和固定装置。用一系列非常详细的废弃街区快速构建您的场景&#xff0c;并用波纹铁、水箱、折叠椅和劣质电线进一步修饰它们。从足球场到摇摇欲坠的码头&#xff0c;每一…

python编程代码示例_python编程线性回归代码示例

用python进行线性回归分析非常方便&#xff0c;有现成的库可以使用比如&#xff1a;numpy.linalog.lstsq例子、scipy.stats.linregress例子、pandas.ols例子等。 不过本文使用sklearn库的linear_model.LinearRegression&#xff0c;支持任意维度&#xff0c;非常好用。 一、二维…

单例模式的两种实现方式对比:DCL (double check idiom)双重检查 和 lazy initialization holder class(静态内部类)...

首先这两种方式都是延迟初始化机制&#xff0c;就是当要用到的时候再去初始化。 但是Effective Java书中说过&#xff1a;除非绝对必要&#xff0c;否则就不要这么做。 1. DCL (double checked locking&#xff09;双重检查&#xff1a; 如果出于性能的考虑而需要对实例域(注意…

【golang程序包推荐分享】go-ini、viper、godoc

【golang程序包推荐&分享】go-ini、viper、godoc一、go-ini1.程序包简介2.下载安装3.简单使用【截取自官网】二、viper1.程序包简介2.下载安装3.简单使用三、godoc1.程序包简介2.下载安装3.简单使用一、go-ini 1.程序包简介 ini 是常用的配置文件格式&#xff0c;而go-in…

Request To JavaBean(请求对象转换为JavaBean对象)

背景: 经常要从request等对象取出值来赋入bean中&#xff0c;如果不用MVC框架的绑定功能的话,麻烦 一 参考资料 1 http://jc-dreaming.iteye.com/blog/563893 2 http://www.iteye.com/topic/76043 3 http://xubindehao.iteye.com/blog/754807 4 http://javafenger.iteye.com/b…

在Substance Designer中创建砖墙视频教程

学习在Substance Designer中创建复杂材料的高级技术。 如果你想进入游戏行业&#xff0c;想学习如何创建高质量的纹理和学习物质设计&#xff0c;那么这个课程是给你的。 我设计了这个课程&#xff0c;从一开始就带你&#xff0c;教你我用来创建AAA纹理的3个步骤:图案&#xff…

python requests 动态加载_python requests 高级用法

HTTP动词 Requests 提供了几乎所有HTTP动词的功能&#xff1a;GET、OPTIONS、HEAD、POST、PUT、PATCH、DELETE。以下内容为使用 Requests 中的这些动词以及 Github API 提供了详细示例。 我将从最常使用的动词 GET 开始。HTTP GET 是一个幂等方法&#xff0c;从给定的 URL 返回…

redis配置开机启动

2019独角兽企业重金招聘Python工程师标准>>> 一、下载安装 去http://download.redis.io/releases/现在最新的redis版本解压 tar zxvf xxx.tar.gz编译进入到解压开的目录&#xff0c;执行&#xff1a;make && make install(可选)添加到bin目录cp redis-serve…

Docker exec命令详细使用指南

Docker exec命令是Docker提供的一个强大工具,用于在正在运行的容器中执行命令。本文将详细介绍Docker exec命令的用法和示例,帮助大家更好地理解和使用这个命令。Docker是一种流行的容器化平台,允许我们在容器中运行应用程序。有时候,在容器内执行命令可以帮助我们调试、排查问题或进行其他操作。这就是Docker exec命令发挥作用的时候。本文详细介绍了Docker exec命令的用法和示例。

Docker网络详解

如何自定义一个网络?查看新创键的mynet详细信息:# 创建两个使用相同自定义网络的容器# 测试容器互连^C^C。

Django Python:完整的BUNDLE + Django真实项目2021

Django和python Bundle:从学习python的所有基础知识到高级python再到UI设计TKINTER&#xff0c;然后是Django 你会学到: 学习编程的基础知识 学习Python编程语言 学习Django & Bootstrap框架 为真实世界的Python程序编写代码 用Python创建一个真实世界的网站 学习使用TKIn…

鱼眼相机标定_鱼眼相机模型(二)

前言在介绍其他相机模型之前&#xff0c;可以先看一下kalibr支持标定的相机模型&#xff08;kalibr可以标定的相机模型&#xff09;&#xff0c;这里的相机模型一共有4种&#xff0c;针孔相机模型&#xff0c;全景相机模型&#xff0c;Double sphere相机模型还有EUCM。其中EUCM…