iOS開發-SiriKit應用

林欣達發表於2016-06-20

 

關於SiriKit

在6月14日凌晨的WWDC2016大會上,蘋果提出iOS10是一次里程碑並且推出了十個新特性,大部分的特性是基於iPhone自身的原生應用的更新,具體的特性筆者不在這裡再次敘述,請看客們移步WWDC2016下載自行觀賞。要說里程碑在筆者看來有些誇大其實了,不過新增的通知中心聯動3D Touch確實為人機互動帶來新的發展,另外一個最大的亮點在於Siri的介面開放。在iOS10中提供了SiriKit框架在使用者使用Siri的時候會生成INExtension物件來告知我們的應用,通過實現方法來讓Siri獲取應用想要展示給使用者的內容

iOS開發-SiriKit應用
Siri服務

iOS10之後,蘋果希望Siri能夠給使用者帶來更多的功能體驗,基於這個出發點,新增了SiriKit框架。Siri通過語言處理系統對使用者發出的對話請求進行解析之後生成一個用來描述對話內容的Intents事件,然後通過SiriKit框架分發給整合框架的應用程式以此來獲取應用的內容,比如完成類似通過文字匹配查詢應用聊天記錄、聊天物件的功能,此外它還支援為使用者使用蘋果地圖時提供應用內建服務等功能。通過官方文件我們可以看到SiriKit框架支援的六類服務分別是:

  • 語音和視訊通話
  • 傳送訊息
  • 收款或者付款
  • 圖片搜尋
  • 管理鍛鍊
  • 行程預約

SiriMaps通過Intents extension的擴充套件方式和我們的應用進行互動,其中,型別為INExtension的物件扮演著Intents extension擴充套件中直接協同Siri物件共同響應使用者請求的關鍵角色。當我們實現了Intents extension擴充套件併產生了一個Siri請求事件時,一個典型的Intent事件的處理過程中總共有這三個步驟ResolveConfirmHandle

  • Resolve階段。在Siri獲取到使用者的語音輸入之後,生成一個INIntent物件,將語音中的關鍵資訊提取出來並且填充對應的屬性。這個物件在稍後會傳遞給我們設定好的INExtension子類物件進行處理,根據子類遵循的不同服務protocol來選擇不同的解決方案
  • Confirm階段。在上一個階段通過handler(for intent:)返回了處理intent的物件,此階段會依次呼叫confirm打頭的例項方法來判斷Siri填充的資訊是否完成。匹配的判斷結果包括Exactly one matchTwo or more matches以及No match三種情況。這個過程中可以讓Siri向使用者徵求更具體的引數資訊
  • confirm方法執行完成之後,Siri進行最後的處理階段,生成答覆物件,並且向此intent物件確認處理結果然後執顯示結果給使用者看
 iOS開發-SiriKit應用

具體的執行過程請參考文件講解視訊

建立Intents Extension

SiriKit通過新增App Extension的方式來完成整合,這是一種獨立於應用本身執行的程式碼結構,作為應用的擴充套件功能,只有在需要的時候系統會喚醒這些Extension程式碼來執行任務,然後在執行完畢之後將其殺死。另一方面,這些Extension在執行過程中的可佔用記憶體是較少的,並且由於呼叫時機的限制,我們也無法在執行期間做一些壞事

 iOS開發-SiriKit應用

現階段整合SiriKit的條件是需要將開發工具升級到Xcode8,需要使用開發者賬號到官方網站去下載Xcode8_beta版,並且需要將一臺測試裝置升級到iOS10系統。選中我們的應用,進入專案總覽介面,新增一個TARGET

 iOS開發-SiriKit應用
 iOS開發-SiriKit應用

如上圖所示,我建立的Intents Extension被我命名為LXDSiriExtension。記住在建立好一個Extension的時候,會詢問你是否啟用這個擴充套件,勾選是。另外還會提示你是否連同Intents UI Extension一併建立了,我們同樣選是。這樣我們在專案下面總共建立了LXDSiriExtensionLXDSiriExtensionUI兩個TARGET,這兩個檔案目錄下面分別存在著一個新的info.plist檔案,這個檔案用來設定intent事件發生時我們設定的處理類。這裡借用WWDC在講解時的一張ppt來了解:

 iOS開發-SiriKit應用

按圖中的層次展開,IntentsSupportedIntentsRestrictedWhileLocked分別是兩個字串陣列,每一個字串表示的是應用擴充套件處理的intent事件的類名。前者表示支援的事件型別,後者表示在非鎖屏狀態下執行的事件型別。檔案預設是workout型別的事件,在這裡筆者改成了傳送訊息INSendMessageIntent。除此之外,NSExtensionPrincipalClass對應的是INExtension子類類名,這個類用來獲取處理intent事件的類。

