共用方式為


在 Xamarin.iOS 中實作 SiriKit

本文涵蓋在 Xamarin.iOS 應用程式中實作 SiriKit 支援所需的步驟。

IOS 10 的新功能 SiriKit 可讓 Xamarin.iOS 應用程式提供服務,讓使用者可以使用 Siri 和 iOS 裝置上的 地圖 應用程式來存取。 本文涵蓋在 Xamarin.iOS 應用程式中實作 SiriKit 支援所需的步驟,方法是新增必要的意圖延伸模組、意圖 UI 延伸模組和詞彙。

Siri 適用於網域的概念、相關工作的已知動作群組。 應用程式與 Siri 進行的每個互動都必須屬於其其中一個已知的服務網域,如下所示:

  • 音訊或視訊通話。
  • 預訂車程。
  • 管理鍛煉。
  • 傳訊。
  • 搜尋相片。
  • 傳送或接收付款。

當使用者提出涉及其中一個應用程式延伸模組服務 Siri 的要求時,SiriKit 會將擴充功能傳送一個 Intent 物件,以描述使用者的要求以及任何支持的數據。 應用程式延伸模組接著會針對指定的意圖產生適當的 Response 對象,詳細說明延伸模組如何處理要求。

本指南會提供將 SiriKit 支援納入現有應用程式的快速範例。 為了此範例,我們將使用假的 MonkeyChat 應用程式:

MonkeyChat 圖示

MonkeyChat 會保留使用者朋友的專屬聯繫人簿,每個聯繫人都與螢幕名稱相關聯(例如 Bobo),並可讓使用者透過螢幕名稱將文字聊天傳送給每個朋友。

使用 SiriKit 擴充應用程式

如瞭解 SiriKit 概念指南所示,有三個主要部分涉及使用 SiriKit 擴充應用程式:

使用 SiriKit 擴充應用程式圖表

包括:

  1. 意圖擴充 功能 - 驗證使用者回應、確認應用程式可以處理要求,並實際執行工作以完成使用者的要求。
  2. 意圖UI延伸模組 - 選用,提供自訂UI給Siri環境中的回應,並可將應用程式UI和商標帶入Siri,以豐富用戶體驗。
  3. 應用程式 - 提供應用程式與使用者特定的詞彙,以協助 Siri 使用。

下列各節將詳細說明這些元素及其包含在應用程式中的步驟。

準備應用程式

不過,SiriKit 是以擴充功能為基礎,在將任何延伸模組新增至應用程式之前,開發人員需要執行一些動作來協助採用 SiriKit。

移動通用共享程序代碼

首先,開發人員可以將應用程式與延伸模塊之間共用的一些常見程式代碼移至 共用專案可攜式類別庫 (PCL)原生連結庫

延伸模組必須能夠執行應用程式執行的所有作業。 在範例 MonkeyChat 應用程式方面,尋找聯繫人、新增聯繫人、傳送訊息及擷取訊息歷程記錄等專案。

藉由將此一般程式代碼移至共用專案,PCL 或原生連結庫可讓您輕鬆地在一個通用位置維護該程式碼,並確保延伸模組和父應用程式為使用者提供統一的體驗和功能。

在範例 App MonkeyChat 的案例中,數據模型和處理程式碼,例如網路和數據庫存取,將會移至原生連結庫。

執行下列操作:

  1. 啟動 Visual Studio for Mac 並開啟 MonkeyChat 應用程式。

  2. 以滑鼠右鍵按兩下 Solution Pad 中的 [方案名稱],然後選取 [新增>專案...]:

    新增專案

  3. 選取 [iOS>連結庫類別庫>],然後按下一步: 按鈕:

    選取類別庫

  4. 針對 [名稱] 輸入 MonkeyChatCommon ,然後按兩下 [建立] 按鈕:

    輸入 MonkeyChatCommon 以取得名稱

  5. 以滑鼠右鍵按兩下 方案總管 中主要應用程式的 [參考] 資料夾,然後選取 [編輯參考...]。檢查 MonkeyChatCommon 專案,然後按兩下 [確定] 按鈕:

    檢查 MonkeyChatCommon 專案

  6. 方案總管 中,將一般共享程式代碼從主要應用程式拖曳至原生連結庫。

  7. 如果是 MonkeyChat,請將 DataModelsProcessors 資料夾從主要應用程式拖曳到原生連結庫:

    方案總管 中的DataModels和 Processors資料夾

編輯任何移至原生連結庫的檔案,並將命名空間變更為符合連結庫的檔案。 例如,變更 MonkeyChatMonkeyChatCommon

using System;
namespace MonkeyChatCommon
{
    /// <summary>
    /// A message sent from one user to another within a conversation.
    /// </summary>
    public class MonkeyMessage
    {
        public MonkeyMessage ()
        {
        }
        ...
    }
}

接下來,返回主要應用程式,並在應用程式使用其中一個 using 已移動的類別,為 Native Library 的命名空間新增 語句:

