SiriKit框架详细解析(五) —— 编程指南之Intents和Intents UI扩展(一)

版本记录

版本号 时间
V1.0 2018.09.12

前言

大家都知道随着人工智能的发展,会掀起来另外一个工业革命,而语音识别就是人工智能的初始阶段,但是每个公司做的都不一样,涉及到一系列的语音的采集和算法实现,苹果的Siri就是业界语音识别的代表性的产品。接下来的几篇我们就详细解析一下SiriKit这个框架。感兴趣的可以看下面几篇文章。
1. SiriKit框架详细解析(一)—— 基本概览(一)
2. SiriKit框架详细解析(二)—— 请求授权使用SiriKit和INPreferences类(一)
3. SiriKit框架详细解析(三)—— 创建Intents App扩展(一)
4. SiriKit框架详细解析(四)—— 构建代码以支持App扩展和将意图调度到处理对象(一)

开始

SiriKit是您通过Siri提供内容的一种方式。 它还允许您向Maps应用添加对服务的支持。 要支持SiriKit,您可以使用Intents框架和Intents UI框架来实现一个或多个扩展,然后将这些扩展包含在iOS应用程序中。 当用户通过Siri或Maps请求特定类型的服务时,系统会使用您的扩展来提供这些服务。

仅当您的应用程序实现以下类型的服务之一时才添加SiriKit支持:

  • 音频或视频通话
  • 消息
  • 支付
  • 搜索照片
  • 锻炼
  • 乘车预订

汽车制造商可以使用CarPlay intents允许用户使用语音命令控制汽车功能。

每种类型的服务代表您可以支持的功能域,每个域定义一个或多个意图供您支持。 意图是表示用户意图的对象。 Siri和Maps创建意图对象以响应用户请求,并使用任何用户指定的信息填充它们。 例如,发送消息的意图可能包括消息的接收者和内容。 您使用intent对象提供适当的响应并执行相关的任务。 有关支持的域及其意图的更多信息,请参阅Intents Domains


The Intents and Intents UI Extensions - Intents和Intents UI扩展

SiriMaps通过两种不同类型的扩展与您的应用服务进行互动:

  • Intents extension将您的应用程序内容传递给Siri和Maps,并执行与任何支持的意图相关的任务。
  • Intents UI extension为Siri或Maps界面中的内容提供自定义界面。此扩展是可选的。

您必须提供Intents扩展才能支持SiriKit。您的Intents扩展程序负责处理意图并提供Siri和Maps可用于与用户通信的信息。提供Intents UI扩展是可选的,但是通过Siri与您的应用进行交互的方式对您的用户来说似乎很熟悉。例如,Intents UI扩展可以显示横幅和其他特定于应用的信息,以强化您的应用正在提供响应。

有关用于实现Intents扩展的类的信息,请参阅Intents Framework Reference。有关用于实现Intents UI扩展的协议的信息,请参阅Intents UI Framework Reference


The Role of Siri and the Maps App - Siri和Maps应用程序的角色

Siri处理将用户的语音请求转换为扩展可以处理的可操作意图所需的语言处理和语义分析。 Siri和Maps应用程序管理所有用户交互,并使用标准系统界面向用户显示结果。 您的角色主要是提供要显示的数据。 如果您的应用程序包含Intents UI扩展,您还可以提供自定义界面来补充默认系统界面。

乘车预订和餐厅预订主要由Maps应用程序处理,尽管用户也可以使用Siri预订游乐设施。 您的Intents扩展程序处理源自Maps应用程序的交互,其处理方式与处理来自Siri的请求的方式相同。 如果您自定义用户界面,您的Intents UI扩展可以根据请求来自Siri还是Maps来进行不同的配置。


Creating the Intents Extension - 创建Intents扩展

SiriMaps通过您的Intents扩展程序与您的应用互动。 Intents扩展的入口点是INExtension对象,其唯一的工作是将Siri指向能够响应用户请求的对象。实现Intents扩展时,您经常使用三种类型的对象:

  • intent对象(intent object)定义用户的意图并包含Siri从用户收集的数据。
  • 处理程序对象(handler object)是您定义并用于解析,确认和处理意图的自定义对象。
  • 响应对象(response object)是包含对intent的响应的数据对象。

当您的扩展程序有意图处理时,Siri会询问您的INExtension对象是否有能够处理该意图的对象。处理程序对象可以是您想要的任何类型,但它必须实现处理给定意图所需的特定方法。每个intent都有一个与其处理程序必须采用的关联协议。该协议的方法分为三组:解决方法,确认方法和处理方法。您可以实现所需的方法,并向Siri提供有关您计划如何处理意图的信息。

