一、SiriKit介绍
Siri
是一款苹果 iOS 系统提供的智能语音助手软件,它的全名是 Speech Interpretation and Recognition Interface
。2011年 Siri
第一次以 iOS 内置软件的形式随 iPhone 4s
一同问世之后,终于在 WWDC 2016
上,苹果开放了Siri
的 API,开发者们可以利用SiriKit
将自己的服务提供给用户。
备注:SiriKit
是系统调用,是一个语义处理结合扩展UI
的框架,不是语音转文字的框架。SiriExtensionDemo
1、SiriKit提供11类服务领域,详情请见苹果官方文档
SiriKit 服务领域(Domain) | 对应的意图(Intent) |
---|---|
语音和视频通话 (VoIP calling) | INSearchCallHistoryIntent、INStartAudioCallIntent、INStartVideoCallIntent |
发送消息 (Messaging) | INSendMessageIntent |
收款或者付款 (Payments) | INSendPaymentIntent、INRequestPaymentIntent |
列表和笔记 (Lists and Notes) | INCreateNoteIntent、INAppendToNoteIntent |
视觉编码 (Visual Codes) | INGetVisualCodeIntent |
图片搜索 (Photo search) | INSearchForPhotosIntent |
管理锻炼 (Workouts) | INEndWorkoutIntent、INPauseWorkoutIntent 、INStartWorkoutIntent 、 INResumeWorkoutIntent 、INCancelWorkoutIntent |
行程预约 (Ride booking) | INRequestRideIntent、INGetRideStatusIntent、 INListRideOptionsIntent、 INGetRideStatusIntent |
车载管理 (Car Commands) | INGetCarLockStatusIntent、INSetCarLockStatusIntent、INActivateCarSignalIntent |
车载系统 (CarPlay) | INSetAudioSourceInCarIntent、 INSetClimateSettingsInCarIntent、 INSetSeatSettingsInCarIntent、INSaveProfileInCarIntent、INSetProfileInCarIntent、INSetRadioStationIntent |
餐厅订位 (Restaurant Reservations) | INBookRestaurantReservationIntent、 INGetAvailableRestaurantReservationBookingDefaultsIntent、 INGetAvailableRestaurantReservationBookingsIntent、 INGetRestaurantGuestIntent、 INGetUserCurrentRestaurantReservationBookingsIntent |
简单来说,在SiriKit
的开发功能基本上就是在苹果提供的这些领域(Domain
)上,在App开发中需要开发哪种领域的功能,就要在对应的plist
文件中添加对应的Intent
支持(具体在哪个plist文件下文有说明)那什么是Intent
?
备注:SiriKit不是万能的,语义的处理流程要按照苹果的套路来(应用领域,意图),界面UI也套路来,不能调用App内部页面,具体UI会有SiriKit的UI扩展来实现。
2、Intent的说明
要想了解Intent
,首先要清楚SiriKit
的外部工作流程:
1)、 Siri
完成语音识别和语义分析;
2)、会根据你词汇中的关键词识别出你属于上述11种领域中的哪一种;
3)、然后将结构化语音分析结果打包成一个某个领域(Domain
)的意图(Intent);
4)、接着交给支持这个意图(Intent
)的第三方应
用,第三方应用被启动,从 传入的Inten
t中获取相应的信息,完成操作。
整个宏观的流程如下图:
例如,上图演示中提到了的例句 “用演示发消息给小明",
领域 (Domain):Messaging
意图 (Intent):Send a message (INSendMessageIntent)
意图参数 (Intent Parameter)
收件人(recipients):小明
消息内容(content):空
备注:(appname:演示。如果没有消息内容,这时就会涉及到Sikit的API中提供的处理机制,这个机制会调Siri反问你要发送什么内容,这个就涉及到下文提到的SiriKit相关功能和处理流程,会有不同的扩展和类在处理这个问题)
二、SiriKit功能开发介绍
1、发消息意图API(举例)
1)、发消息INSendMessageIntent配置
涉及到SiriKit
的基本项目文件:
2)、发消息INSendMessageIntent相关协议方法
一个标准的意图语音被Siri
识别之后,SiriKit
会先进入一个继承于INExtension
的指定意图流程入口(NSExtensionPrincipalClass
)类IntentHandler.m
(默认类)。下面在这个相关类会处理整个流程:
方法列表 | 中文解释 |
---|---|
-resolveRecipientsForSendMessage:withCompletion: | 解析发送消息语义,提取意图对象 |
- resolveContentForSendMessage:withCompletion: | 解析发送消息内容方法 |
- confirmSendMessage:completion: | 确认方法 |
- handleSendMessage:completion: | 处理方法 |
意图的生命周期如下图文描述:
一个典型的Intent
事件的处理过程中有这三个步骤Resolve
、Confirm
和Handle
Resolve
阶段。在Siri
获取到用户的语音输入之后,生成一个INIntent
对象,将语音中的关键信息提取出来并且填充对应的属性。这个对象在稍后会传递给我们设置好的INExtension
子类对象进行处理,根据子类遵循的不同协议来选择不同的解决方案。Confirm
阶段。在上一个阶段通过handlerForIntent:(INIntent *)
返回了处理Intent
的对象,此阶段会依次调用confirm
打头的实例方法来判断Siri
填充的信息是否完成。匹配的判断结果包括Exactly one match
、Two or more matches
以及No match
三种情况。这个过程中可以让Siri
向用户征求更具体的参数信息。-
Handle
阶段。在confirm
方法执行完成之后,Siri
进行最后的处理阶段,生成答复对象,并且向此Intent对象确认处理结果然后执显示结果给用户看。
3)、发消息INSendMessageIntent的意图对象
具体在各个阶段的方法里怎么代码实现,主要是要理解INSendMessageIntent
的对象属性,通过解析对象,可以在各个阶段用获取到的对象进行相关程序逻辑编码。如:
对象名称 | 类型 | 备注 |
---|---|---|
recipients |
NSArray<INPerson*> |
Contacts to whom the message should be sent. |
content |
NSString |
Body text of the message. |
groupName |
NSString |
Body text of the message. |
serviceName |
NSString |
Specified service for the message. |
sender |
INPerson |
The person, or account, sending the message. |
通过流程方法里获取到INSendMessageIntent
对象进行解析,匹配,处理,这个过程还涉及到返回的处理。每一个解析方法都需要得到一个INIntentResolutionResult
类型的实例,用来保存校验结果。
INIntentResolutionResult
及其子类有不同的构造方法生成不同类型的结果,用来指定和Siri的交互。
值类型 INIntentResolutionResult
|
说明 |
---|---|
+ (instancetype)needsValue; |
需要一个值,Siri会提示用户给一个值 |
+ (instancetype)notRequired; |
不是必要的,是否给值都会过这个resolve |
+ (instancetype)unsupported; |
不支持的,Siri会提示用户这个值不被支持 |
+(instancetype)successWithResolvedValue:(BOOL)resolvedValue; |
成功解析 |
+(instancetype)confirmationRequiredWithValueToConfirm:(nullable NSNumber *)valueToConfirm; |
Siri提示用户确认当前是否是一个bool值 |
当一个intent
的所有参数都成功解析了,处理程序就会向用户询问是否确认这个intent
的细节,并且提供一个建议响应。当所有参数被成功解析后,或者在不要求所有参数进行解析,那么就认为是解析成功。
在确认期间,就可以执行所有的intent
参数的附加验证,以确保你可以使用该信息来执行所请求的服务。如果之前的解析函数是单元测试,那么这个确认函数就是集成测试,保证所有输入参数正确。
最后一个处理intent
的阶段,就是执行与这个intent
相关的动作。在-handleSendPayment:completion
函数中做相应业务逻辑,需要注意的是你在Extension
中做的修改也应当反应到App主程序当中,所以需要提供任务的数据给到App。SiriKit
提供了一个包含intent
细节(INIntent、INIntentResponse)
的InInteraction
对象,你可以使用userActivityInstance.interaction
得到它,在App启动时调用
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler
函数处理来自Extension
的数据。
4)、根据流程方法处理之后,如何与主程序通信
轻量级通信可采用这个办法:
1)、在handling
阶段在NSUserActivity
存储相应的信息,字典或字符串都行(如上handling
阶段代码)。
2)、在AppDelegate
,获取NSUserActivity
所存储的信息。
3)、发送通知给所需要的地方。
4)、接收到通知后对主程序进行相应操作。
备注:确认消息发送之后的逻辑也可以在处理阶段编码解决
有关在AppDelegate中处理SiriKit的Intent可以参考相关苹果官方文档
//AppDelegate.m
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return NO;
}
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {
if ([userActivity.interaction.intent isKindOfClass:[INSendMessageIntent class]]) {
INSendMessageIntent *intent = (INSendMessageIntent *)(userActivity.interaction.intent);
NSLog(@"%@",[[intent.recipients lastObject] displayName]);
}
return YES;
}
2、自定义界面(Intent UI Extension)
运用SiriKit开发相关功能,UI是依赖于Intent UI Extension
,SiriKit
并不能从系统层面调用App内部UI
,只能调用打开App和SirKit
自定义UI
。
系统创建了ViewController
,加载视图,调用viewDidLoad
方法并且调用了INUIHostedViewControlling
协议的configureWithInteraction:context:completion:
方法,传递了一个交互对象,用于配置界面。 当配置完成后,ViewController
就会展示在Siri
或者Maps
应用界面的空白部分。这时会调用viewWillAppear/viewDidAppea
r方法。
当视图消失时,也会调用生命周期的viewWillDisappear/viewDidDisappear
方法。
关于控制器的使用,苹果给出了几点注意事项:
- 切换子控制器来展示不同类型的内容。 你的Intents UI扩展只有一个主视图控制器,如果你想为不同的Intents展示不同的内容,你需要使用不同的视图。可以在
configureWithInteraction:context:completion:
这个方法里面,根据提供的intentObject来创建不同的子视图。
- 在你的视图控制器可用的期间,动态调整内容。 在
viewDidAppear
:方法里面才开始启动动画,在viewWillDisappear
: 方法里面要结束动画。
- 尽快的配置好你的视图控制器,这样
Siri
才能更快的展示它。 你的视图控制器也许不会在屏幕上停留太久,所以尽量利用本地资源以及提供的INInteraction
对象来配置你的设置。如果你需要从服务器拉取更多的信息,请异步完成,并在稍后再更新你的界面。
- 请不要在界面里面展示广告。你可以展示你自己的品牌信息,但是你不能够加入其它广告。
三、结束
本文Demo:SiriExtensionDemo
发消息例子:
对 Siri
说:“用演示给小明发消息”
转账例子:
对 Siri
说:“用演示转账100元给孙波”