using System;
using System.Collections.Generic;
using UIKit;
using Foundation;
using CoreGraphics;
using MonkeyChatCommon;

namespace MonkeyChat
{
    public partial class MasterViewController : UITableViewController
    {
        public DetailViewController DetailViewController { get; set; }

        DataSource dataSource;
        ...
    }
}

建構擴充功能應用程式

一般而言,應用程式會註冊多個意圖,而開發人員需要確保應用程式已針對適當的意圖延伸模組數目進行架構。

在應用程式需要多個意圖的情況下,開發人員可以選擇將其所有意圖處理放在一個意圖延伸模組中,或為每個意圖建立個別的意圖延伸模組。

如果您選擇為每個意圖建立個別的意圖延伸模組,開發人員最終可能會在每個延伸模組中複製大量的重複使用程序代碼,並建立大量的處理器和記憶體額外負荷。

若要協助在兩個選項之間進行選擇,請參閱是否有任何意圖自然屬於一起。 例如,進行音訊和視訊呼叫的應用程式可能會想要在單一意圖延伸模組中包含這兩個意圖,因為它們正在處理類似的工作,而且可以提供最多程式代碼重複使用。

針對不符合現有群組的任何意圖或意圖群組,請在應用程式的方案中建立新的意圖延伸模組以包含它們。

設定必要的權利

任何包含 SiriKit 整合的 Xamarin.iOS 應用程式都必須設定正確的權利。 如果開發人員未正確設定這些必要的權利,將無法在實際的 iOS 10 (或更新版本) 硬體上安裝或測試應用程式,這也是 iOS 10 模擬器不支援 SiriKit 的需求。

執行下列操作:

  1. 按兩下 Entitlements.plist 方案總管中的檔案以開啟檔案以進行編輯。

  2. 切換至 [ 來源] 索引標籤

  3. com.apple.developer.siri新增 屬性,將 Type 設定為 Boolean ,並將 Value 設定Yes

    新增 com.apple.developer.siri 屬性

  4. 儲存對檔案所做的變更。

  5. 按兩下 方案總管中的項目檔,以開啟它進行編輯。

  6. 選取 [iOS 套件組合簽署 ], Entitlements.plist 並確定已選取 [ 自定義權利 ] 字段中的檔案:

    在 [自定義權利] 字段中選取 Entitlements.plist 檔案

  7. 按一下 [確定] 按鈕以儲存所做的變更。

完成後,應用程式的 Entitlements.plist 檔案看起來應該像下面這樣(在外部編輯器中開啟):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.developer.siri</key>
    <true/>
</dict>
</plist>

正確布建應用程式

由於 Apple 在 SiriKit 架構周圍放置的嚴格安全性,任何實作 SiriKit 的 Xamarin.iOS 應用程式都必須 具有正確的應用程式識別碼和權利(請參閱上一節),且必須使用適當的布建配置檔簽署。

