iOS 探讨之 初探SiriKit

阐述

最近研究了一下SiriKit,感觉有点意思,记录并与大家探讨一下。

工欲善其事必先利其器,在研究SiriKit模块时苹果官方介绍通篇充斥着Intent、Resolve、Confirm等词汇,让英语未过六级的我感到无比吃力。感觉词汇还是有必要给大家介绍一下,顺便统一单词说法以便大家能够看懂后续内容。

词汇确认:  (箭头后为文章所用含义)

Intent             意图,想法,倾向        —>        意图

Resolve         解决,决心,分解        —>        解析

Confirm         确认,确定,批准        —>        确认

Handle          处理,操作,搬运         —>        处理

探讨

1 程序拓展类型

在开始之前,首先介绍一下苹果给我们提供的与SiriKit开发相关的拓展。

这两类拓展都是用来附加额外的业务逻辑处理,当然并不是必须要集成到主程序中(后续有介绍)。

拓展种类:

  • Intents App Extension              Siri意图处理拓展

  • Intents UI App Extension         Siri意图定制界面拓展(可以使用苹果提供的原生界面,或者自定义界面)

2 用户 - Siri - [拓展] - 应用 服务流程

2.1 图示层次

上图中的Intents App Extension、Your App services不是必要的,在Siri不需要用户进一步提供信息时可直接与应用交流,当然我们在处理复杂业务的时候(如签到业务需要在Siri界面判断登录逻辑),是需要集成拓展的。

2.2 代码层次

当用户向Siri发出请求时,SiriKit会首先通过每个应用的Info.plist文件找到意图(Intent)所属的应用。随后判断该意图(Intent)添加方式是否为直接捐献(Donate)。

若为直接捐献,SiriKit会直接启动应用并在AppDelegate的application(application: continue userActivity: restorationHandler: ) 方法中给开发者通知。

若相反的话,SiriKit会加载当前应用的所有Siri意图处理拓展( Intents App Extension ), 并通过各自拓展的Info.plist文件中NSExtension-NSExtensionAttributes-IntentsSupported对应数组进行匹配,找到对应的拓展并创建该拓展所绑定的INExtension子类实例。INExtension子类实例会调用 handler(for: ) 方法将用户请求分发给开发者针对每个业务所编写的IntentHandler对象。

(该IntentHander不是指系统直接生成的文件,而是指我们针对每个Intent编写的并且遵守每个Intent的IntentHandling协议的类文件。IntentHandling协议定义了处理Intent的必要方法)

这里的INExtension子类相当于上图中的程序服务组合包(App services),而每个Intent的专属IntentHandler相当于单个服务的处理对象。

注意:

SiriKit处理同一个意图(Intent)请求时,会多次创建对应服务的专属IntentHander对象来执行方法,而不是直接生成一个长久的对象来持续调用,所以不要在对应服务的IntentHandler对象中存储状态信息。

