iOS开发-Siri预研

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;

你可能感兴趣的:(iOS开发-Siri预研)