在您的 Mac 上執行下列動作:

  1. 在網頁瀏覽器中,流覽至 https://developer.apple.com 並登入您的帳戶。

  2. 按兩下 [ 憑證]、 [標識符 ] 和 [配置檔]。

  3. 選取 [ 布建配置檔 ],然後選取 [應用程式標識符],然後按下 + 按鈕。

  4. 輸入 新配置檔的 [名稱 ]。

  5. 輸入 Apple命名建議之後的套件組合標識碼

  6. 向下捲動至 [App Services ] 區段,選取 [SiriKit ],然後按兩下 [ 繼續] 按鈕:

    選取 SiriKit

  7. 確認所有設定,然後 提交 應用程式識別碼。

  8. 選取 [布建配置文件>開發],按下+按鈕,選取 Apple ID,然後按兩下 [繼續]。

  9. 按兩下 [全選 ],然後按兩下 [ 繼續]。

  10. 再次按兩下 [ 全選] ,然後按兩下 [ 繼續]。

  11. 使用 Apple 的命名建議輸入設定檔名稱,然後按兩下 [繼續]。

  12. 啟動 Xcode。

  13. 從 [Xcode] 功能選取 [ 喜好設定...

  14. 選取 [帳戶],然後按下 [ 檢視詳細數據...] 按鈕:

    選取帳戶

  15. 按下左下角的 [ 下載所有設定檔] 按鈕:

    下載所有配置檔

  16. 確定上面建立的 布建配置檔 已安裝在 Xcode 中。

  17. 開啟專案以在Visual Studio for Mac 中新增 SiriKit 支援。

  18. 按兩下 Info.plist 方案總管 中的檔案。

  19. 確定套件 組合識別碼符合上述 Apple 開發人員入口網站中建立的識別碼

    套件組合標識碼

  20. 方案總管 中,選取 [專案]。

  21. 以滑鼠右鍵按兩下項目,然後選取 [ 選項]。

  22. 選取 [iOS 套件組合簽署],選取上面建立的 簽署身分識別布建配置檔

    選取簽署身分識別和布建配置檔

  23. 按一下 [確定] 按鈕以儲存所做的變更。

重要

測試 SiriKit 僅適用於真正的 iOS 10 硬體裝置,而不是在 iOS 10 模擬器中運作。 如果在實際硬體上安裝已啟用 SiriKit 的 Xamarin.iOS 應用程式時遇到問題,請確定 Apple 開發人員入口網站和 Visual Studio for Mac 中都已正確設定必要的權利、應用程式識別碼、簽署識別符和布建配置檔。

要求 Siri 授權

在應用程式新增任何使用者特定詞彙或意圖延伸模組連線到 Siri 之前,它必須要求使用者授權才能存取 Siri。

編輯應用程式的 Info.plist 檔案、切換至 [來源 ] 檢視,並使用字串值來新增 NSSiriUsageDescription 索引鍵,描述應用程式如何使用 Siri,以及傳送數據類型。 例如,MonkeyChat 應用程式可能會說「將傳送給 Siri 的 MonkeyChat 連絡人」:

Info.plist 編輯器中的 NSSiriUsageDescription

RequestSiriAuthorization第一次啟動應用程式時,呼叫 類別的 INPreferences 方法。 AppDelegate.cs編輯 類別,並讓 FinishedLaunching 方法看起來如下:

using Intents;
...

public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{

    // Request access to Siri
    INPreferences.RequestSiriAuthorization ((INSiriAuthorizationStatus status) => {
        // Respond to returned status
        switch (status) {
        case INSiriAuthorizationStatus.Authorized:
            break;
        case INSiriAuthorizationStatus.Denied:
            break;
        case INSiriAuthorizationStatus.NotDetermined:
            break;
        case INSiriAuthorizationStatus.Restricted:
            break;
        }
    });

    return true;
}

第一次呼叫此方法時,會顯示警示,提示使用者允許應用程式存取 Siri。 將在此警示中顯示開發人員新增至 NSSiriUsageDescription 上述的訊息。 如果使用者一開始拒絕存取權,他們可以使用 設定 應用程式來授與應用程式的存取權。

應用程式可以隨時呼叫 SiriAuthorizationStatus 類別的 INPreferences 方法來檢查應用程式存取 Siri 的能力。

當地語系化和 Siri

在 iOS 裝置上,用戶可以選取與系統預設值不同的 Siri 語言。 使用本地化的數據時,應用程式必須使用 SiriLanguageCode 類別的 INPreferences 方法,從 Siri 取得語言代碼。 例如:

var language = INPreferences.SiriLanguageCode();

// Take action based on language
if (language == "en-US") {
    // Do something...
}

新增使用者特定詞彙

使用者特定詞彙會提供應用程式個別使用者特有的單字或片語。 這些會在運行時間從主要應用程式(而非應用程式延伸模組)提供為一組已排序的字詞,並以使用者最重要的使用優先順序來排序,且清單開頭最重要的詞彙。

使用者特定詞彙必須屬於下列其中一個類別:

  • 聯繫人名稱(不是由聯繫人架構管理)。
  • 相片標記。
  • 相簿名稱。
  • 鍛煉名稱。

選取術語以註冊為自定義詞彙時,只有選擇可能被不熟悉應用程式的人誤解的字詞。 永遠不要註冊一般詞彙,例如「我的鍛煉」或「我的專輯」。 例如,MonkeyChat 應用程式會註冊與用戶通訊簿中每個聯繫人相關聯的昵稱。

應用程式會藉由呼叫 SetVocabularyStrings 類別的 INVocabulary 方法,並從主要應用程式傳入 NSOrderedSet 集合,來提供使用者特定詞彙。 應用程式應該一律先呼叫 RemoveAllVocabularyStrings 方法,先移除任何現有的字詞,再新增新的字詞。 例如:

using System;
using System.Linq;
using System.Collections.Generic;
using Foundation;
using Intents;

namespace MonkeyChatCommon
{
    public class MonkeyAddressBook : NSObject
    {
        #region Computed Properties
        public List<MonkeyContact> Contacts { get; set; } = new List<MonkeyContact> ();
        #endregion

        #region Constructors
        public MonkeyAddressBook ()
        {
        }
        #endregion

        #region Public Methods
        public NSOrderedSet<NSString> ContactNicknames ()
        {
            var nicknames = new NSMutableOrderedSet<NSString> ();

            // Sort contacts by the last time used
            var query = Contacts.OrderBy (contact => contact.LastCalledOn);

            // Assemble ordered list of nicknames by most used to least
            foreach (MonkeyContact contact in query) {
                nicknames.Add (new NSString (contact.ScreenName));
            }

            // Return names
            return new NSOrderedSet<NSString> (nicknames.AsSet ());
        }

        // This method MUST only be called on a background thread!
        public void UpdateUserSpecificVocabulary ()
        {
            // Clear any existing vocabulary
            INVocabulary.SharedVocabulary.RemoveAllVocabularyStrings ();

            // Register new vocabulary
            INVocabulary.SharedVocabulary.SetVocabularyStrings (ContactNicknames (), INVocabularyStringType.ContactName);
        }
        #endregion
    }
}

在此程式代碼就緒后,可能會呼叫它,如下所示:

using System;
using System.Threading;
using UIKit;
using MonkeyChatCommon;
using Intents;

namespace MonkeyChat
{
    public partial class ViewController : UIViewController
    {
        #region AppDelegate Access
        public AppDelegate ThisApp {
            get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
        }
        #endregion

        #region Constructors
        protected ViewController (IntPtr handle) : base (handle)
        {
            // Note: this .ctor should not contain any initialization logic.
        }
        #endregion

        #region Override Methods
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            // Do we have access to Siri?
            if (INPreferences.SiriAuthorizationStatus == INSiriAuthorizationStatus.Authorized) {
                // Yes, update Siri's vocabulary
                new Thread (() => {
                    Thread.CurrentThread.IsBackground = true;
                    ThisApp.AddressBook.UpdateUserSpecificVocabulary ();
                }).Start ();
            }
        }

        public override void DidReceiveMemoryWarning ()
        {
            base.DidReceiveMemoryWarning ();
            // Release any cached data, images, etc that aren't in use.
        }
        #endregion
    }
}