iOS開發-SiriKit應用

plist設定

另外,官方講解中提到了Embedded frameworks,在session中蘋果開發人員通過一個訊息聊天應用來示例整合SiriKit。由於應用擴充套件自身的執行機制和應用本身的執行機制不同,彼此之間建立的類是不能訪問使用的。因此把我們需要的類開發成frameworks的方式匯入我們的應用之後就能夠在兩種之中都使用到這些類。本文未使用frameworks匯入功能,而是模擬了一個類用來管理事件處理過程中的部分邏輯,但是Embedded frameworks這個使用的準則需要記住。這個模擬類的具體程式碼如下:

在完成這些需要的工作之後,我們還需要對應用本身的Info.plist配置檔案進行設定,新增一個關鍵字為NSSiriUsageDescription的字串物件,對應填寫的字串將在我們徵詢使用者Siri許可權的時候顯示給使用者看。比如Siri想要訪問您的應用資訊之類的提示語。然後通過INPreferences類方法向使用者請求Siri訪問許可權

程式碼實現

首先我們需要一個INExtension的子類,你也可以在預設建立的子類中實現程式碼。在方法中,我們通過判斷intent的型別來建立對應的處理者例項,然後返回。在本文的示例中,假設我們對Siri說出這麼一句話 Siri,在微信上告訴我的家人們今天我不回去吃飯了

通過判斷intent事件是傳送訊息的聊天事件後,筆者建立了一個用來處理事件的LXDSendMessageIntentHandler類物件,並且返回。在物件建立完成之後需要完成ResolveConfirmHandle三個步驟,具體操作需要子類遵循實現INSendMessageIntentHandling協議來完成:

  • Resolve階段
    這個階段需要我們找到訊息的具體接收者。在這個過程中,可能會出現三種情況:Exactly one matchTwo or more matches以及No matches,對於這三種情況的處理分別如下:

    上面的程式碼用來確認出訊息中的我的家人們指代的是哪些人,其中每個聯絡人最終用一個INPerson的物件來表示。接著我們需要匹配訊息的內容:

    在匹配完訊息接收者跟訊息內容之後,對於intent事件的處理就會進入第二階段Confirm確認值是否正確
  • Confirm階段
    在這個階段intent物件本身的資訊預計是已經完成填充的,我們通過獲取這些填充值來判斷是否符合我們的要求。同時在這個階段,Siri會嘗試喚醒應用來準備完成最後的處理操作。前面說了為了保證在應用和應用擴充之間能夠進行通訊,最好使用frameworks的方式來標記應用是否被啟動,再進行相應操作。

    Confirm階段是我們最後可以嘗試修改intent事件中傳遞的數值的時候。要記住一點,完全精確的內容固然是最好的答案,但是過多的讓Siri詢問使用者引數的詳細資訊也會導致使用者的牴觸
  • Handle階段
    Handle階段不需要做太多額外的工作,判斷一下訊息接收者或訊息內容是否存在,如果存在,執行類似儲存/傳送的工作,然後完成。否則告訴Siri本次的intent事件處理處理失敗,我們還可以通過配置NSUserActivity物件來告訴Siri失敗的原因

事件UI

可以看到上面的程式碼主要集中在事件處理的邏輯上,那麼在和Siri互動的過程中,我們同樣可以讓Siri展示響應的自定義介面:

 iOS開發-SiriKit應用

在我們建立Intents Extension的時候,同時Xcode也詢問我們是否建立Intents UI Extension。在後者的檔案目錄下也有一個Info.plist,有著跟前面類似的鍵值對,差別在於後者只有一個狀態的設定。

 iOS開發-SiriKit應用

在這個檔案目錄下存在一個故事板MainInterface,這個故事板就是Siri和應用互動時展示給使用者看的介面。通過修改這個故事板的介面元素,就可以實現上圖中的效果了。此外,在這個介面將要展示之前,我們可以修改類檔案中的程式碼完成介面資訊填充的操作:

尾言

在觀看WWDC2016的新特性的時候,最開始給Siri和應用的互動驚豔到了。但是後來閱讀文件發現這種互動仍然存在著過多的限制,整體而言並沒有對Siri的使用帶來更明顯的提升。但是毫無疑問,這種互動如果蘋果能繼續對其進行補充發展,可以給我們的應用帶來更多的新活力。

相關文章