图2-1说明了Siri与扩展中的处理程序对象之间的高级别流程。在该示例中,当用户要求使用乘车预订服务预订乘车时,Siri创建具有乘坐参数的意图对象并将其发送给处理者。处理程序将intent对象中的数据解析为可用于完成行程的值。当所有骑行参数都已解决后,Siri要求处理者确认其计划如何处理乘坐请求并执行任何最终验证。在确认阶段,处理程序提供一个响应对象,其中包含骑行的详细信息,Siri可能会向用户显示。如果用户接受了乘坐,Siri要求乘车请求处理者处理该意图。处理程序通过预订车辆并回复预订车辆的详细信息来回应。

SiriKit框架详细解析(五) —— 编程指南之Intents和Intents UI扩展(一)_第1张图片
Figure 2-1 Handling a ride request intent

有关如何创建扩展的一般信息,请参阅App Extension Programming Guide


Configuring Your Xcode Project - 配置Xcode项目

要支持SiriKit,请在您的iOS应用中添加Intents extension

1. To add an Intents extension to your app - 向您的应用添加Intents扩展程序

  • 1) 在Xcode中打开现有的iOS应用程序项目。
  • 2) 选择File > New > Target
  • 3) 从适用平台的Application Extension组中选择Intents扩展。
  • 4) 点击下一步。
  • 5) 指定扩展名称并配置语言和其他选项。如果您计划自定义Siri界面的某些部分,请启用“包含UI扩展”选项。
  • 6) 单击完成。

Xcode提供的Intents扩展模板包含一个INExtension子类供您自定义。 您可以使用该类来创建处理意图所需的处理程序对象。 Siri使用您的扩展的Info.plist文件来发现它支持的意图。 Xcode提供的Info.plist文件主要是配置的,但您必须修改它的一部分以指定扩展程序处理的意图。

2. To specify the intents that your app supports - 指定应用支持的意图

  • 1) 在Xcode中,选择Intents扩展的Info.plist文件。
  • 2) 展开NSExtensionNSExtensionAttributes键以查看IntentsSupportedIntentsRestrictedWhileLocked键。
  • 3) 在IntentsSupported键中,为计划支持的每个intent添加String项。将每个项的值设置为intent的类名。

这个key是必需的。您可以支持给定域中的所有或部分意图,并且您的扩展可以支持任意数量的域。该值必须包含扩展支持的所有intent类。

  • 4) 在IntentsRestrictedWhileLocked键中,为仅在用户设备解锁时支持的任何意图添加字符串项。将每个项的值设置为intent的类名。

此键是可选的。该值包含您需要解锁设备的intent类的子集。如果处理意图涉及访问磁盘上的受保护文件或操纵敏感用户数据,则可能在此列表中包含intent

实现扩展的行为涉及以下任务:

  • Define handler classes for each intent that you support - 为您支持的每个intent定义处理程序类。您可以为每个intent定义一个处理程序类,或者为多个Intent使用单个处理程序类。使用协议可以轻松地将任何对象转换为意图的处理程序对象。有关如何实现处理程序的信息,请参阅Resolving and Handling Intents

  • Add the custom source files that you need to perform the tasks for any supported intents - 添加为任何支持的意图执行任务所需的自定义源文件。您的扩展程序必须能够执行与任何意图相关的任务。例如,乘车预订服务的处理者必须能够预订乘车并获得有关使用该服务的乘车的信息。将任何源文件添加到您需要实现的扩展项目中;请参阅Structuring Your App’s Services

  • update the default INExtension class that Xcode provided - 更新Xcode提供的默认INExtension类。修改Xcode提供的INExtension子类的handlerForIntent:方法,以创建并返回自定义处理程序对象。有关如何实现此方法的信息,请参阅INIntentHandlerProviding Protocol Reference

  • Define any custom vocabulary that your app uses - 定义应用使用的任何自定义词汇表。以特定方式使用单词或短语的应用程序可以定义自定义词汇表文件,以帮助Siri了解自定义用法。有关如何为Siri提供应用程序自定义词汇表的信息,请参阅Specifying Custom Vocabulary

有关可用意图的列表以及为每个意图实现的关联类和协议,请参阅Intents Domains


Requesting Siri Authorization in Your iOS App - 在您的iOS应用程序中请求Siri授权

在使用Intents扩展程序之前,在注册任何特定于用户的词汇表之前,您的iOS应用程序必须请求授权才能使用Siri。 要请求授权,请执行以下操作:

  • 在应用的Info.plist文件中包含NSSiriUsageDescription键。 此键的值是一个字符串,用于描述应用程序在处理意图时向Siri发送的数据。 例如,锻炼应用程序可能会将值设置为字符串“Workout information will be sent to Siri”
  • 在应用程序执行期间的某个时刻调用INPreferences的类方法requestSiriAuthorization:

您的iOS应用首次调用requestSiriAuthorization:方法时,系统会显示一条alert弹窗,提示用户授权您的应用。弹窗包括您在应用的Info.plist文件的NSSiriUsageDescription键中提供的使用说明字符串。用户可以批准或拒绝您的应用程序的授权请求,并可以稍后在“设置”应用中更改您应用的授权状态。系统会记住您的应用程序的授权状态,以便后续调用requestSiriAuthorization:方法不会再次提示用户。


Structuring Your App’s Services - 构建应用程序的服务

您的Intents扩展程序是代表您的应用程序执行的代理程序,应该能够执行与您的应用程序相同的服务。由于您的iOS应用和Intents扩展执行许多相同的任务,请考虑以下事项:

  • Use a private shared framework to store the code for your core services - 使用私有共享框架来存储核心服务的代码。将框架链接到您的iOS应用程序和Intents扩展程序。共享框架最小化了可执行文件的大小,并确保两者都使用相同的代码与您的服务进行交互。

  • Use a shared container to store common resources - 使用共享容器来存储公共资源。如果您的服务使用位于应用程序包外部的图像或数据文件,请将这些资源放入共享容器中。在每个目标的“Capabilities”选项卡中启用共享容器支持。


Testing Your Extension - 测试你的扩展

要测试Intents扩展,必须在设备上运行它。 Xcode支持直接从Xcode项目启动Intents扩展,并在设备上运行时对其进行调试。

1. To run and debug your Intents extension on a device - 在设备上运行和调试Intents扩展

  • 1) 将活动scheme设置为Intents扩展的方案。

当您向项目添加Intents扩展时,Xcode会自动创建一个运行该扩展的scheme

  • 2) 将scheme配置为在连接的设备上运行。

您无法在模拟器中调试Intents扩展。

  • 3) 选择Product > Run以在设备上启动扩展。

  • 4) 当Xcode提示时,选择Siri作为要运行的应用程序。

Xcode构建您的应用和扩展,将它们安装在设备上,然后启动Siri。

首次安装您的扩展程序时,Siri可能无法立即识别您的应用扩展程序。您可能需要等待几分钟才能发出任何相关命令。同样,在更新Info.plist文件时,您可能需要等待几分钟,然后Siri才能识别出更改。


Using the Intents Framework From Your iOS App - 使用iOS应用程序中的Intents框架

您的iOS应用程序使用Intents框架执行特定任务:

  • 使用INVocabulary类注册用户特定的词汇表术语。 仅针对您的应用和特定用户自定义的术语注册用户特定词汇,否则可能会被Siri误解; 不要注册常见或易于理解的术语。 有关注册词汇表的信息,请参阅Specifying Custom Vocabulary

  • 使用INPreferences类获取本地化内容的Siri语言。 使用此信息来格式化您的应用与扩展程序共享的任何内容。 有关更多信息,请参阅INPreferences Class Reference

  • 如果要将交互移交给系统,请创建INInteraction对象。 通过移交交互,您可以提供有关用户正在执行的操作的上下文。 系统和其他应用程序可以使用该信息来改进搜索结果并提供更好的用户体验。 有关更多信息,请参阅INInteraction Class Reference


Internationalization and Siri - 国际化和Siri

用户可以为Siri配置与设备其余部分不同的语言。 在iOS应用程序中,系统使用特定于设备的语言设置检索本地化内容。 在Intents扩展中,系统使用Siri语言检索本地化内容。 如果您的应用与扩展程序共享本地化内容,则必须使用Siri语言共享该内容,您的应用可以使用INPreferences类的siriLanguageCode方法检索该语言。

有关获取Siri语言的更多信息,请参阅INPreferences Class Reference


Resolving and Handling Intents - 解决和处理意图

Intents扩展中,处理程序对象执行解析,确认和处理Siri发送的intent对象的关键工作。每个intent对象都有一个专门为处理该intent而设计的相关协议。例如,INRequestRideIntent对象的处理程序采用INRequestRideIntentHandling协议。

每种协议的方法分为三组:

  • 用于解析intent参数的零个或多个方法
  • 一种确认方法,为Siri提供您的建议响应
  • 执行任务的句柄方法

实现处理程序时,必须始终实现处理intent的方法。所有其他方法都是可选的,但建议使用。解决和确认方法是您在尝试处理意图之前验证意图内容的机会。您还可以使用这些方法来标识或创建处理意图所需的内部数据对象。

有关意图列表和相应的意图处理协议,请参阅Intents Domains


Resolving the Parameters of an Intent - 解析意图的参数

在意图的解决阶段,Siri要求您的处理程序解析关键参数并确认您打算使用的值。因为说出了来自用户的数据,所以可能存在丢失或模糊的信息。解决阶段是您验证所提供数据的机会,并让Siri知道您是否需要澄清或更多信息。建议您为给定的处理程序协议实现所有解析方法。虽然您可能不会使用所有参数,但每种方法都会告诉Siri您是否在自己的数据结构中找到了适当的值。