重要

Siri 會將自定義詞彙視為提示,並將盡可能納入大部分的術語。 不過,自定義詞彙的空間有限,因此請務必只註冊可能造成混淆的術語,因此將已註冊字詞總數保持在最低。

如需詳細資訊,請參閱我們的 使用者特定詞彙參考 和 Apple 的 指定自定義詞彙參考

新增應用程式特定詞彙

應用程式特定詞彙會定義所有應用程式用戶都會知道的特定單字和片語,例如車輛類型或鍛煉名稱。 因為這些是應用程式的一部分,所以會在檔案中 AppIntentVocabulary.plist 定義為主要應用程式套件組合的一部分。 此外,這些單字和片語應該當地語系化。

應用程式特定詞彙字詞必須屬於下列其中一個類別:

  • 乘坐選項。
  • 鍛煉名稱。

應用程式特定詞彙檔案包含兩個根層級索引鍵:

  • ParameterVocabularies必要 - 定義其適用的應用程式自定義詞彙和意圖參數。
  • IntentPhrases選擇性 - 包含使用 中所 ParameterVocabularies定義的自定義詞彙範例片語。

中的每個 ParameterVocabularies 項目都必須指定一個標識符字串、字詞和該字詞套用的意圖。 此外,單一字詞可能會套用至多個意圖。

如需可接受的值和必要檔案結構的完整清單,請參閱Apple的應用程式 詞彙檔格式參考