(https://developer.apple.com/documentation/sirikit/dispatching_intents_to_handler_objects)

3 单个服务IntentHandler执行过程

Intent的专属IntentHandler对象处理用户请求时会大致分三个阶段(苹果封装的Intent为三个阶段,自定义的Intent分为两个阶段):

  • Resolve  参数解析(自定义Intent不包含此阶段)

  • Confirm  最终确认(参数和环境)  

  • Handle   业务处理

3.1 解析Intent参数

官方描述:

Validate the parameters of an intent and make sure that you have the information you need to continue.

本人理解: 

对Intent所携带的参数分别验证,确认参数信息是否明确,或者说是确认这个参数在下一阶段是否能够使用。

官方描述:

When the user talks to Siri, Siri converts the user’s spoken commands into actionable data and places that data in an intent object.

During resolution, SiriKit prompts you to verify each parameter individually by calling the resolution methods of your handler object.

In each method, you validate the provided data and create a resolution result object indicating your success of failure in resolving the parameter.

SiriKit uses your resolution result object to determine how to proceed.

本人理解:

当用户对Siri发出请求时,Siri会将用户语句转化成程序可以处理的数据,并把这些数据存放在与之匹配的Intent对象中。

在解析(Resolve)阶段,SiriKit会调用开发者所编写的校验函数来分别验证参数的完整性及明确性。

校验方法的返回参数表示解析是否成功,SiriKit用返回的结果来决定后续的处理方式。

Resolve结果分类

INIntentResolutionResult 解析结果类(除了Success和not require 其它类型的Siri都会让用户提供更多信息)

Success                                 成功  does not require further user interactions

Not required                           不是必须的  does not require further user interactions

Needs disambiguation           需要区分  prompt the user to select one of the provided options

Needs confirmation               需要确认  prompt the user to confirm the value

Value required                        需要数据  prompt the user for a value

Unsupported                         不支持 notify the user that the value is not supported

(https://developer.apple.com/documentation/sirikit/resolving_and_handling_intents/resolving_the_parameters_of_an_intent)

涉及类及协议 :

类名: INExtension

The INExtension class is the principal class of your Intents extension, which provides infomation to SiriKit。

Your extension object acts like a dispatcher, providing SiriKit with objects it needs to resolve and handle request.

程序拓展的主要类,负责给SiriKit提供一些信息。该对象扮演者分发者的形象,负责给Siri提供能够处理用户请求的对象。

协议名: INIntentHanderProviding

程序拓展扮演者需要实现的协议

类名: INIntent

A request for you to fulfill using your Intents extension.

一个需要你用程序拓展去实现的请求。

3.2 确认Intent细节

The confirmation phase is your chance to perform any final validation of the intent parameters and to verify that any needed services are available.

After performing your final validation, you provide SiriKit with a response object indicating how you plan to handle the request.

Confirm阶段是用来确认参数是否合适,及其它各项基本服务(网络环境)是否准备好的最后阶段。 

当Confirm阶段结束后,开发者需要向Siri提交一个回应对象来表示是否准备好处理当前用户的Intent请求。

提示:

如果在这个阶段决定直接跳转应用,可以使用code为.continue的回应对象,并且可以自定义NSUserActivity,将额外信息放入它的userInfo属性中,作为返回对象的参数传递给主应用。

(https://developer.apple.com/documentation/sirikit/resolving_and_handling_intents/confirming_the_details_of_an_intent)

涉及类:

INIntentResponse  请求的回应

3.3 处理Intent业务

When handing an intent, you do the following:

  • Perform the task associated with the intent

  • Return a response object with information about what you did

You handle most intents directly from your Intents app extension, but in some case you may ask SiriKit to let your app handle the request.

当开发者处理倾向时,需要做到: 处理对应的业务并返回结果告诉SiriKit下一步要执行什么。

大多数情况下我们通过扩展就可以完成相应的业务,但也有一些场景需要我们通知Siri启动应用,让应用去完成其余的业务逻辑。

处理Intent的一些Tips:

Always include as much information as possible in your responses.     尽可能给返回的对象填满已知的信息

Configure data objects fully before assigning them to the response object.   处理方法所使用的参数,一般情况下对应的属性都默认使用copy,如果修改这个属性并没有同步到原对象中,参数里的对应属性值并不会随之改变,所以开发者最好把参数对应的属性进行修改。

Return your response objects within a few seconds.   尽可能用很少的时间来返回处理结果。(Siri与用户的交互界面不可能等那么长时间,如果真需要可以使用 in progress状态)

Use custom user activity objects to support deep linking into your app. 尽可能使用自定义UserActivity来完成应用的后续操作

Always handle user activity objects in your parent app.   尽可能把传递给本地应用的UserActivity处理完。

注意点: SiriKit有可能使用当前用户的通讯录,如果当前应用没有对应的权限,在一些场景中将无法解析完整语句。(如聊天应用处理人名)

(https://developer.apple.com/documentation/sirikit/resolving_and_handling_intents/handling_an_intent)

4 Intent应用场景

SiriKit groups intents to domains based on the type of app that is likely to support them.

苹果的SiriKit基于各个场景封装出对应的处理方案。

如:

Messaging                              消息类

Lists and Notes                      标注、计划类

Workouts                               日常锻炼类

Payments                               支付类

VoIP Calling                            电话呼叫类

Visual Codes                          展示二维码类

Photos                                    图片类

Ride Booking                          预定座驾类

Car Commands                      智能汽车类

CarPlay                                   苹果汽车应用类

Restaurant Reservations        餐馆预定类

除了这里官方提供的处理方案外,我们也可以通过自定义Intent来实现其它功能,如捷径Shortcuts。

5 Shortcuts 捷径

5.1 Donating Shortcuts (捐献捷径)

Tell Siri about shortcuts to actions that the user performed in your app.

通知Siri你在应用中所绑定的动作

5.2 捷径实现方式

  • NSUserActivity      involve a view within your app                                    直接与应用交互 

  • INInteraction          involve a task the user accomplish with your app      可以通过Siri处理完成一个绑定的业务

具体实现:

NSUserActivity   调用 becomeCurrent() 方法,或者使它成为当前UIViewController/UIResponder的 .activity属性

INInteraction       调用INInteraction实例的 donate( completion: ) 方法

注意: INInteraction 默认情况下是直接打开APP, 不过可以使用 Intents App Extension 来实现Siri交互处理。

注意: 

Don’t donate intents handled by your Intent App Extension. Siri already knows about those intents and will consider them when predicting suggestions in the future.

不要把将要使用Intent App Extension 处理额外业务的Intent进行捐献。 Siri 已经知道这些Intents并且考虑将要去处理他们。

( https://developer.apple.com/documentation/sirikit/soup_chef_accelerating_app_interactions_with_shortcuts )

6 Intents UI App Extension     

6.1 Info.plist 相关 (NSExtension)

NSExtensionAttributes-IntentsSupported        设置Intent的调用界面权限

NSExtensionMainStoryboardKey                     storyboard文件名称        

NSExtensionPrincipalClassKey                        不用storyboard时,填写ViewController类名

6.2 要求和限制

ViewController remain part of the foreground Siri or Maps interface until the user dismisses it.

自定义的界面在不接受任何干扰的情况下,会一直存在。(干扰包括外界语音)

ViewController do not receive touch events or any other events while they are onscreen, and you cannot add gesture recognizers to them.

自定义的界面不接受任何的触摸事件,你也不能给他们添加手势。

6.3 自定义ViewController生命周期

6.4 苹果建议

Incorporate your brand into your interface.   添加符合应用风格的图片文字

Configure any animated content to run only when your view controller is visible. 图形动画最好在界面显示阶段进行

Configure your view controller’s view as quickly as possible so that Siri can display it. 配置当前界面时间尽可能短

Configure your interface using only the provided interaction object. 配置界面最好是使用interaction所携带的数据

Do not include advertising in your interface. 不要打广告

Return a zero size when you want to hide your custom interface 当你要隐藏的时候尺寸返回zero

Do not include a map view when your view controller is shown in a Maps context. 不要在Map上下文继续添加Map

Use child view controllers to switch between different types of content. 最好用子ViewController来区分界面

1 Siri权限请求

Warning: You Request authorization from your iOS app, not your extension .

(注意: 请求权限的对象应该是当前应用,而不是拓展)

步骤:

1 Enable the Siri capability

2 Configure your Info.plist      NSSiriUsageDescription

3 Request authorization from your iOS app.    INPreferences 的类方法 requestSiriAuthorization(_: )

注意项:

当用户的语句解析成Intent时,系统会优先选择Intents App Extension中Info.plist文件 IntentsSupportedKey数组靠前的Intent。

用户第一次安装的时候,Extension的设置可能没有效果,Siri需要几分钟来适应。 另外修改 Extension的Info.plist也会有这种情况。

涉及类:

类名: INPreferences

The preferences and authorization related to using SiriKit.

与SiriKit的配置和权限相关

requestSiriAuthorization(_ : )  请求Siri的权限,不过只有在第一次的时候才会有授权提示,后面都不会出现提示

siriAuthorizationStatus() 获取当前app的siri权限状态

INSiriAuthorizationStatus 权限状态 

  • notDetermined 没有请求过

  • restricted 收到限制(用户没有请求但是在系统中用户将Siri总开关关闭)

  • denied 拒绝

  • authorized  授权

siriLanguageCode() siri的语言环境

猜你喜欢

转载自blog.csdn.net/yanglei3kyou/article/details/85044516