Xamarin.iOS 中的 Siri 快捷方式
在 iOS 10 中,Apple 引進 SiriKit,讓您能夠建置與 Siri 互動的訊息、VoIP 通話、付款、鍛煉、乘坐預約和相片搜尋應用程式。
在 iOS 11 中,SiriKit 已獲得更多應用程式類型的支援,並提升 UI 自定義的彈性。
iOS 12 新增 Siri 快捷方式,允許所有類型的應用程式向 Siri 公開其功能。 Siri 瞭解特定應用程式型工作與使用者最相關的時機,並使用此知識透過 快捷方式建議潛在動作。 點選快捷方式,或使用語音命令叫用它,將會開啟應用程式或執行背景工作。
快捷方式應該用來加速使用者完成一般工作的能力– 在許多情況下,甚至不需要開啟有問題的應用程式。
範例應用程式:湯 Chef
若要進一步瞭解 Siri 快捷方式,請參閱湯廚師範例應用程式。 湯廚師可讓使用者從虛構的湯餐廳訂購訂單、檢視其訂單歷程記錄,以及定義在與 Siri 互動訂購湯時要使用的片語。
提示
在 iOS 12 模擬器或裝置上測試湯 Chef 之前,請啟用下列兩個設定,在偵錯快捷方式時很有用:
- 在 設定 應用程式中,啟用開發人員>顯示最近的快捷方式。
- 在 設定 應用程式中,啟用 [鎖定畫面上的開發人員>顯示捐款]。
這些偵錯設定可讓您輕鬆地在 iOS 鎖定畫面和搜尋畫面上尋找最近建立的快捷方式(而不是預測的)。
若要使用範例應用程式:
- 在 iOS 12 模擬器或 裝置上安裝並執行湯 Chef 範例應用程式。
- +按兩下右上角的按鈕以建立新訂單。
- 選取湯的類型、指定數量和選項,然後點選 [下單]。
- 在 [ 訂單歷程記錄] 畫面上,點選新建立的訂單以檢視其詳細數據。
- 在訂單詳細數據畫面底部,點選 [新增至 Siri]。
- 錄製語音片語以與訂單產生關聯,然後點選 [完成]。
- 將湯廚師最小化、叫用 Siri,然後使用您錄製的語音片語再次下單。
- Siri 完成訂單之後,請重新開啟湯廚師,並注意到新訂單會列在 [訂單歷程記錄 ] 畫面上。
範例應用程式示範如何:
Info.plist 和 Entitlements.plist
在深入探索湯 Chef 程式代碼之前,請先看看其 Info.plist 和 Entitlements.plist 檔案。
Info.plist
湯Chef 專案中的 Info.plist 檔案會將套件組合識別元com.xamarin.SoupChef
定義為 。 此套件組合標識碼將作為本檔稍後討論之意圖和意圖 UI 延伸模組套件組合識別碼的前置詞。
Info.plist 檔案也包含下列專案:
<key>NSUserActivityTypes</key>
<array>
<string>OrderSoupIntent</string>
<string>com.xamarin.SoupChef.viewMenu</string>
</array>
這個 NSUserActivityTypes
機碼/值組表示湯廚師知道如何處理 OrderSoupIntent
,以及 NSUserActivity
具有 ActivityType
“com.xamarin.湯Chef.viewMenu” 的 。
在 中處理傳遞至應用程式本身的活動和自定義意圖,與其擴充 AppDelegate
UIApplicationDelegate
ContinueUserActivity
功能相反。
Entitlements.plist
SoupChef 專案中的 Entitlements.plist 檔案包含下列專案:
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.xamarin.SoupChef</string>
</array>
<key>com.apple.developer.siri</key>
<true/>
此組態表示應用程式使用 「group.com.xamarin.SoupChef」 應用程式群組。 SoupChefIntents 應用程式延伸模組會使用相同的應用程式群組,這可讓兩個項目共用NSUserDefaults
數據。
機 com.apple.developer.siri
碼表示應用程式與 Siri 互動。
注意
湯切夫項目的組建組態會將自定義權利設定為 Entitlements.plist。
使用 NSUserActivity 快捷方式開啟應用程式
若要建立可開啟應用程式以顯示特定內容的快捷方式,請建立 NSUserActivity
,並將它附加至您想要開啟快捷方式之畫面的檢視控制器。
設定 NSUserActivity
在功能表畫面上, SoupMenuViewController
建立 NSUserActivity
並將它指派給檢視控制器的 UserActivity
屬性:
public override void ViewDidLoad()
{
base.ViewDidLoad();
UserActivity = NSUserActivityHelper.ViewMenuActivity;
}
設定 屬性會將UserActivity
活動捐贈給 Siri。 從這項捐贈中,Siri 會取得有關使用者何時和何處相關活動的資訊,並學會在未來進一步建議。
NSUserActivityHelper
是湯Chef解決方案中包含的公用程式類別,位於湯基特類別庫中。 它會建立 NSUserActivity
並設定與 Siri 和搜尋相關的各種屬性:
public static string ViewMenuActivityType = "com.xamarin.SoupChef.viewMenu";
public static NSUserActivity ViewMenuActivity {
get
{
var userActivity = new NSUserActivity(ViewMenuActivityType)
{
Title = NSBundleHelper.SoupKitBundle.GetLocalizedString("ORDER_LUNCH_TITLE", "View menu activity title"),
EligibleForSearch = true,
EligibleForPrediction = true
};
var attributes = new CSSearchableItemAttributeSet(NSUserActivityHelper.SearchableItemContentType)
{
ThumbnailData = UIImage.FromBundle("tomato").AsPNG(),
Keywords = ViewMenuSearchableKeywords,
DisplayName = NSBundleHelper.SoupKitBundle.GetLocalizedString("ORDER_LUNCH_TITLE", "View menu activity title"),
ContentDescription = NSBundleHelper.SoupKitBundle.GetLocalizedString("VIEW_MENU_CONTENT_DESCRIPTION", "View menu content description")
};
userActivity.ContentAttributeSet = attributes;
var phrase = NSBundleHelper.SoupKitBundle.GetLocalizedString("ORDER_LUNCH_SUGGESTED_PHRASE", "Voice shortcut suggested phrase");
userActivity.SuggestedInvocationPhrase = phrase;
return userActivity;
}
}
請特別注意下列功能:
- 設定
EligibleForPrediction
表示true
Siri 可以預測此活動,並將其呈現為快捷方式。 ContentAttributeSet
數位是CSSearchableItemAttributeSet
用來在NSUserActivity
iOS 搜尋結果中包含的標準。SuggestedInvocationPhrase
是 Siri 在將片語指派給快捷方式時,建議使用者作為潛在選擇的片語。
處理 NSUserActivity 快捷方式
若要處理 NSUserActivity
使用者叫用的快捷方式,iOS 應用程式必須覆寫 ContinueUserActivity
類別的 AppDelegate
方法,並根據 ActivityType
傳入 NSUserActivity
物件的欄位回應:
public override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)
{
// ...
else if (userActivity.ActivityType == NSUserActivityHelper.ViewMenuActivityType)
{
HandleUserActivity();
return true;
}
// ...
}
這個方法會呼叫 HandleUserActivity
,它會尋找功能表畫面的 Segue 並叫用它:
void HandleUserActivity()
{
var rootViewController = Window?.RootViewController as UINavigationController;
var orderHistoryViewController = rootViewController?.ViewControllers?.FirstOrDefault() as OrderHistoryTableViewController;
if (orderHistoryViewController is null)
{
Console.WriteLine("Failed to access OrderHistoryTableViewController.");
return;
}
var segue = OrderHistoryTableViewController.SegueIdentifiers.SoupMenu;
orderHistoryViewController.PerformSegue(segue, null);
}
將片語指派給 NSUserActivity
若要將片語指派給 NSUserActivity
,請開啟 iOS 設定 應用程式,然後選擇 [Siri] 和 [搜尋>我的快捷方式]。 然後,選取快捷方式(在此案例中為「訂購午餐」),並記錄片語。
叫用 Siri 並使用這個片語會將湯廚師開啟至功能表畫面。
使用自定義意圖快捷方式來執行工作
定義自定義意圖
若要提供快捷方式,讓用戶能夠快速完成與您的應用程式相關的特定工作,請建立自定義意圖。 自定義意圖代表使用者可能想要完成的工作、與該工作相關的參數,以及工作執行所產生的潛在回應。 根據自定義意圖的定義方式,叫用它可以開啟您的應用程式或執行背景工作。
使用 Xcode 10 建立自定義意圖。 在湯Chef 存放庫中,自定義意圖定義於專案 OrderSoupIntentCodeGenObjective-C 中。 開啟此專案,然後選取 Project Navigator 中的 Intents.intentdefinition 檔案,以檢視 OrderSoup 意圖。
請注意下列功能:
- 意圖具有 Order 的 Category。 有各種預先定義的類別可用於自定義意圖;選取最符合您自定義意圖將啟用之工作的工作。 由於此解決方案是湯訂購應用程式, OrderSoupIntent 會使用 Order。
- [ 確認] 複選框指出 Siri 是否在執行工作之前,必須要求確認。 針對湯 Chef 中的 Order 湯意圖,因為使用者正在購買,因此會啟用此選項。
- .intentdefinition 檔案的 Parameters 區段會定義與快捷方式相關的參數。 若要訂購湯,湯廚師必須知道湯的類型、其數量,以及任何相關聯的選項。 每個參數都有類型;無法以預先定義型別表示的參數會設定為 Custom。
- 快捷方式 類型 介面描述 Siri 在建議快捷方式時可以使用的各種參數組合。 相關聯的 [標題 ] 和 [子標題 ] 區段可讓您定義 Siri 在向使用者呈現建議快捷方式時將使用的訊息。
- 應該針對任何可以執行的快捷方式選取 [支援背景執行] 複選框,而不需開啟應用程式以進行進一步的用戶互動。
定義自定義意圖回應
OrderSoup 意圖下方的 Response 專案代表湯訂單所產生的潛在回應。
在 OrderSoup 意圖的回應定義中,請注意下列功能:
- 回應的屬性可用來自定義傳回給使用者的訊息。 OrderSoup 意圖回應具有湯和 waitTime 屬性。
- 回應 範本 會指定各種成功和失敗訊息,這些訊息可用來指出意圖工作完成後的狀態。
- 應該針對指出成功的響應選取 [ 成功 ] 複選框。
- OrderSoupIntent 成功回應會使用湯和 waitTime 屬性來提供友好且實用的訊息,描述湯訂單何時就緒。
產生自定義意圖的程序代碼
建置包含此自定義意圖定義的 Xcode 專案會導致 Xcode 產生程式代碼,以程式設計方式與自定義意圖及其響應互動。
若要檢視這個產生的程式代碼:
- 開啟 AppDelegate.m。
- 將匯入新增至自訂意圖的頭檔:
#import "OrderSoupIntent.h"
- 在類別中的任何方法中,新增 對 的
OrderSoupIntent
參考。 - 以滑鼠右鍵按下
OrderSoupIntent
並選擇 [ 跳至定義]。 - 以滑鼠右鍵按下新開啟的檔案 OrderSoupIntent.h,然後選取 [在 Finder 中顯示]。
- 此動作會開啟包含 .h 和 .m 檔案的 Finder 視窗,其中包含產生的程序代碼。
此產生的程式代碼包括:
OrderSoupIntent
– 表示自定義意圖的類別。OrderSoupIntentHandling
– 一種通訊協定,定義將用來確認應該執行意圖的方法,以及實際執行意圖的方法。OrderSoupIntentResponseCode
– 定義各種回應狀態的列舉。OrderSoupIntentResponse
– 類別,表示意圖執行的回應。
建立自定義意圖的系結
若要在 Xamarin.iOS 應用程式中使用 Xcode 所產生的程式代碼,請為其建立 C# 系結。
建立靜態庫和 C# 系結定義
在湯Chef 存放庫中,查看 OrderSoupIntentStaticLib 資料夾,然後開啟 OrderSoupIntentStaticLib.xcodeproj Xcode 專案。
此 Cocoa Touch 靜態庫 專案包含 Xcode 所產生的 OrderSoupIntent.h 和 OrderSoupIntent.m 檔案。
設定靜態庫專案組建設定
在 Xcode 專案導覽器中,選取最上層專案 OrderSoupIntentStaticLib,然後流覽至 [建置階段 > 編譯來源]。 請注意, OrderSoupIntent.m (匯入 OrderSoupIntent.h) 列在這裡。 在 [鏈接二進位檔與連結庫] 中,請注意 會包含 Intents.framework 和 Foundation.framework 。 使用這些設定,架構將會正確建置。
建置靜態庫併產生 C# 系結定義
若要建置靜態庫併為其產生 C# 系結定義,請遵循下列步驟:
安裝 Objective Sharpie,此工具用來從 Xcode 所建立的 .h 和 .m 檔案產生系結定義。
將您的系統設定為使用 Xcode 10 命令列工具:
警告
更新選取 的命令行工具 會影響系統上所有已安裝的 Xcode 版本。 當您使用湯 Chef 範例應用程式完成時,請務必將此設定還原為其原始組態。
- 在 Xcode 中,選擇 [Xcode > 喜好>設定位置],並將 [命令行工具] 設定為系統上可用的最新 Xcode 10 安裝。
在終端機中,
cd
移至 OrderSoupIntentStaticLib 目錄。輸入
make
,其會建置:- 靜態庫 libOrderSoupIntentStaticLib.a
- 在 bo 輸出目錄中,C# 系結定義:
- ApiDefinitions.cs
- StructsAndEnums.cs
依賴此靜態庫及其相關聯繫結定義的 OrderSoupIntentBindings 專案會自動建置這些專案。 不過,手動執行上述程式可確保其如預期般建置。
如需建立靜態庫和使用 Objective Sharpie 建立 C# 系結定義的詳細資訊,請參閱 系結 iOS Objective-C 連結庫 逐步解說。
建立系結連結庫
建立靜態庫和 C# 系結定義之後,Xamarin.iOS 專案中取用 Xcode 產生的意圖相關程式碼所需的其餘部分是系結連結庫。
在湯 Chef 存放庫中,開啟SoupChef.sln檔案。 除此之外,此解決方案還 包含 OrderSoupIntentBinding,這是稍早所產生靜態庫的系結連結庫。
請注意,此專案包含:
ApiDefinitions.cs – Objective Sharpie 稍早產生的檔案,並新增至此專案。 此檔案的 建置動作 設定為 ObjcBindingApiDefinition。
StructsAndEnums.cs – Objective Sharpie 稍早產生的另一個檔案,並新增至此專案。 此檔案的 建置動作 設定為 ObjcBindingCoreSource。
libOrderSoupIntentStaticLib.a 的原生參考,這是稍早建置的靜態庫。 更新原生參考屬性,並指定下列值:
- Frameworks =
Foundation Intents
- Smart Link =
On
- 強制載入 =
On
- Kind =
Static
- Frameworks =
注意
ApiDefinitions.cs和StructsAndEnums.cs都包含屬性,例如 [Watch (5,0), iOS (12,0)]
。 Objective Sharpie 所產生的這些屬性已標記為批註,因為此專案並非必要屬性。
如需建立 C# 系結連結庫的詳細資訊,請參閱 系結 iOS Objective-C 連結庫 逐步解說。
請注意,湯Chef 專案包含 OrderSoupIntentBinding 的參考,這表示它現在可以在 C# 中存取它所包含的類別、介面和列舉:
OrderSoupIntent
OrderSoupIntentHandling
OrderSoupIntentResponse
OrderSoupIntenseResponseCode
建立 Swift 架構
根據預設,使用原生項目的語言,Xcode 會產生意圖定義機器碼。 如果您在 Swift 專案中定義 Intents.intentdefinition 檔案,Xcode 將會產生具有所有必要類別的單一 Swift 檔案,您可以使用這個檔案來建立 Swift 架構。
提示
您可以在 Xcode 組建設定中,為產生的意圖程式代碼選取所需的語言。 移至 [意圖目標>組建 設定 > 意圖定義編譯程式 - 程式代碼產生],然後選取 Swift 或 Objective-C。 您也可以讓它保持自動,以符合您的目標語言。
建立 Swift 架構的程式類似於先前所述的程式:
- 建立新的 Swift 架構專案。
- 將具有意圖程式代碼的自動產生的 Swift 檔案複製到此專案,您可以找到此檔案,如這裡所述。
- Objective-C開啟橋接標頭,因此架構會自動產生與 sharpie 標頭檔所需的 Objective-C 。
建置架構之後,請遵循 先前所述的相同步驟 來建立 Xamarin 系結。 您可以在這裡深入瞭解如何建立 Swift 架構的系結。
將意圖定義檔新增至您的解決方案
在 C# 湯Chef 解決方案中 ,湯基 特專案包含應用程式與其延伸模組之間共用的程序代碼。 Intents.intentdefinition 檔案已放在湯基的 Base.lproj 目錄中,且其具有內容的建置動作。 建置程式會將此檔案複製到湯 Chef 應用程式套件組合中,應用程式必須正確運作。
捐贈意圖
為了讓 Siri 建議快捷方式,必須先瞭解快捷方式何時相關。
為了給予 Siri 這個理解,湯廚師 每次使用者放置湯訂單時,都會向 Siri 捐贈 意圖。 根據這項捐贈 -- 當捐贈時,捐贈地點,它所包含的參數 – Siri 會瞭解未來何時建議快捷方式。
湯切夫 使用 SoupOrderDataManager
類別來捐贈。
呼叫 以為使用者下湯訂單時, PlaceOrder
方法會接著呼叫 DonateInteraction
:
void DonateInteraction(Order order)
{
var interaction = new INInteraction(order.Intent, null);
interaction.Identifier = order.Identifier.ToString();
interaction.DonateInteraction((error) =>
{
// ...
});
}
擷取意圖之後,它會包裝在 中 INInteraction
。
INInteraction
已提供Identifier
符合訂單的唯一標識碼(刪除不再有效的意圖捐贈時,會很有説明)。 然後,互動會捐贈給 Siri。
呼叫 order.Intent
getter 會擷取 OrderSoupIntent
代表訂單的 ,方法是設定其 Quantity
、 Soup
、 Options
和 影像,以及當用戶記錄 Siri 與意圖關聯的片語時,用來做為建議的調用片語:
public OrderSoupIntent Intent
{
get
{
var orderSoupIntent = new OrderSoupIntent();
orderSoupIntent.Quantity = new NSNumber(Quantity);
orderSoupIntent.Soup = new INObject(MenuItem.ItemNameKey, MenuItem.LocalizedString);
var image = UIImage.FromBundle(MenuItem.IconImageName);
if (!(image is null))
{
var data = image.AsPNG();
orderSoupIntent.SetImage(INImage.FromData(data), "soup");
}
orderSoupIntent.Options = MenuItemOptions
.ToArray<MenuItemOption>()
.Select<MenuItemOption, INObject>(arg => new INObject(arg.Value, arg.LocalizedString))
.ToArray<INObject>();
var comment = "Suggested phrase for ordering a specific soup";
var phrase = NSBundleHelper.SoupKitBundle.GetLocalizedString("ORDER_SOUP_SUGGESTED_PHRASE", comment);
orderSoupIntent.SuggestedInvocationPhrase = String.Format(phrase, MenuItem.LocalizedString);
return orderSoupIntent;
}
}
拿掉無效的捐款
請務必移除不再有效的捐款,讓 Siri 不會提供無益或令人困惑的快捷方式建議。
在 [湯廚師] 中 ,[設定功能表 ] 畫面可用來將功能表項標示為無法使用。 Siri 不應該再建議快捷方式來排序無法使用的功能表項,因此刪除 RemoveDonation
不再可用的功能表項捐款的方法 SoupMenuManager
。 應用程式會透過下列方式實作這項功能:
- 尋找與目前無法使用功能表項相關聯的訂單。
- 擷取其標識碼。
- 刪除具有相同標識碼的互動。
void RemoveDonation(MenuItem menuItem)
{
if (!menuItem.IsAvailable)
{
Order[] orderHistory = OrderManager?.OrderHistory.ToArray<Order>();
if (orderHistory is null)
{
return;
}
string[] orderIdentifiersToRemove = orderHistory
.Where<Order>((order) => order.MenuItem.ItemNameKey == menuItem.ItemNameKey)
.Select<Order, string>((order) => order.Identifier.ToString())
.ToArray<string>();
INInteraction.DeleteInteractions(orderIdentifiersToRemove, (error) =>
{
if (!(error is null))
{
Console.WriteLine($"Failed to delete interactions with error {error.ToString()}");
}
else
{
Console.WriteLine("Successfully deleted interactions");
}
});
}
}
驗證成功的捐款
解決方案包含多個專案和特定組態。 在某些情況下,應用程式可能會因為設定不完整而當機,在其他情況下,應用程式可能會以無訊息方式無法捐贈互動。 請務必驗證成功的捐款,而 iOS 開發人員設定有助於它。 流覽至 [設定 > 開發人員],並啟用下列開發人員選項,以查看最近的捐款和快捷方式:
- 顯示最近的快捷方式
- 在鎖定畫面上顯示捐款
啟用之後,每個成功的捐贈都會出現在鎖定畫面上,並在 Siri 建議選項下方顯示。 如果在執行應用程式之後,您看不到該處的捐款,請檢閱下列疑難解答案例:
應用程式無法建立
OrderSoupIntent
,並出現下列錯誤:無法建立 'NativeLibrary.OrderSoupIntent' 類型的原生實例:尚未載入原生類別。
此錯誤表示 Xamarin 無法透過 Xamarin 系結載入原生類別。 若要修正此問題,請確認原生連結庫包含系結項目所參考的必要程序代碼,並已設定適當的旗標,如這裡所述,將
Force Load
旗標設定為On
。應用程式無法初始化意圖類別載入的原生實例,並出現下列錯誤:
無法初始化類型 'NativeLibrary.OrderSoupIntent' 的實例:傳回 nil 的原生 'init' 方法。
此問題與遺漏的意圖定義檔案有關。 Xamarin 應用程式應該包含具有
Content
類型的原始意圖定義檔,如這裡所述。應用程式會建立意圖並呼叫捐贈方法,而不會當機,但控制台輸出會顯示未知意圖類型的警告,而且不會進行捐贈:
無法捐贈沒有有效快捷鍵類型的 OrderSoupIntent 互動
若要修正意圖必須在 plist 中正確定義的問題,必須透過項目設定啟用並選取 Siri 權利以供目前的組建組態使用。
應用程式的 info.plist:
<key>NSUserActivityTypes</key> <array> <string>ScheduleMeetingIntent</string> </array>
具有 Siri 功能之應用程式的 Entitlements.plist:
<key>com.apple.developer.siri</key> <true/>
應針對目標組建組態選取自定義權利。 移至 [項目設定>] [建>置 iOS 套件組合簽署],並將 [自定義權利] 設定為包含所需權利的權利的 Entitlements.plist 檔案。
建立意圖延伸模組
當 Siri 叫用意圖時執行的程式代碼會放在意圖延伸模組中,其可新增為與湯 Chef 等現有 Xamarin.iOS 應用程式相同的解決方案的新專案。 在湯Chef 解決方案中,延伸模組稱為湯ChefIntents。
湯ChefIntents – Info.plist 和 Entitlements.plist
SoupChefIntents – Info.plist
SoupChefIntents 專案中的 Info.plist 會將套件組合識別元com.xamarin.SoupChef.SoupChefIntents
定義為 。
Info.plist 檔案也包含下列專案:
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>IntentsRestrictedWhileLocked</key>
<array/>
<key>IntentsSupported</key>
<array>
<string>OrderSoupIntent</string>
</array>
<key>IntentsRestrictedWhileProtectedDataUnavailable</key>
<array/>
</dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.intents-service</string>
<key>NSExtensionPrincipalClass</key>
<string>IntentHandler</string>
</dict>
在上述 Info.plist 中:
IntentsRestrictedWhileLocked
列出解除鎖定裝置時要處理的意圖。IntentsSupported
列出此延伸模組所處理的意圖。NSExtensionPointIdentifier
指定應用程式延伸模組的類型。 如需詳細資訊,請參閱 Apple的檔。NSExtensionPrincipalClass
指定應該用來處理此延伸模組所支援意圖的類別。
湯ChefIntents – Entitlements.plist
湯ChefIntents 專案中的 Entitlements.plist 具有應用程式群組功能。 這項功能設定為使用與 湯Chef 專案相同的應用程式群組:
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.xamarin.SoupChef</string>
</array>
湯 Chef 會使用 NSUserDefaults
保存數據。 為了在應用程式與應用程式延伸模組之間共用數據,他們會在其 Entitlements.plist 檔案中參考相同的應用程式群組。
注意
SoupChefIntents 專案的組建組態會將自定義權利設定為 Entitlements.plist。
處理 OrderSoupIntent 背景工作
意圖延伸模組會根據自定義意圖執行快捷方式的必要背景工作。
Siri 會呼叫 GetHandler
類別的 IntentHandler
方法(定義於 Info.plist 中為 NSExtensionPrincipalClass
,以取得擴充 OrderSoupIntentHandling
的類別實例,可用來處理 OrderSoupIntent
:
[Register("IntentHandler")]
public class IntentHandler : INExtension
{
public override NSObject GetHandler(INIntent intent)
{
if (intent is OrderSoupIntent)
{
return new OrderSoupIntentHandler();
}
throw new Exception("Unhandled intent type: ${intent}");
}
protected IntentHandler(IntPtr handle) : base(handle) { }
}
OrderSoupIntentHandler
,定義於共用程式代碼的 湯基特 專案中,會實作兩個重要的方法:
ConfirmOrderSoup
– 確認是否應該實際執行與意圖相關聯的工作HandleOrderSoup
– 藉由呼叫傳入的完成處理程式來放置湯順序並回應使用者
處理開啟應用程式的 OrderSoupIntent
應用程式必須正確處理未在背景執行的意圖。
在的 方法AppDelegate
中ContinueUserActivity
,這些意圖的處理方式與NSUserActivity
快捷方式相同:
public override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)
{
var intent = userActivity.GetInteraction()?.Intent as OrderSoupIntent;
if (!(intent is null))
{
HandleIntent(intent);
return true;
}
// ...
}
提供自定義意圖的使用者介面
意圖UI延伸模組提供意圖延伸模組的自訂使用者介面。 在湯Chef 解決方案中,湯ChefIntentsUI 是意圖UI延伸模組,可提供湯ChefIntents的介面。
SoupChefIntentsUI – Info.plist 和 Entitlements.plist
SoupChefIntentsUI – Info.plist
SoupChefIntentsUI 專案中的 Info.plist 會將套件組合識別碼com.xamarin.SoupChef.SoupChefIntentsui
定義為 。
Info.plist 檔案也包含下列專案:
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>IntentsSupported</key>
<array>
<string>OrderSoupIntent</string>
</array>
<!-- ... -->
</dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.intents-ui-service</string>
<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>
</dict>
在上述 Info.plist 中:
IntentsSupported
OrderSoupIntent
表示這個意圖 UI 延伸模組會處理 。NSExtensionPointIdentifier
指定應用程式延伸模組的類型。 如需詳細資訊,請參閱 Apple的檔。NSExtensionMainStoryboard
指定定義此延伸模組主要介面的分鏡腳本
SoupChefIntentsUI – Entitlements.plist
SoupChefIntentsUI 專案不需要 Entitlements.plist 檔案。
建立使用者介面
由於 SoupChefIntentsUI 的 Info.plist 會將索引鍵設定NSExtensionMainStoryboard
為 MainInterface
,MainInterace.storyboard 檔案會定義 Intents UI 延伸模組的介面。
在此分鏡腳本中,有一個類型為IntentViewController的單一檢視控制器。 它會參考兩個檢視:
- invoiceView,類型為
InvoiceView
- 確認檢視,類型為
ConfirmOrderView
注意
invoiceView 和 confirmationView 的介面會在 Main.storyboard 中定義為次要檢視。 Visual Studio for Mac 和 Visual Studio 2017 不支持檢視或編輯次要檢視;若要這樣做,請在 Xcode 的 Interface Builder 中開啟 Main.storyboard 。
IntentViewController
實作 IINUIHostedViewControlling
介面,用來在處理 Siri 意圖時提供自定義介面。 ConfigureView
會呼叫 方法來自定義介面,並顯示確認或發票,視互動是否已確認 (INIntentHandlingStatus.Ready
) 或已順利執行而定 (INIntentHandlingStatus.Success
):
[Export("configureViewForParameters:ofInteraction:interactiveBehavior:context:completion:")]
public void ConfigureView(
NSSet<INParameter> parameters,
INInteraction interaction,
INUIInteractiveBehavior interactiveBehavior,
INUIHostedViewContext context,
INUIHostedViewControllingConfigureViewHandler completion)
{
// ...
if (interaction.IntentHandlingStatus == INIntentHandlingStatus.Ready)
{
desiredSize = DisplayInvoice(order, intent);
}
else if(interaction.IntentHandlingStatus == INIntentHandlingStatus.Success)
{
var response = interaction.IntentResponse as OrderSoupIntentResponse;
if (!(response is null))
{
desiredSize = DisplayOrderConfirmation(order, intent, response);
}
}
completion(true, parameters, desiredSize);
}
提示
如需方法 ConfigureView
的詳細資訊,請觀看Apple的WWDC 2017簡報 SiriKit的新功能。
建立語音快捷方式
湯廚師提供一個介面,將語音快捷方式指派給每個訂單,讓您能夠使用 Siri 訂購湯。 事實上,用來錄製和指派語音快捷方式的介面是由iOS提供,而且需要很少的自定義程序代碼。
在 中 OrderDetailViewController
,當使用者點選數據表的 [新增至 Siri ] 數據列時, RowSelected
方法會顯示畫面以新增或編輯語音快捷方式:
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
// ...
else if (TableConfiguration.Sections[indexPath.Section].Type == OrderDetailTableConfiguration.SectionType.VoiceShortcut)
{
INVoiceShortcut existingShortcut = VoiceShortcutDataManager?.VoiceShortcutForOrder(Order);
if (!(existingShortcut is null))
{
var editVoiceShortcutViewController = new INUIEditVoiceShortcutViewController(existingShortcut);
editVoiceShortcutViewController.Delegate = this;
PresentViewController(editVoiceShortcutViewController, true, null);
}
else
{
// Since the app isn't yet managing a voice shortcut for
// this order, present the add view controller
INShortcut newShortcut = new INShortcut(Order.Intent);
if (!(newShortcut is null))
{
var addVoiceShortcutVC = new INUIAddVoiceShortcutViewController(newShortcut);
addVoiceShortcutVC.Delegate = this;
PresentViewController(addVoiceShortcutVC, true, null);
}
}
}
}
根據目前顯示順序是否存在現有語音快捷方式, RowSelected
呈現 類型 INUIEditVoiceShortcutViewController
為 或 INUIAddVoiceShortcutViewController
的檢視控制器。
在每個案例中, OrderDetailViewController
將本身設定為檢視控制器的 Delegate
,這就是為什麼它也會實作的原因 IINUIAddVoiceShortcutViewControllerDelegate
和 IINUIEditVoiceShortcutViewControllerDelegate
。
在裝置上進行測試
若要在裝置上執行湯 Chef,請遵循本節中的指示。 另請閱讀 關於自動布建的附註。
應用程式群組、應用程式識別碼、布建配置檔
在 Apple Developer Portal 的 [憑證、 識別碼和設定檔] 區段中,執行下列步驟:
建立應用程式群組,以在湯 Chef 應用程式與其擴充功能之間共享數據。 例如: group.com.yourcompanyname.SoupChef
建立三個應用程式識別碼:一個用於應用程式本身、一個用於意圖擴充功能,另一個用於意圖UI擴充功能。 例如:
應用程式: com.yourcompanyname.SoupChef
- 若要使用此應用程式識別碼,請指派 SiriKit 和 應用程式群組 功能。
意圖延伸模組: com.yourcompanyname.SoupChef.Intents
- 若要使用此應用程式識別碼,請指派 應用程式群組 功能。
意圖 UI 延伸模組: com.yourcompanyname.SoupChef.Intentsui
- 此應用程式識別碼不需要特殊功能。
建立上述應用程式識別碼之後,請編輯 指派給應用程式和意圖延伸模組的應用程式群組 功能,並指定稍早建立的特定應用程式群組。
建立三個新的開發佈建配置檔,每個新的應用程式識別碼各一個。
下載這些布建配置檔,然後按兩下每個設定檔加以安裝。 如果 Visual Studio for Mac 或 Visual Studio 2017 已在執行中,請重新啟動它以確定它註冊新的布建配置檔。
編輯 Info.plist、Entitlements.plist 和原始程式碼
在 Visual Studio for Mac 或 Visual Studio 2017 中,執行下列步驟:
更新方案中的各種 Info.plist 檔案。 將應用程式、意圖延伸模組和意圖 UI 延伸模組 套件組合識別碼 設定為稍早定義的應用程式識別碼:
- 應用程式: com.yourcompanyname.SoupChef
- 意圖延伸模組: com.yourcompanyname.湯Chef.Intents
- 意圖 UI 延伸模組: com.yourcompanyname.SoupChef.Intentsui
更新 SoupChef 專案的 Entitlements.plist 檔案:
- 針對應用程式 群組 功能,請將群組設定為稍早建立的新應用程式群組(在上述範例中,它是 group.com.yourcompanyname.SoupChef)。
- 請確定 已啟用 SiriKit 。
更新湯ChefIntents 專案的 Entitlements.plist 檔案:
- 針對應用程式 群組 功能,請將群組設定為稍早建立的新應用程式群組(在上述範例中,它是 group.com.yourcompanyname.SoupChef)。
最後,開啟 NSUserDefaultsHelper.cs。 將
AppGroup
變數設定為新應用程式群組的值(例如,將它設定為group.com.yourcompanyname.SoupChef
)。
設定組建設定
在 Visual Studio for Mac 或 Visual Studio 2017 中:
開啟 SoupChef 項目的選項/屬性。 在 [iOS 套件組合簽署] 索引標籤上,將 [簽署身分識別] 設定為 [自動],並將 [布建配置檔] 設定為您稍早建立的新應用程式特定布建配置檔。
開啟 SoupChefIntents 項目的選項/屬性。 在 [iOS 套件組合簽署] 索引標籤上,將 [簽署身分識別] 設定為 [自動],並將 [布建配置檔] 設定為您稍早建立的新意圖擴充功能特定布建配置檔。
開啟 SoupChefIntentsUI 專案的選項/屬性。 在 [iOS 套件組合簽署] 索引標籤上,將 [簽署身分識別] 設定為 [自動],並將 [布建配置檔] 設定為您稍早建立的新意圖 UI 延伸模組專用布建配置檔。
有了這些變更,應用程式將會在iOS裝置上執行。
自動佈建
您可以使用 自動布建 ,直接在 IDE 中完成許多這些布建工作。 不過,自動布建不會設定應用程式群組。 您必須以您想要使用的應用程式群組名稱手動 設定 Entitlements.plist 檔案,請造訪 Apple Developer Portal 以建立應用程式群組、將該應用程式群組指派給自動布建所建立的每個應用程式識別碼、重新產生布建配置檔(應用程式、意圖延伸模組、意圖 UI 延伸模組)以包含新建立的應用程式群組, 並下載並安裝它們。