若要將檔案新增 AppIntentVocabulary.plist 至應用程式專案,請執行下列動作:

  1. 以滑鼠右鍵按兩下 方案總管 中的 [項目名稱],然後選取[新增>檔案...>iOS

    新增屬性清單

  2. 按兩下 AppIntentVocabulary.plist 方案總管中的檔案以開啟檔案以進行編輯。

  3. +點選 以新增索引鍵、將 [名稱] 設定為 ParameterVocabularies ,並將 [類型] 設定為 Array

    將 Name 設定為 ParameterVocabularies,並將 Type 設定為 Array

  4. 展開 ParameterVocabularies 並按鍵, + 並將 [ 類型 ] 設定為 Dictionary

    將 [類型] 設定為 [字典]

  5. +點選 以新增索引鍵、將 [名稱] 設定為 ParameterNames ,並將 [類型] 設定為 Array

    將 [名稱] 設定為 ParameterNames,並將 [類型] 設定為 [陣列]

  6. 按兩下 以 + 新增具有 TypeString 值的新索引鍵作為其中一個可用的參數名稱。 例如: INStartWorkoutIntent.workoutName

    INStartWorkoutIntent.workoutName 機碼

  7. ParameterVocabulary索引鍵新增至ParameterVocabularies具有 類型Array索引鍵:

    使用陣列類型將ParameterVocabulary 索引鍵新增至ParameterVocabularies 索引鍵

  8. 新增具有 類型 的新 Dictionary索引鍵:

    在 Visual Studio for Mac 中新增具有字典類型的新索引鍵。

  9. VocabularyItemIdentifier新增具有 TypeString索引鍵,並指定字詞的唯一標識碼:

    使用字串類型新增 VocabularyItemIdentifier 索引鍵,並指定唯一標識符

  10. VocabularyItemSynonyms使用 的型Array新增索引鍵

    使用陣語類型新增詞彙ItemSynonyms 索引鍵

  11. 新增具有 類型 的新 Dictionary索引鍵:

    在 Visual Studio for Mac 中使用字典類型新增另一個新索引鍵。

  12. VocabularyItemPhrase新增具有 TypeString索引鍵,以及應用程式正在定義的字詞:

    使用字串類型新增詞彙ItemPhrase 金鑰,以及應用程式正在定義的字詞

  13. VocabularyItemPronunciation新增具有 類型String索引鍵,以及字詞的語音發音:

    新增具有字串類型與字詞語音發音的詞彙ItemPronunciation 索引鍵

  14. VocabularyItemExamples使用 的型Array新增索引鍵

    使用陣語型別新增詞彙ItemExamples 索引鍵

  15. 新增一些 String 索引鍵,其中範例會使用 詞彙:

    在 Visual Studio for Mac 中新增一些字串索引鍵,其中範例會使用 詞彙。

  16. 針對應用程式需要定義的任何其他自定義字詞重複上述步驟。

  17. 折疊索引 ParameterVocabularies 鍵。

  18. IntentPhrases使用 的型Array新增索引鍵

    使用陣列類型新增 IntentPhrases 索引鍵

  19. 新增具有 類型 的新 Dictionary索引鍵:

    在 Visual Studio for Mac 中新增具有字典類型的其他新索引鍵。

  20. 使用 IntentName 和意圖新增索引鍵String,以取得範例:

    為範例新增 IntentName 索引鍵,其中包含 String 和 Intent 的類型

  21. IntentExamples使用 的型Array新增索引鍵

    使用陣列類型新增 IntentExamples 索引鍵

  22. 新增一些 String 索引鍵,其中範例會使用 詞彙:

    在 Visual Studio for Mac 中新增一些額外的 String 索引鍵,並搭配使用詞彙的範例。

  23. 針對應用程式需要提供範例使用方式的任何意圖重複上述步驟。

重要

將在 AppIntentVocabulary.plist 開發期間向 Siri 註冊測試裝置,而且 Siri 可能需要一些時間才能納入自定義詞彙。 因此,測試人員必須等候數分鐘,才能嘗試在更新應用程式特定詞彙時進行測試。

如需詳細資訊,請參閱我們的 應用程式特定詞彙參考 和 Apple 的 指定自定義詞彙參考

新增意圖擴充功能

既然應用程式已準備好採用 SiriKit,開發人員必須將一或多個意圖延伸模組新增至解決方案,以處理 Siri 整合所需的意圖。

針對所需的每個意圖擴充功能,請執行下列動作:

  • 將意圖延伸模組專案新增至 Xamarin.iOS 應用程式解決方案。
  • 設定意圖延伸模組 Info.plist 檔案。
  • 修改 Intents Extension 主要類別。

如需詳細資訊,請參閱我們的 意圖延伸模組參考 和 Apple 的 建立意圖延伸模塊參考

建立延伸模組

若要將意圖擴充功能新增至解決方案,請執行下列動作:

  1. 以滑鼠右鍵按兩下 Solution Pad 中的 [方案名稱],然後選取 [新增>新增專案...]。

  2. 從對話框中選取 [iOS>擴充>功能意圖延伸模組],然後按兩下一步[ 下一步] 按鈕:

    選取意圖延伸模組

  3. 接下來,輸入意圖延伸模組的名稱,然後按兩下一步按鈕

    輸入意圖延伸模組的名稱。

  4. 最後,按兩下 [ 建立] 按鈕,將意圖延伸模組新增至應用程式解決方案:

    將意圖延伸模組新增至應用程式解決方案。

  5. 方案總管 中,以滑鼠右鍵按下新建立意圖延伸模組的 [參考] 資料夾。 檢查通用共享程式代碼連結庫項目的名稱(上面建立的應用程式),然後按下 [ 確定 ] 按鈕:

    選取通用共享程式代碼連結庫項目的名稱。

針對應用程式將需要的意圖延伸模組數目重複這些步驟(根據 上述架構適用於延伸 模組的應用程式一節)。

設定 Info.plist

針對已新增至應用程式解決方案的每個意圖延伸模組,必須在檔案中 Info.plist 設定才能使用應用程式。

就像任何一般應用程式延伸模組一樣,應用程式會有和NSExtensionAttributes的現有索引鍵NSExtension。 針對意圖延伸模組,必須設定兩個新的屬性:

必須設定的兩個新屬性

  • IntentsSupported - 這是必要專案,而且是由應用程式想要從意圖延伸模組支援的意圖類別名稱陣列所組成。
  • IntentsRestrictedWhileLocked - 這是應用程式指定擴充功能鎖定畫面行為的選擇性密鑰。 它包含意圖類別名稱的陣列,應用程式想要要求使用者從意圖擴充功能登入以使用。

若要設定意圖延伸模組的Info.plist檔案,請在 方案總管按兩下它以開啟它以進行編輯。 接下來,切換至 [ 來源 ] 檢視,然後在編輯器中展開 NSExtensionNSExtensionAttributes 索引鍵:

展開機碼, IntentsSupported 並新增此延伸模組將支援的任何意圖類別名稱。 例如,MonkeyChat 應用程式支援 INSendMessageIntent

如果應用程式選擇性地要求使用者登入裝置以使用指定的意圖,請展開 IntentRestrictedWhileLocked 機碼,並新增具有限制存取權的意圖類別名稱。 針對範例 MonkeyChat 應用程式,用戶必須登入以傳送聊天訊息,以便我們新增 INSendMessageIntent

如需可用意圖網域的完整清單,請參閱Apple的 意圖網域參考

設定Main類別

接下來,開發人員必須設定主要類別,以做為 Siri 意圖延伸模組的主要進入點。 它必須是符合委派的INExtensionIINIntentHandler子類別。 例如:

using System;
using System.Collections.Generic;

using Foundation;
using Intents;

namespace MonkeyChatIntents
{
    [Register ("IntentHandler")]
    public class IntentHandler : INExtension, IINSendMessageIntentHandling, IINSearchForMessagesIntentHandling, IINSetMessageAttributeIntentHandling
    {
        #region Constructors
        protected IntentHandler (IntPtr handle) : base (handle)
        {
            // Note: this .ctor should not contain any initialization logic.
        }
        #endregion

        #region Override Methods
        public override NSObject GetHandler (INIntent intent)
        {
            // This is the default implementation.  If you want different objects to handle different intents,
            // you can override this and return the handler you want for that particular intent.

            return this;
        }
        #endregion
        ...
    }
}

有一個單獨方法,應用程式必須在意圖延伸模組主要類別 GetHandler 上實作 方法。 這個方法會由 SiriKit 傳遞意圖,而且應用程式必須傳回 符合指定意圖類型的意圖處理程式

由於 MonkeyChat 應用程式範例只會處理一個意圖,因此它會在方法中 GetHandler 傳回本身。 如果延伸模組處理了多個意圖,開發人員會為每個意圖類型新增類別,並根據傳遞給方法的傳回實例 Intent

處理解析階段

解決階段是意圖延伸模組會釐清和驗證從 Siri 傳入的參數,並已透過使用者的交談設定。

針對從 Siri 傳送的每個參數,都有一種方法 Resolve 。 應用程式必須針對應用程式可能需要 Siri 協助才能從使用者取得正確答案的每個參數實作此方法。

在範例 MonkeyChat 應用程式的情況下,意圖延伸模組會要求一或多個收件者傳送訊息。 針對清單中的每個收件者,延伸模組必須執行聯繫人搜尋,才能有下列結果:

  • 找到一個相符的聯繫人。
  • 找到兩個或多個相符的聯繫人。
  • 找不到相符的聯繫人。

此外,MonkeyChat 需要訊息本文的內容。 如果使用者尚未提供此內容,Siri 必須提示使用者輸入內容。

意圖延伸模組必須正常處理上述每個案例。

[Export ("resolveRecipientsForSearchForMessages:withCompletion:")]
public void ResolveRecipients (INSendMessageIntent intent, Action<INPersonResolutionResult []> completion)
{
    var recipients = intent.Recipients;
    // If no recipients were provided we'll need to prompt for a value.
    if (recipients.Length == 0) {
        completion (new INPersonResolutionResult [] { (INPersonResolutionResult)INPersonResolutionResult.NeedsValue });
        return;
    }

    var resolutionResults = new List<INPersonResolutionResult> ();

    foreach (var recipient in recipients) {
        var matchingContacts = new INPerson [] { recipient }; // Implement your contact matching logic here to create an array of matching contacts
        if (matchingContacts.Length > 1) {
            // We need Siri's help to ask user to pick one from the matches.
            resolutionResults.Add (INPersonResolutionResult.GetDisambiguation (matchingContacts));
        } else if (matchingContacts.Length == 1) {
            // We have exactly one matching contact
            resolutionResults.Add (INPersonResolutionResult.GetSuccess (recipient));
        } else {
            // We have no contacts matching the description provided
            resolutionResults.Add ((INPersonResolutionResult)INPersonResolutionResult.Unsupported);
        }
    }

    completion (resolutionResults.ToArray ());
}

[Export ("resolveContentForSendMessage:withCompletion:")]
public void ResolveContent (INSendMessageIntent intent, Action<INStringResolutionResult> completion)
{
    var text = intent.Content;
    if (!string.IsNullOrEmpty (text))
        completion (INStringResolutionResult.GetSuccess (text));
    else
        completion ((INStringResolutionResult)INStringResolutionResult.NeedsValue);
}

如需詳細資訊,請參閱我們的 解決階段參考 和Apple的 解析和處理意圖參考

處理確認階段

確認階段是意圖延伸模組檢查,以查看其具有滿足使用者要求的所有資訊。 應用程式想要一起傳送確認,將會提供 Siri 即將發生的一切支援詳細數據,以便與使用者確認這是預定的動作。

[Export ("confirmSendMessage:completion:")]
public void ConfirmSendMessage (INSendMessageIntent intent, Action<INSendMessageIntentResponse> completion)
{
    // Verify user is authenticated and the app is ready to send a message.
    ...

    var userActivity = new NSUserActivity (nameof (INSendMessageIntent));
    var response = new INSendMessageIntentResponse (INSendMessageIntentResponseCode.Ready, userActivity);
    completion (response);
}

如需詳細資訊,請參閱我們的 確認階段參考

處理意圖

這是意圖延伸模組實際執行工作以完成使用者的要求,並將結果傳回 Siri,以便通知使用者。

public void HandleSendMessage (INSendMessageIntent intent, Action<INSendMessageIntentResponse> completion)
{
    // Implement the application logic to send a message here.
    ...

    var userActivity = new NSUserActivity (nameof (INSendMessageIntent));
    var response = new INSendMessageIntentResponse (INSendMessageIntentResponseCode.Success, userActivity);
    completion (response);
}

public void HandleSearchForMessages (INSearchForMessagesIntent intent, Action<INSearchForMessagesIntentResponse> completion)
{
    // Implement the application logic to find a message that matches the information in the intent.
    ...

    var userActivity = new NSUserActivity (nameof (INSearchForMessagesIntent));
    var response = new INSearchForMessagesIntentResponse (INSearchForMessagesIntentResponseCode.Success, userActivity);

    // Initialize with found message's attributes
    var sender = new INPerson (new INPersonHandle ("sarah@example.com", INPersonHandleType.EmailAddress), null, "Sarah", null, null, null);
    var recipient = new INPerson (new INPersonHandle ("+1-415-555-5555", INPersonHandleType.PhoneNumber), null, "John", null, null, null);
    var message = new INMessage ("identifier", "I am so excited about SiriKit!", NSDate.Now, sender, new INPerson [] { recipient });
    response.Messages = new INMessage [] { message };
    completion (response);
}

public void HandleSetMessageAttribute (INSetMessageAttributeIntent intent, Action<INSetMessageAttributeIntentResponse> completion)
{
    // Implement the application logic to set the message attribute here.
    ...

    var userActivity = new NSUserActivity (nameof (INSetMessageAttributeIntent));
    var response = new INSetMessageAttributeIntentResponse (INSetMessageAttributeIntentResponseCode.Success, userActivity);
    completion (response);
}

如需詳細資訊,請參閱我們的 句柄階段參考

新增意圖UI擴充功能

選擇性的意圖 UI 延伸模組提供將應用程式的 UI 和品牌帶入 Siri 體驗的機會,並讓用戶感覺已連線到應用程式。 透過此延伸模組,應用程式可以將品牌以及視覺效果和其他資訊帶入文字記錄中。

意圖UI延伸模組輸出範例

就像意圖擴充功能一樣,開發人員會針對意圖 UI 延伸模組執行下列步驟:

  • 將意圖UI延伸模組專案新增至 Xamarin.iOS 應用程式解決方案。
  • 設定意圖 UI 延伸模組 Info.plist 檔案。
  • 修改 Intents UI 擴充功能主要類別。

如需詳細資訊,請參閱我們的 意圖UI延伸模組參考 和Apple 提供自定義介面參考

建立延伸模組

若要將意圖 UI 延伸模組新增至解決方案,請執行下列動作:

  1. 以滑鼠右鍵按兩下 Solution Pad 中的 [方案名稱],然後選取 [新增>新增專案...]。

  2. 從對話框中選取 [iOS>擴充功能>意圖 UI 擴充功能],然後按兩下 [下一步] 按鈕:

    選取意圖 UI 延伸模組

  3. 接下來,輸入意圖延伸模組的名稱,然後按兩下一步按鈕

    在 Visual Studio for Mac 中輸入意圖延伸模組的名稱。

  4. 最後,按兩下 [ 建立] 按鈕,將意圖延伸模組新增至應用程式解決方案:

    在 Visual Studio for Mac 中將意圖擴充功能新增至應用程式解決方案。

  5. 方案總管 中,以滑鼠右鍵按下新建立意圖延伸模組的 [參考] 資料夾。 檢查通用共享程式代碼連結庫項目的名稱(上面建立的應用程式),然後按下 [ 確定 ] 按鈕:

    在 Visual Studio for Mac 中選取通用共用程式代碼庫項目的名稱。

設定 Info.plist

將意圖 UI 延伸模組的 Info.plist 檔案設定為使用應用程式。

就像任何一般應用程式延伸模組一樣,應用程式會有和NSExtensionAttributes的現有索引鍵NSExtension。 針對意圖延伸模組,必須設定一個新的屬性:

必須設定的新屬性

需要 IntentsSupported ,並且由應用程式想要從意圖延伸模組支援的意圖類別名稱陣列所組成。

若要設定意圖 UI 延伸模組的Info.plist檔案,請在 方案總管按兩下它以開啟它以供編輯。 接下來,切換至 [ 來源 ] 檢視,然後在編輯器中展開 NSExtensionNSExtensionAttributes 索引鍵:

編輯器中的 NSExtension 和 NSExtensionAttributes 索引鍵。

展開機碼, IntentsSupported 並新增此延伸模組將支援的任何意圖類別名稱。 例如,MonkeyChat 應用程式支援 INSendMessageIntent

如需可用意圖網域的完整清單,請參閱Apple的 意圖網域參考

設定Main類別

將主要類別設定為 Siri 中意圖 UI 延伸模組的主要進入點。 它必須是符合 介面的UIViewControllerIINUIHostedViewController子類別。 例如:

using System;
using Foundation;
using CoreGraphics;
using Intents;
using IntentsUI;
using UIKit;

namespace MonkeyChatIntentsUI
{
    public partial class IntentViewController : UIViewController, IINUIHostedViewControlling
    {
        #region Constructors
        protected IntentViewController (IntPtr handle) : base (handle)
        {
            // Note: this .ctor should not contain any initialization logic.
        }
        #endregion

        #region Override Methods
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            // Do any required interface initialization here.
        }

        public override void DidReceiveMemoryWarning ()
        {
            // Releases the view if it doesn't have a superview.
            base.DidReceiveMemoryWarning ();

            // Release any cached data, images, etc that aren't in use.
        }
        #endregion

        #region Public Methods
        [Export ("configureWithInteraction:context:completion:")]
        public void Configure (INInteraction interaction, INUIHostedViewContext context, Action<CGSize> completion)
        {
            // Do configuration here, including preparing views and calculating a desired size for presentation.

            if (completion != null)
                completion (DesiredSize ());
        }

        [Export ("desiredSize:")]
        public CGSize DesiredSize ()
        {
            return ExtensionContext.GetHostedViewMaximumAllowedSize ();
        }
        #endregion
    }
}