您使用解析结果对象将解析结果传回SiriKit,解析结果对象是INIntentResolutionResult类的实例。您可能需要解析每种参数类型的不同子类。例如,在以INPerson对象的形式解析联系人时,将返回INPersonResolutionResult类的实例。实例化子类时,请使用与解析工作结果相对应的创建方法。表3-1列出了可能的结果,并说明了何时使用每种结果。

Table 3-1 Possible outcomes when resolving intent parameters

Resolution Examples
您已成功匹配该值。 成功验证参数后指定此结果,并具有可用于处理意图的相应值。 此结果是最优选的,因为它不需要进一步的用户交互,您应该尽可能采取步骤成功解析参数。 例如,您可以利用用户模式或收藏夹来识别参数的可能值。
不需要值 如果不需要参数值来处理意图,请指定此结果。 通常,仅在某些时间使用参数且当前不相关时才返回此结果。 例如,当意图包含通常没有目标的开放式锻炼的目标时,您可能会返回此结果。
值需要消除歧义 当您确定两个或更多可能的结果,但不能明确选择一个时,请指定此结果。 此结果通常会导致额外的用户交互以消除参数的歧义。 例如,如果邮件收件人仅被标识为“Brandon”,但用户有两个具有该名称的联系人,则可以使用此结果在选择正确的联系人时寻求帮助。
该值需要用户确认 如果希望Siri提示用户确认指定值,请指定此结果。 Siri总是要求确认涉及金融交易的意图,但是如果您希望用户确认您提供的值,您可以使用此方法。 例如,您可以请求确认音频呼叫的收件人。
该值需要更多细节 当给定参数的信息不完整时,请指定此结果。 一些参数由可能具有多条信息的对象表示。 例如,如果INPerson对象不包含足够的详细信息来标识特定联系人,并且您无法从可用信息中进行合理猜测,请使用此结果。 使用此结果要求用户提供缺少的信息。
需要一个值 缺少必需参数的值时指定此结果。 无论用户是否为该参数指定了值,Siri都会要求您的扩展程序解析每个参数。 当您需要值进行处理时,请使用此结果。 例如,如果用户请求其他人付款但未指定金额,则可能会返回此结果。
该值不受支持 当您的应用不支持特定值或该值与其他参数的值冲突时,请指定此结果。 您必须指定参数无效的原因。 您也可以选择指定有效的替代值。 例如,当用户想要以瑞士法郎发送付款时,您可能会返回此结果,但您的应用需要以欧元或美元进行交易。 在提供替代值列表时,仅提供最可能的替代值而不是每个可能的值。 提供太多选择可能使用户难以选择正确的选择。

解析参数时,尝试尽快达成成功的解决方案。 询问更多信息会导致额外的用户交互以及对处理程序的额外调用,从而导致延迟并可能使用户感到沮丧。 相反,尝试根据用户的模式和习惯选择合理的值,并仅在需要时要求消除歧义或确认。

Listing 3-1显示了乘坐预订应用程序的示例,该应用程序验证了乘车的下车位置。 如果存在一个下车位置,则该方法返回一个成功的结果;否则,该方法返回表示需要该值的结果。

// Listing 3-1 Resolving a required parameter of an intent

//OC

- (void)resolveDropOffLocationForRequestRide:(INRequestRideIntent *)requestRideIntent
withCompletion:(void (^)(INPlacemarkResolutionResult *resolutionResult))completion 
{
CLPlacemark* location = requestRideIntent.dropOffLocation;
INPlacemarkResolutionResult* result = nil;
if (location) {
    // Use the specified drop-off location.
    result = [INPlacemarkResolutionResult successWithResolvedPlacemark:location];
}
else {
    // Ask for the drop-off location.
    result = [INPlacemarkResolutionResult needsValue];
}
    // Execute the completion block with the result.
    completion(result);
}
// Swift

func resolveDropOffLocation(forRequestRide intent: INRequestRideIntent,
with completion: (INPlacemarkResolutionResult) -> Void) {
let location = intent.dropOffLocation
var result : INPlacemarkResolutionResult
if location != nil {
    // Use the specified drop-off location.
    result = INPlacemarkResolutionResult.success(with: location!)
}
else {
    // Ask for the drop-off location.
    result = INPlacemarkResolutionResult.needsValue()
}
// Execute the completion block with the result.
completion(result);
}

后记

本篇主要讲述了编程指南之Intents和Intents UI扩展,感兴趣的给个赞或者关注~~~

SiriKit框架详细解析(五) —— 编程指南之Intents和Intents UI扩展(一)_第2张图片

你可能感兴趣的:(SiriKit框架详细解析(五) —— 编程指南之Intents和Intents UI扩展(一))