一、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元給孫波”