Siri 會將類別實例傳遞 INInteractionConfigure 意圖 UI 延伸模組內實例的方法 UIViewController

物件 INInteraction 會提供延伸模組的三個主要資訊片段:

  1. 正在處理的 Intent 物件。
  2. 意圖 Confirm 擴充功能的 和 Handle 方法的 Intent Response 物件。
  3. 定義應用程式與 Siri 之間互動狀態的互動狀態。

實例 UIViewController 是與 Siri 互動的原則類別,因為它繼承自 UIViewController,因此可以存取 UIKit 的所有功能。

當 Siri 呼叫Configure傳遞的 方法UIViewController時,它會傳入檢視內容,指出檢視控制器會裝載在 Siri Snippit 或 地圖 Card 中。

Siri 也會傳入完成處理程式,應用程式在應用程式完成設定之後,必須傳回所需的檢視大小。

在 iOS 設計工具中設計 UI

在 iOS 設計工具中設定意圖 UI 延伸模組的使用者介面。 按兩下 方案總管中的延伸模組MainInterface.storyboard檔案,以開啟它進行編輯。 拖曳到所有必要的 UI 元素,以建置使用者介面並儲存變更。

重要

雖然可以新增互動式元素,例如 UIButtonsUITextFields 的意圖UI延伸模組 UIViewController,但這些是絕對禁止的,因為非互動式的意圖UI,而且使用者將無法與其互動。

