Siri介绍
Siri是一款苹果 iOS 系统提供的智能语音助手软件,它的全名是Speech Interpretation and Recognition Interface。在WWDC 2016上,苹果开放了Siri的 API,开发者们可以利用SiriKit将自己的服务提供给用户。
支持 iOS 10.0+;
官方文档:https://developer.apple.com/documentation/sirikit;
以下内容均是对官方文档的解析!
概念概览
Domain - 被苹果划分的不同业务领域,每个领域中可以执行不同的任务
Intent - 领域中的任务或意图指令
Domains
VoIP Calling - 语音通信相关,如微信、Facebook Messager、Line等;
Payments - 适用于支付类应用,如PayPal、支付宝等;
Photo - 与图库相关应用,如Instagram等;
Workouts - 运动健康类应用,如Strava、NikeRun、野兽骑行等;
Ride booking - 适用于出行类应用,如Uber、滴滴打车等;
CarPlay(automotive vendors only)- 车载及自动驾驶相关,尚不明晰
Restarurant reservations(Requires addtional support from Apple) - 酒店服务类,具体需求上不明晰
Intents
VoIP Calling
Start an audio call -开始语音通话
Start a video call - 开始视频通话
Search the user’s call history -搜寻通话历史
Messaging
Send a message
Search for messages
Set attributes on a message
Photos
Search for photos
Play a photo slideshow
Payments
Send a payment to another user
Request a payment from another user
Workouts
Start a workout
Pause a workout
Resume a workout
End a workout
Cancel a workout
Ride Booking
Get a list of available rides (Maps only)
Book a ride
Get the status of a booked ride
CarPlay
Change the audio source
Change the climate control settings
Change the defroster settings
Saving vehicle settings to a profile
Restoring vehicle settings from a profile
Change the seat temperature
Change the radio station
Restaurant Reservations
Get the user’s current restaurant reservations
Get information about the user to associate with a booking.
Get default values to use when requesting reservation times.
Get the reservation times that are currently available.
Book a reservation for the user.
简单来说:
开发功能基本上就是在苹果提供的这些领域(Domain)上,在App开发中需要开发哪种领域的功能,就要在对应的plist文件中添加对应的Intent支持;
当然SiriKit不是万能的,语义的处理流程要按照苹果的套路来(应用领域,意图),界面UI也套路来,不能调用App内部页面。
那什么是Intent呢?
了解Intent,首先要清楚SiriKit的外部工作流程:
1)、Siri完成语音识别和语义分析;
2)、会根据你词汇中的关键词识别出你属于上述领域(Domain)中的哪一种;
3)、然后将结构化语音分析结果打包成一个某个领域(Domain)的意图(Intent);
4)、接着交给支持这个意图(Intent)的第三方应用,第三方应用被启动,从传入的Intent中获取相应的信息,完成操作。
整个宏观的流程如下图:
例如,上图演示中提到了的例句 “用演示发消息给小明",
领域 (Domain):Messaging
意图 (Intent):Send a message (INSendMessageIntent)
意图参数 (Intent Parameter)
收件人(recipients):小明
消息内容(content):空
备注:(appname:演示。如果没有消息内容,这时就会涉及到Sikit的API中提供的处理机制,这个机制会调Siri反问你要发送什么内容,这个就涉及到下文提到的SiriKit相关功能和处理流程,会有不同的扩展和类在处理这个问题)
项目集成
1.先创建对应的target:
根据需求确认是否需要 UI Extension ,该target类似于富文本推送;
生成结果:
2.定义需要支持的Intent类型:
支持类型的具体对应内容可参考官方文档;
IntentsRestrictedWhileLocked是可选项,用来控制锁屏状态下,对不同命令的响应行为。
3.添加对主应用Siri权限支持
在主应用Info.plist文件中添加NSSiriUsageDescription Key,该key用来标记应用与Extension所沟通的数据类型,用于告知用户,你的应用为何要支持Siri的描述信息,比如Workout类应用,我可以这么写:“健身锻炼的信息会发送到Siri,更快捷的记录健身数据”
仅仅添加NSSiriUsageDescription这个Key到Info.plist文件中是不够的,当应用第一次启动时,我们需要用户打开应用的Siri支持权限,默认情况下,这个权限是关闭的,所以,需要我们通过调用INPreferences的类方法equestSiriAuthorization: 来通知用户打开Siri权限支持。
4.一个标准的意图语音被Siri识别之后,SiriKit会先进入一个继承于INExtension的指定意图流程入口(NSExtensionPrincipalClass)类IntentHandler.m(默认类)。下面在这个相关类会处理整个流程:
意图的生命周期如下图文描述:
一个典型的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对象确认处理结果然后执显示结果给用户看。
4.发消息INSendMessageIntent的意图对象
具体在各个阶段的方法里怎么代码实现,主要是要理解INSendMessageIntent的对象属性,通过解析对象,可以在各个阶段用获取到的对象进行相关程序逻辑编码。如:
对象名称类型备注
通过流程方法里获取到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的数据。
5.根据流程方法处理之后,与主程序通信方式
轻量级通信可采用这个办法:
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 *)userActivityrestorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler { if ([userActivity.interaction.intent isKindOfClass:[INSendMessageIntent class]]) { INSendMessageIntent *intent = (INSendMessageIntent *)(userActivity.interaction.intent); NSLog(@"%@",[[intent.recipients lastObject] displayName]); } return YES;}
6.自定义界面(Intent UI Extension)
运用SiriKit开发相关功能,UI是依赖于Intent UI Extension,SiriKit并不能从系统层面调用App内部UI,只能调用打开App和SirKit自定义UI。
系统创建了ViewController,加载视图,调用viewDidLoad方法并且调用了INUIHostedViewControlling协议的configureWithInteraction:context:completion:方法,传递了一个交互对象,用于配置界面。 当配置完成后,ViewController就会展示在Siri或者Maps应用界面的空白部分。这时会调用viewWillAppear/viewDidAppear方法。
当视图消失时,也会调用生命周期的viewWillDisappear/viewDidDisappear方法。
类似于富文本推送的 UI 界面构造方式。
关于控制器的使用,苹果给出了几点注意事项:
1.切换子控制器来展示不同类型的内容。 你的Intents UI扩展只有一个主视图控制器,如果你想为不同的Intents展示不同的内容,你需要使用不同的视图。可以在configureWithInteraction:context:completion:这个方法里面,根据提供的intentObject来创建不同的子视图。
2.在你的视图控制器可用的期间,动态调整内容。 在viewDidAppear:方法里面才开始启动动画,在viewWillDisappear: 方法里面要结束动画。
3.尽快的配置好你的视图控制器,这样Siri才能更快的展示它。 你的视图控制器也许不会在屏幕上停留太久,所以尽量利用本地资源以及提供的INInteraction对象来配置你的设置。如果你需要从服务器拉取更多的信息,请异步完成,并在稍后再更新你的界面。
4.请不要在界面里面展示广告。你可以展示你自己的品牌信息,但是你不能够加入其它广告。
参考文档:
https://www.jianshu.com/p/0881bb0ff538;
https://www.jianshu.com/p/eb15faeb4a66;
https://www.jianshu.com/p/d0e157627f3a;