連接使用者介面

在 iOS 設計工具中建立意圖 UI 延伸模組的使用者介面之後,編輯 UIViewController 子類別並覆寫 Configure 方法,如下所示:

[Export ("configureWithInteraction:context:completion:")]
public void Configure (INInteraction interaction, INUIHostedViewContext context, Action<CGSize> completion)
{
    // Do configuration here, including preparing views and calculating a desired size for presentation.
    ...

    // Return desired size
    if (completion != null)
        completion (DesiredSize ());
}

[Export ("desiredSize:")]
public CGSize DesiredSize ()
{
    return ExtensionContext.GetHostedViewMaximumAllowedSize ();
}

覆寫預設 Siri UI

意圖UI延伸模組一律會與其他Siri內容一起顯示,例如UI頂端的應用程式圖示和名稱,或根據意圖、按鈕(例如傳送或取消)可能會顯示在底部。

有幾個實例,應用程式可以取代 Siri 預設向使用者顯示的資訊,例如訊息或地圖,讓應用程式可以使用針對應用程式量身訂做的預設體驗來取代預設體驗。

如果意圖 UI 延伸模組需要覆寫預設 Siri UI 的元素, UIViewController 子類別將需要實 IINUIHostedViewSiriProviding 作 介面,並加入加入以顯示特定介面元素。

將下列程式代碼新增至 UIViewController 子類別,以告訴 Siri 意圖 UI 延伸模組已經顯示訊息內容:

public bool DisplaysMessage {
    get {return true;}
}

考量

Apple 建議開發人員在設計和實作意圖 UI 延伸模組時考慮下列考慮:

  • 注意記憶體使用量 - 因為意圖 UI 延伸模組是暫時的,而且只會在短時間內顯示,因此系統會強加比完整應用程式使用更嚴格的記憶體限制。
  • 請考慮最小和最大檢視大小 - 確定意圖 UI 延伸模組在每個 iOS 裝置類型、大小和方向上看起來都不錯。 此外,應用程式傳送回 Siri 所需的大小可能無法授與。
  • 使用彈性和調適型版面配置模式 - 同樣地,確保UI在每個裝置上看起來都很棒。

摘要

本文涵蓋 SiriKit,並示範如何將它新增至 Xamarin.iOS 應用程式,以提供使用者可在 iOS 裝置上使用 Siri 和 地圖 應用程式存取的服務。