Siri-Tastenkombinationen in Xamarin.iOS
In iOS 10 hat Apple SiriKit eingeführt, sodass Messaging, VoIP-Anrufe, Zahlungen, Training, Fahrbuchungs- und Fotosuche-Apps erstellt werden können, die mit Siri interagieren.
In iOS 11 hat SiriKit Unterstützung für mehr Arten von Apps und mehr Flexibilität bei der Anpassung der Benutzeroberfläche erhalten.
iOS 12 fügt Siri-Tastenkombinationen hinzu, sodass alle Arten von Apps ihre Funktionen für Siri verfügbar machen können. Siri lernt, wenn bestimmte app-basierte Aufgaben für den Benutzer am relevantesten sind und dieses Wissen verwendet, um potenzielle Aktionen über Verknüpfungen vorzuschlagen. Durch Tippen auf eine Tastenkombination oder das Aufrufen mit einem Sprachbefehl wird eine App geöffnet oder eine Hintergrundaufgabe ausgeführt.
Tastenkombinationen sollten verwendet werden, um die Fähigkeit eines Benutzers zu beschleunigen, eine häufige Aufgabe auszuführen – in vielen Fällen, ohne die betreffende App sogar zu öffnen.
Beispiel-App: Suppenkoch
Um Siri Shortcuts besser zu verstehen, sehen Sie sich die Beispiel-App "Suppenkoch" an. Der Suppenkoch ermöglicht es Benutzern, Bestellungen aus einem imaginären Suppenrestaurant zu tätigen, ihre Bestellgeschichte anzuzeigen und Ausdrücke zu definieren, die beim Bestellen von Suppen verwendet werden sollen, indem sie mit Siri interagieren.
Tipp
Aktivieren Sie vor dem Testen von Soup Chef auf einem iOS 12-Simulator oder -Gerät die folgenden beiden Einstellungen, die beim Debuggen von Verknüpfungen nützlich sind:
- Aktivieren Sie in der Einstellungen-App "Entwickleranzeige > zuletzt verwendete Verknüpfungen".
- Aktivieren Sie in der Einstellungen-App "Entwickleranzeige > spenden" auf dem Sperrbildschirm.
Diese Debugeinstellungen erleichtern das Auffinden kürzlich erstellter (statt vorhergesagter) Verknüpfungen auf dem iOS-Sperrbildschirm und dem Suchbildschirm.
So verwenden Sie die Beispiel-App:
- Installieren und ausführen Sie die Soup Chef-Beispiel-App auf einem iOS 12-Simulator oder -Gerät.
- Klicken Sie in der oberen rechten Ecke auf die + Schaltfläche, um eine neue Reihenfolge zu erstellen.
- Wählen Sie eine Art Suppe aus, geben Sie eine Menge und Optionen an, und tippen Sie auf "Bestellung aufgeben".
- Tippen Sie auf dem Bildschirm "Bestellverlauf " auf die neu erstellte Bestellung, um die Details anzuzeigen.
- Tippen Sie unten im Bildschirm "Bestelldetails" auf " Zu Siri hinzufügen".
- Notieren Sie einen Sprachausdruck, um der Reihenfolge zuzuordnen, und tippen Sie auf "Fertig".
- Minimieren Sie den Suppenkoch, rufen Sie Siri auf, und platzieren Sie die Bestellung erneut, indem Sie den sprachausdruck verwenden, den Sie aufgezeichnet haben.
- Nachdem Siri die Bestellung abgeschlossen hat, öffnen Sie den Suppenkoch erneut, und beachten Sie, dass die neue Bestellung auf dem Bildschirm "Bestellverlauf " aufgeführt ist.
Die Beispiel-App veranschaulicht Folgendes:
- Verwenden Sie eine NSUserActivity-Verknüpfung, um eine App zu öffnen.
- Verwenden Sie eine benutzerdefinierte Absichtsverknüpfung, um eine Aufgabe auszuführen.
- Stellen Sie eine Benutzeroberfläche für eine benutzerdefinierte Absicht bereit.
- Erstellen Sie eine Sprachkombination.
Info.plist und Entitlements.plist
Bevor Sie sich tiefer in den Code des Suppenkochs eingraben, sehen Sie sich die Dateien "Info.plist" und "Entitlements.plist" an.
Info.plist
Die Datei "Info.plist " im Projekt "SoupChef " definiert den Bündelbezeichner als com.xamarin.SoupChef
. Dieser Bündelbezeichner wird als Präfix für die Bündelbezeichner der Intents- und Intents-UI-Erweiterungen verwendet, die weiter unten in diesem Dokument erläutert werden.
Die Datei Info.plist enthält auch den folgenden Eintrag:
<key>NSUserActivityTypes</key>
<array>
<string>OrderSoupIntent</string>
<string>com.xamarin.SoupChef.viewMenu</string>
</array>
Dieses NSUserActivityTypes
Schlüssel-Wert-Paar gibt an, dass Suppenkoch weiß, wie man mit einem ActivityType
OrderSoupIntent
NSUserActivity
"com.xamarin.SoupChef.viewMenu" umgeht.
Aktivitäten und benutzerdefinierte Absichten, die an die App selbst übergeben werden, im Gegensatz zu den Erweiterungen, werden in der AppDelegate
(eine UIApplicationDelegate
von der ContinueUserActivity
Methode) behandelt.
Entitlements.plist
Die Datei "Entitlements.plist " im Projekt "SoupChef " enthält die folgenden Einträge:
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.xamarin.SoupChef</string>
</array>
<key>com.apple.developer.siri</key>
<true/>
Diese Konfiguration gibt an, dass die App die App -Gruppe "group.com.xamarin.SoupChef" verwendet. Die App-Erweiterung "SoupChefIntents " verwendet dieselbe App-Gruppe, mit der die beiden Projekte gemeinsam verwendet werden können. NSUserDefaults
-Daten.
Der com.apple.developer.siri
Schlüssel gibt an, dass die App mit Siri interagiert.
Hinweis
Die Buildkonfiguration des SoupChef-Projekts legt benutzerdefinierte Berechtigungen auf "Entitlements.plist" fest.
Verwenden einer NSUserActivity-Verknüpfung zum Öffnen einer App
Um eine Verknüpfung zu erstellen, mit der eine App zum Anzeigen bestimmter Inhalte geöffnet wird, erstellen Sie eine NSUserActivity
App, und fügen Sie sie an den Ansichtscontroller für den Bildschirm an, den Sie öffnen möchten.
Einrichten einer NSUserActivity
Erstellt auf dem Menübildschirm SoupMenuViewController
eine NSUserActivity
Und weist sie der Eigenschaft des Ansichtscontrollers UserActivity
zu:
public override void ViewDidLoad()
{
base.ViewDidLoad();
UserActivity = NSUserActivityHelper.ViewMenuActivity;
}
Das Festlegen der UserActivity
Immobilie spendet die Aktivität an Siri. Von dieser Spende erhält Siri Informationen darüber, wann und wo diese Aktivität für den Benutzer relevant ist und lernt, es in Zukunft besser vorzuschlagen.
NSUserActivityHelper
ist eine Hilfsklasse, die in der SoupChef-Lösung enthalten ist, in der Klassenbibliothek "SoupKit ". Es erstellt eine NSUserActivity
und legt verschiedene Eigenschaften im Zusammenhang mit Siri und suche:
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;
}
}
Beachten Sie insbesondere die folgenden Features:
- Die Einstellung
EligibleForPrediction
zeigttrue
an, dass Siri diese Aktivität vorhersagen und als Verknüpfung anzeigen kann. - Das
ContentAttributeSet
Array ist ein StandardCSSearchableItemAttributeSet
, der verwendet wird, um eineNSUserActivity
in iOS-Suchergebnisse einzuschließen. SuggestedInvocationPhrase
ist ein Ausdruck, den Siri dem Benutzer als mögliche Wahl vorschlagen wird, wenn er einer Verknüpfung einen Ausdruck zuweist.
Behandeln einer NSUserActivity-Verknüpfung
Um eine NSUserActivity
verknüpfung zu behandeln, die von einem Benutzer aufgerufen wird, muss eine iOS-Anwendung NSUserActivity
die ContinueUserActivity
Methode der AppDelegate
Klasse überschreiben und basierend auf dem ActivityType
Feld des übergebenen Objekts reagieren:
public override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)
{
// ...
else if (userActivity.ActivityType == NSUserActivityHelper.ViewMenuActivityType)
{
HandleUserActivity();
return true;
}
// ...
}
Diese Methode ruft die HandleUserActivity
Segue auf dem Menübildschirm auf und ruft sie auf:
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);
}
Zuweisen eines Ausdrucks zu einer NSUserActivity
Um einer NSUserActivity
App einen Ausdruck zuzuweisen, öffnen Sie die iOS-Einstellungen-App, und wählen Sie Siri & Search > My Shortcuts aus. Wählen Sie dann die Verknüpfung (in diesem Fall "Mittagessen bestellen") aus, und notieren Sie einen Ausdruck.
Wenn Sie Siri aufrufen und diesen Ausdruck verwenden, wird der Suppenkoch auf dem Menübildschirm geöffnet.
Verwenden einer benutzerdefinierten Absichtsverknüpfung zum Ausführen einer Aufgabe
Definieren einer benutzerdefinierten Absicht
Um eine Verknüpfung bereitzustellen, mit der ein Benutzer schnell eine bestimmte Aufgabe im Zusammenhang mit Ihrer App ausführen kann, erstellen Sie eine benutzerdefinierte Absicht. Eine benutzerdefinierte Absicht stellt eine Aufgabe dar, die ein Benutzer möglicherweise abschließen möchte, Parameter, die für diese Aufgabe relevant sind, und potenzielle Antworten, die sich aus der Ausführung der Aufgabe ergeben. Je nachdem, wie eine benutzerdefinierte Absicht definiert ist, kann das Aufrufen der App entweder ihre App öffnen oder eine Hintergrundaufgabe ausführen.
Verwenden Sie Xcode 10, um benutzerdefinierte Absichten zu erstellen. Im Repository "SoupChef" wird der benutzerdefinierte Intent in OrderSoupIntentCodeGen definiert, einem Objective-C Projekt. Öffnen Sie dieses Projekt, und wählen Sie die Intents.intentdefinition-Datei im Project Navigator aus, um die OrderSoup-Absicht anzuzeigen.
Beachten Sie die folgenden Features:
- Die Absicht hat eine Kategorie der Bestellung. Es gibt verschiedene vordefinierte Kategorien, die für benutzerdefinierte Absichten verwendet werden können; wählen Sie die Aufgabe aus, die ihrer benutzerdefinierten Absicht am ehesten entspricht. Da es sich bei dieser Lösung um eine Suppenbestellungs-App handelt, verwendet OrderSoupIntent "Order".
- Das Bestätigungskontrollkästchen gibt an, ob Siri eine Bestätigung anfordern muss, bevor die Aufgabe ausgeführt wird. Für den Auftrag Suppenabsicht im Suppenkoch ist diese Option aktiviert, da der Benutzer einen Kauf vornimmt.
- Im Abschnitt "Parameters" der Intentdefinition-Datei werden die für eine Verknüpfung relevanten Parameter definiert. Um eine Suppenbestellung zu bestellen, muss der Suppenkoch die Art der Suppe, seine Menge und alle zugehörigen Optionen kennen. Jeder Parameter hat einen Typ; Parameter, der nicht durch einen vordefinierten Typ dargestellt werden kann, werden als benutzerdefiniert festgelegt.
- Die Benutzeroberfläche für Tastenkombinationen beschreibt die verschiedenen Parameterkombinationen, die Siri verwenden kann, wenn Sie Ihre Verknüpfung vorschlagen. Mit den zugehörigen Abschnitten "Titel " und "Untertitel " können Sie die Nachrichten definieren, die Siri beim Präsentieren einer vorgeschlagenen Verknüpfung für den Benutzer verwendet.
- Das Kontrollkästchen "Hintergrundausführung unterstützt" sollte für alle Tastenkombinationen aktiviert werden, die ausgeführt werden können, ohne die App für weitere Benutzerinteraktionen zu öffnen.
Definieren von benutzerdefinierten Absichtsantworten
Das unter der OrderSoup-Absicht geschachtelte Antwortelement stellt die potenziellen Antworten dar, die aus einer Suppenreihenfolge resultieren.
Beachten Sie in der Antwortdefinition der OrderSoup-Absicht die folgenden Features:
- Die Eigenschaften einer Antwort können verwendet werden, um die nachricht anzupassen, die dem Benutzer mitgeteilt wurde. Die OrderSoup-Absichtsantwort verfügt über Suppen - und WaitTime-Eigenschaften .
- Die Antwortvorlagen geben die verschiedenen Erfolgs- und Fehlermeldungen an, die verwendet werden können, um den Status anzuzeigen, nachdem die Aufgabe einer Absicht abgeschlossen wurde.
- Das Kontrollkästchen "Erfolg " sollte für Antworten aktiviert werden, die den Erfolg angeben.
- Die Erfolgsantwort orderSoupIntent verwendet die Suppen - und WaitTime-Eigenschaften , um eine freundliche und nützliche Nachricht bereitzustellen, die beschreibt, wann die Suppenbestellung bereit ist.
Generieren von Code für die benutzerdefinierte Absicht
Durch das Erstellen des Xcode-Projekts, das diese benutzerdefinierte Absichtsdefinition enthält, generiert Xcode Code, der für die programmgesteuerte Interaktion mit der benutzerdefinierten Absicht und den zugehörigen Antworten verwendet werden kann.
So zeigen Sie diesen generierten Code an:
- Öffnen Sie AppDelegate.m.
- Fügen Sie einen Import zur Headerdatei der benutzerdefinierten Absicht hinzu:
#import "OrderSoupIntent.h"
- Fügen Sie in einer beliebigen Methode der Klasse einen Verweis auf
OrderSoupIntent
. - Klicken Sie mit der rechten Maustaste,
OrderSoupIntent
und wählen Sie "Zur Definition springen" aus. - Klicken Sie mit der rechten Maustaste in die neu geöffnete Datei " OrderSoupIntent.h", und wählen Sie " In Finder anzeigen" aus.
- Diese Aktion öffnet ein Finder-Fenster, das eine H- und M-Datei enthält, die den generierten Code enthält.
Dieser generierte Code umfasst:
OrderSoupIntent
– Eine Klasse, die die benutzerdefinierte Absicht darstellt.OrderSoupIntentHandling
– Ein Protokoll, das die Methoden definiert, die verwendet werden, um zu bestätigen, dass die Absicht ausgeführt werden soll, und die Methode, die sie tatsächlich ausführt.OrderSoupIntentResponseCode
– Eine Enumeration, die verschiedene Antwortstatus definiert.OrderSoupIntentResponse
– eine Klasse, die die Antwort auf die Ausführung einer Absicht darstellt.
Erstellen einer Bindung an die benutzerdefinierte Absicht
Um den von Xcode generierten Code in einer Xamarin.iOS-App zu verwenden, erstellen Sie eine C#-Bindung dafür.
Erstellen einer statischen Bibliothek und C#-Bindungsdefinitionen
Sehen Sie sich im Repository "SoupChef" den Ordner "OrderSoupIntentStaticLib " an, und öffnen Sie das Projekt "OrderSoupIntentStaticLib.xcodeproj Xcode".
Dieses Cocoa Touch Static Library-Projekt enthält die Dateien OrderSoupIntent.h und OrderSoupIntent.m, die von Xcode generiert werden.
Konfigurieren der Buildeinstellungen für statische Bibliotheken
Wählen Sie im Xcode-Projektnavigator das Projekt der obersten Ebene, OrderSoupIntentStaticLib, aus, und navigieren Sie zu Buildphasen kompilierungsquellen>. Beachten Sie, dass OrderSoupIntent.m (der OrderSoupIntent.h importiert) hier aufgeführt ist. Beachten Sie in "Binärdatei mit Bibliotheken verknüpfen", dass Intents.framework und Foundation.framework enthalten sind. Mit diesen Einstellungen wird das Framework ordnungsgemäß erstellt.
Erstellen der statischen Bibliothek und Generieren von C#-Bindungendefinitionen
Führen Sie die folgenden Schritte aus, um die statische Bibliothek zu erstellen und C#-Bindungen zu generieren:
Installieren Sie Objective Sharpie, das Tool verwendet, um Bindungen aus den von Xcode erstellten H - und M-Dateien zu generieren.
Konfigurieren Sie Ihr System so, dass Xcode 10-Befehlszeilentools verwendet werden:
Warnung
Das Aktualisieren der ausgewählten Befehlszeilentools wirkt sich auf alle installierten Versionen von Xcode auf Ihrem System aus. Wenn Sie die Beispiel-App "Soup Chef" verwendet haben, müssen Sie diese Einstellung unbedingt auf die ursprüngliche Konfiguration rückgängig machen.
- Wählen Sie in Xcode die Option "Xcode-Einstellungsspeicherorte >>" aus, und legen Sie die Befehlszeilentools auf die neueste Xcode 10-Installation fest, die auf Ihrem System verfügbar ist.
Im Terminal
cd
, zum Verzeichnis OrderSoupIntentStaticLib .Typ
make
, der erstellt:- Die statische Bibliothek libOrderSoupIntentStaticLib.a
- Im Bo-Ausgabeverzeichnis binden C#-Bindungen:
- ApiDefinitions.cs
- StructsAndEnums.cs
Das Projekt OrderSoupIntentBindings , das auf dieser statischen Bibliothek und den zugehörigen Bindungen basiert, erstellt diese Elemente automatisch. Die manuelle Ausführung durch den obigen Prozess stellt jedoch sicher, dass er wie erwartet erstellt wird.
Weitere Informationen zum Erstellen einer statischen Bibliothek und zum Erstellen von C#-Bindungen mit Objective Sharpie finden Sie in der exemplarischen Vorgehensweise zum Binden einer iOS-BibliothekObjective-C.
Erstellen einer Bindungsbibliothek
Nachdem die statische Bibliothek und die C#-Bindungen erstellt wurden, ist das re Standard ing-Element, das zum Verwenden des Xcode-generierten intent-bezogenen Codes in einem Xamarin.iOS-Projekt erforderlich ist, eine Bindungsbibliothek.
Öffnen Sie im Repository "Suppenkoch" die SoupChef.sln Datei. Diese Lösung enthält unter anderem "OrderSoupIntentBinding", eine Bindungensbibliothek für die zuvor generierte statische Bibliothek.
Beachten Sie insbesondere, dass dieses Projekt Folgendes umfasst:
ApiDefinitions.cs – Eine Datei, die zuvor von Objective Sharpie generiert und diesem Projekt hinzugefügt wurde. Die Buildaktion dieser Datei ist auf "ObjcBindingApiDefinition" festgelegt.
StructsAndEnums.cs – Eine andere Datei, die zuvor von Objective Sharpie generiert und diesem Projekt hinzugefügt wurde. Die Buildaktion dieser Datei ist auf ObjcBindingCoreSource festgelegt.
Ein nativer Verweis auflibOrderSoupIntentStaticLib.a, die statische Bibliothek, die zuvor erstellt wurde. Aktualisieren Sie die systemeigenen Referenzeigenschaften, und geben Sie die folgenden Werte an:
- Frameworks =
Foundation Intents
- Smart Link =
On
- Last erzwingen =
On
- Art =
Static
- Frameworks =
Hinweis
Sowohl ApiDefinitions.csals auch StructsAndEnums.cs enthalten Attribute wie [Watch (5,0), iOS (12,0)]
. Diese Attribute, die von Objective Sharpie generiert werden, wurden auskommentiert, da sie für dieses Projekt nicht erforderlich sind.
Weitere Informationen zum Erstellen einer C#-Bindungsbibliothek finden Sie in der exemplarischen Vorgehensweise zum Binden einer iOS-BibliothekObjective-C.
Beachten Sie, dass das SoupChef-Projekt einen Verweis auf OrderSoupIntentBinding enthält, was bedeutet, dass es jetzt in C# auf die Klassen, Schnittstellen und Enumerationen zugreifen kann, die es enthält:
OrderSoupIntent
OrderSoupIntentHandling
OrderSoupIntentResponse
OrderSoupIntenseResponseCode
Erstellen eines Swift-Frameworks
Der systemeigene Absichtsdefinitionscode wird standardmäßig mithilfe der Sprache Ihres nativen Projekts von Xcode generiert. Wenn Sie die Intents.intentdefinition-Datei in einem Swift-Projekt definieren, generiert Xcode Eine einzelne Swift-Datei mit allen erforderlichen Klassen, die Sie zum Erstellen eines Swift-Frameworks verwenden können.
Tipp
Sie können eine gewünschte Sprache für den generierten Absichtscode in den Xcode-Buildeinstellungen auswählen. Wechseln Sie zum Zielbuild > Einstellungen > Intent Definition Compiler – Codegenerierung, und wählen Sie entweder Swift oder Objective-C. Sie können die Zielsprache auch automatisch anpassen.
Der Prozess der Erstellung eines Swift-Frameworks ähnelt dem zuvor beschriebenen:
- Erstellen Sie ein neues Swift-Framework-Projekt.
- Kopieren Sie die automatisch generierte Swift-Datei mit Absichtscode in dieses Projekt, sie finden Sie wie hier beschrieben.
- Aktivieren Sie den ÜberbrückungsheaderObjective-C, sodass das Framework automatisch mit der erforderlichen Objective-C Sharpie-Headerdatei generiert wird.
Nachdem das Framework erstellt wurde, führen Sie die gleichen Schritte aus, die weiter oben beschrieben wurden, um eine Xamarin-Bindung zu erstellen. Weitere Informationen zum Erstellen einer Bindung für ein Swift-Framework finden Sie hier.
Hinzufügen der Absichtsdefinitionsdatei zu Ihrer Lösung
In der C# -SoupChef-Lösung enthält das SoupKit-Projekt Code, der zwischen der App und den Erweiterungen gemeinsam genutzt wird. Die Intents.intentdefinition-Datei wurde im Base.lproj-Verzeichnis von SoupKit platziert und verfügt über eine Buildaktion von Inhalt. Der Buildvorgang kopiert diese Datei in das Suppe Chef-App-Bündel, wo es erforderlich ist, dass die App ordnungsgemäß funktioniert.
Donating an intent
Damit Siri eine Verknüpfung vorschlagen kann, muss sie zuerst verstehen, wann die Verknüpfung relevant ist.
Um Siri dieses Verständnis zu geben, spendet Suppenkoch jedes Mal, wenn der Benutzer eine Suppenbestellung an Siri spendet. Basierend auf dieser Spende – als sie gespendet wurde, wo sie gespendet wurde, lernt Siri, wann die Verknüpfung in der Zukunft vorgeschlagen werden soll.
SuppeChef nutzt die SoupOrderDataManager
Klasse, um Spenden zu tätigen.
Wenn aufgerufen wird, eine Suppenbestellung für einen Benutzer zu platzieren, ruft die PlaceOrder
Methode wiederum auf DonateInteraction
:
void DonateInteraction(Order order)
{
var interaction = new INInteraction(order.Intent, null);
interaction.Identifier = order.Identifier.ToString();
interaction.DonateInteraction((error) =>
{
// ...
});
}
Nach dem Abrufen einer Absicht wird sie in eine INInteraction
umschlossen.
Dies INInteraction
ist ein Identifier
die mit der eindeutigen ID der Bestellung übereinstimmt (es ist später hilfreich, wenn Absichtsspenden gelöscht werden, die nicht mehr gültig sind). Dann wird die Interaktion an Siri gespendet.
Der Aufruf an den order.Intent
Getter ruft eine, OrderSoupIntent
die die Reihenfolge darstellt, indem sie deren Quantity
, Soup
, Options
und Bild und einen Aufrufausdruck festlegen, der als Vorschlag verwendet werden soll, wenn der Benutzer einen Ausdruck für Siri aufzeichnet, der dem Zweck zugeordnet werden soll:
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;
}
}
Entfernen ungültiger Spenden
Es ist wichtig, Spenden zu entfernen, die nicht mehr gültig sind, damit Siri keine hilfreichen oder verwirrenden Verknüpfungsvorschläge macht.
Im Suppenkoch kann der Bildschirm "Menü konfigurieren" verwendet werden, um ein Menüelement als nicht verfügbar zu markieren. Siri sollte keine Verknüpfung mehr vorschlagen, um das nicht verfügbare Menüelement zu bestellen, daher löscht die RemoveDonation
Methode SoupMenuManager
spenden für Menüelemente, die nicht mehr verfügbar sind. Die App implementiert diese Funktionalität durch:
- Suchen nach Bestellungen, die dem jetzt nicht verfügbaren Menüelement zugeordnet sind.
- Greifen Sie auf ihre Bezeichner zu.
- Löschen von Interaktionen mit denselben Bezeichnern.
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");
}
});
}
}
Überprüfen erfolgreicher Spenden
Die Lösung umfasst mehrere Projekte und eine bestimmte Konfiguration. In einigen Fällen kann die Anwendung aufgrund einer unvollständigen Konfiguration abstürzen, in anderen Fällen kann es im Hintergrund fehlschlagen, eine Interaktion zu spenden. Es ist wichtig, erfolgreiche Spenden und iOS-Entwicklereinstellungen zu überprüfen. Navigieren Sie zu Einstellungen > Entwickler, und aktivieren Sie die folgenden Entwickleroptionen, um aktuelle Spenden und Verknüpfungen anzuzeigen:
- Zuletzt verwendete Tastenkombinationen anzeigen
- Spenden auf dem Sperrbildschirm anzeigen
Nach der Aktivierung wird jede erfolgreiche Spende auf dem Sperrbildschirm und unterhalb der Siri-Vorschläge-Optionen angezeigt. Wenn nach dem Ausführen Ihrer Anwendung dort keine Spenden angezeigt werden, lesen Sie die folgenden Problembehandlungsfälle:
Eine App kann den
OrderSoupIntent
folgenden Fehler nicht erstellen:Eine systemeigene Instanz des Typs "NativeLibrary.OrderSoupIntent" konnte nicht erstellt werden: Die systemeigene Klasse wurde nicht geladen.
Dieser Fehler bedeutet, dass Xamarin die systemeigene Klasse nicht über die Xamarin-Bindung laden kann. Um dies zu beheben, stellen Sie sicher, dass die systemeigene Bibliothek den erforderlichen Code enthält, auf den vom Bindungsprojekt verwiesen wird, und die richtigen Flags werden festgelegt, wie hier beschrieben, die
Force Load
Kennzeichnung aufOn
.Eine App initialisiert die geladene systemeigene Instanz der Intent-Klasse nicht mit dem folgenden Fehler:
Eine Instanz des Typs "NativeLibrary.OrderSoupIntent" konnte nicht initialisiert werden: Die systemeigene "init"-Methode hat nil zurückgegeben.
Das Problem bezieht sich auf die fehlende Intent-Definitionsdatei. Die Xamarin-App sollte die ursprüngliche Intent-Definitionsdatei mit dem
Content
Typ enthalten, wie hier beschrieben.Eine App erstellt die Absicht und ruft die Spendenmethode ohne Absturz auf, aber die Konsolenausgabe zeigt eine Warnung zu unbekanntem Absichtstyp an, und es wird keine Spende getätigt:
Interaktion mit OrderSoupIntent, die keine gültigen Tastenkombinationstypen enthält, kann nicht gespendet werden.
Um das Problem zu beheben, muss die Absicht in der plist ordnungsgemäß definiert sein, Siri-Berechtigung muss für die aktuelle Buildkonfiguration über Projekteinstellungen aktiviert und ausgewählt werden.
Die Info.plist der App:
<key>NSUserActivityTypes</key> <array> <string>ScheduleMeetingIntent</string> </array>
Die Berechtigungsliste der App mit der Siri-Funktion:
<key>com.apple.developer.siri</key> <true/>
Benutzerdefinierte Berechtigungen sollten für die zielorientierte Buildkonfiguration ausgewählt werden. Wechseln Sie zu project settings > Build > iOS Bundle Signing, und legen Sie benutzerdefinierte Berechtigungen auf die Datei "Entitlements.plist" fest, die die erforderlichen Berechtigungen enthält.
Erstellen einer Intents-Erweiterung
Der Code, der ausgeführt wird, wenn Siri eine Absicht aufruft, wird in eine Intents-Erweiterung eingefügt, die als neues Projekt zur gleichen Lösung wie eine vorhandene Xamarin.iOS-App wie Soup Chef hinzugefügt werden kann. In der SuppeChef Lösung heißt die Erweiterung " SoupChefIntents".
SoupChefIntents – Info.plist und Entitlements.plist
SoupChefIntents – Info.plist
Die Info.plist im Projekt "SoupChefIntents " definiert den Bündelbezeichner als com.xamarin.SoupChef.SoupChefIntents
.
Die Datei Info.plist enthält auch den folgenden Eintrag:
<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>
In der obigen Info.plist:
IntentsRestrictedWhileLocked
listet absichten auf, die behandelt werden sollen, wenn das Gerät entsperrt ist.IntentsSupported
listet die Absichten auf, die von dieser Erweiterung behandelt werden.NSExtensionPointIdentifier
Gibt den Typ der App-Erweiterung an. Weitere Informationen finden Sie in der Apple-Dokumentation.NSExtensionPrincipalClass
Gibt die Klasse an, die zum Behandeln von Absichten verwendet werden soll, die von dieser Erweiterung unterstützt werden.
SoupChefIntents – Entitlements.plist
Die "Entitlements.plist " im Projekt "SoupChefIntents " verfügt über die App-Gruppenfunktion . Diese Funktion ist so konfiguriert, dass dieselbe App-Gruppe wie das SoupChef-Projekt verwendet wird:
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.xamarin.SoupChef</string>
</array>
Suppenkoch speichert Daten mit NSUserDefaults
. Um Daten zwischen der App und der App-Erweiterung freizugeben, verweisen sie in den Dateien "Entitlements.plist " auf dieselbe App-Gruppe.
Hinweis
Die Buildkonfiguration des Projekts "SoupChefIntents" legt benutzerdefinierte Berechtigungen auf "Entitlements.plist" fest.
Behandeln einer OrderSoupIntent-Hintergrundaufgabe
Eine Intents-Erweiterung führt die erforderlichen Hintergrundaufgaben für eine Verknüpfung basierend auf einer benutzerdefinierten Absicht aus.
Siri ruft die GetHandler
Methode der IntentHandler
Klasse (definiert in Info.plist als die NSExtensionPrincipalClass
) auf, um eine Instanz einer Klasse abzurufen, die erweitert OrderSoupIntentHandling
wird, die verwendet werden kann, um eine 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
, definiert im SoupKit-Projekt des freigegebenen Codes, implementiert zwei wichtige Methoden:
ConfirmOrderSoup
– Bestätigt, ob die mit der Absicht verknüpfte Aufgabe tatsächlich ausgeführt werden soll.HandleOrderSoup
– Platziert die Suppenreihenfolge und reagiert auf den Benutzer, indem er den passed-in-Abschlusshandler aufruft
Behandeln einer OrderSoupIntent, die die App öffnet
Eine App muss Absichten, die nicht im Hintergrund ausgeführt werden, ordnungsgemäß verarbeiten.
Diese Absichten werden auf die gleiche Weise wie NSUserActivity
Tastenkombinationen in der ContinueUserActivity
Methode von AppDelegate
:
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;
}
// ...
}
Bereitstellen einer Benutzeroberfläche für eine benutzerdefinierte Absicht
Eine Intents-UI-Erweiterung stellt eine benutzerdefinierte Benutzeroberfläche für eine Intents-Erweiterung bereit. In der SoupChef-Lösung ist SoupChefIntentsUI eine Intents UI-Erweiterung, die eine Schnittstelle für SoupChefIntents bereitstellt.
SoupChefIntentsUI – Info.plist und Entitlements.plist
SoupChefIntentsUI – Info.plist
Die Info.plist im SoupChefIntentsUI-Projekt definiert den Bundle Identifier als com.xamarin.SoupChef.SoupChefIntentsui
.
Die Datei Info.plist enthält auch den folgenden Eintrag:
<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>
In der obigen Info.plist:
IntentsSupported
gibt an, dass diesOrderSoupIntent
von dieser Intents-UI-Erweiterung behandelt wird.NSExtensionPointIdentifier
Gibt den Typ der App-Erweiterung an. Weitere Informationen finden Sie in der Apple-Dokumentation.NSExtensionMainStoryboard
Gibt das Storyboard an, das die primäre Schnittstelle dieser Erweiterung definiert.
SoupChefIntentsUI – Entitlements.plist
Das Projekt "SoupChefIntentsUI " benötigt keine Datei "Entitlements.plist ".
Erstellen der Benutzeroberfläche
Da die Info.plist für SoupChefIntentsUI den NSExtensionMainStoryboard
Schlüssel festlegt MainInterface
, definiert die Datei "MainInterace.storyboard " die Schnittstelle für die Intents UI-Erweiterung.
In diesem Storyboard gibt es einen einzelnen Ansichtscontroller vom Typ IntentViewController. Es verweist auf zwei Ansichten:
- invoiceView, vom Typ
InvoiceView
- confirmationView, vom Typ
ConfirmOrderView
Hinweis
Die Schnittstellen für invoiceView und confirmationView werden in "Main.storyboard " als sekundäre Ansichten definiert. Visual Studio für Mac und Visual Studio 2017 bieten keine Unterstützung für das Anzeigen oder Bearbeiten sekundärer Ansichten; öffnen Sie dies.Main.storyboard im Schnittstellen-Generator von Xcode.
IntentViewController
implementiert die IINUIHostedViewControlling
Schnittstelle, die verwendet wird, um eine benutzerdefinierte Schnittstelle beim Arbeiten mit Siri Intents bereitzustellen. Der ConfigureView
die Methode wird aufgerufen, um die Schnittstelle anzupassen, die Bestätigung oder die Rechnung anzuzeigen, je nachdem, ob die Interaktion bestätigt (INIntentHandlingStatus.Ready
) oder erfolgreich ausgeführt wurde (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);
}
Tipp
Weitere Informationen zu der Methode finden Sie in der ConfigureView
WwDC 2017-Präsentation von Apple, What's New in SiriKit.
Erstellen einer Sprachkombination
Suppenkoch bietet eine Schnittstelle, um jeder Bestellung eine Sprachkombination zuzuweisen, sodass es möglich ist, Suppe mit Siri zu bestellen. Tatsächlich wird die Schnittstelle zum Aufzeichnen und Zuweisen von Sprachverknüpfungen von iOS bereitgestellt und erfordert wenig benutzerdefinierten Code.
Wenn OrderDetailViewController
ein Benutzer auf die Zeile "Zur Siri hinzufügen" der Tabelle tippt, zeigt die RowSelected
Methode einen Bildschirm an, um eine Sprachkombination hinzuzufügen oder zu bearbeiten:
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);
}
}
}
}
Basierend darauf, ob für die aktuell angezeigte Reihenfolge eine vorhandene Sprachkombination vorhanden ist, RowSelected
wird ein Ansichtscontroller vom Typ INUIEditVoiceShortcutViewController
oder INUIAddVoiceShortcutViewController
.
Legt sich in jedem Fall OrderDetailViewController
als Ansichtscontroller Delegate
fest, weshalb er auch implementiert IINUIAddVoiceShortcutViewControllerDelegate
und IINUIEditVoiceShortcutViewControllerDelegate
.
Testen auf dem Gerät
Um Suppenkoch auf einem Gerät auszuführen, folgen Sie den Anweisungen in diesem Abschnitt. Lesen Sie auch die Notiz zur automatischen Bereitstellung.
App-Gruppe, App-IDs, Bereitstellungsprofile
Führen Sie im Abschnitt "Zertifikate, IDs & Profile " des Apple Developer Portals die folgenden Schritte aus:
Erstellen Sie eine App-Gruppe, um Daten zwischen der Soup Chef-App und ihren Erweiterungen zu teilen. Beispiel: group.com.yourcompanyname.SoupChef
Erstellen Sie drei App-IDs: eine für die App selbst, eine für die Intents-Erweiterung und eine für die Intents-UI-Erweiterung. Zum Beispiel:
App: com.yourcompanyname.SoupChef
- Weisen Sie dieser App-ID die Funktionen SiriKit und App-Gruppen zu.
Intents-Erweiterung: com.yourcompanyname.SoupChef.Intents
- Weisen Sie dieser App-ID die App-Gruppenfunktion zu.
Intents UI-Erweiterung: com.yourcompanyname.SoupChef.Intentsui
- Diese App-ID benötigt keine speziellen Funktionen.
Nachdem Sie die obigen App-IDs erstellt haben, bearbeiten Sie die App-Gruppenfunktion , die der App und der Intents-Erweiterung zugewiesen ist, und geben Sie die zuvor erstellte bestimmte App-Gruppe an.
Erstellen Sie drei neue Entwicklungsbereitstellungsprofile, eines für jede der neuen App-IDs.
Laden Sie diese Bereitstellungsprofile herunter, und doppelklicken Sie auf die einzelnen Profile, um sie zu installieren. Wenn Visual Studio für Mac oder Visual Studio 2017 bereits ausgeführt wird, starten Sie es neu, um sicherzustellen, dass die neuen Bereitstellungsprofile registriert werden.
Bearbeiten von Info.plist, Entitlements.plist und Quellcode
Führen Sie in Visual Studio für Mac oder Visual Studio 2017 die folgenden Schritte aus:
Aktualisieren Sie die verschiedenen Info.plist-Dateien in der Lösung. Legen Sie die App, die Intents-Erweiterung und den Intents UI-Erweiterungsbundle-Bezeichner auf die zuvor definierten App-IDs fest:
- App: com.yourcompanyname.SoupChef
- Intents Extension: com.yourcompanyname.SoupChef.Intents
- Intents UI-Erweiterung: com.yourcompanyname.SoupChef.Intentsui
Aktualisieren Sie die Datei "Entitlements.plist " für das Projekt "SoupChef ":
- Legen Sie für die App-Gruppenfunktion die Gruppe auf die zuvor erstellte neue App-Gruppe fest (im obigen Beispiel war sie group.com.yourcompanyname.SoupChef).
- Stellen Sie sicher, dass SiriKit aktiviert ist.
Aktualisieren Sie die Datei "Entitlements.plist " für das Projekt "SoupChefIntents ":
- Legen Sie für die App-Gruppenfunktion die Gruppe auf die zuvor erstellte neue App-Gruppe fest (im obigen Beispiel war sie group.com.yourcompanyname.SoupChef).
Öffnen Sie schließlich NSUserDefaultsHelper.cs. Legen Sie die
AppGroup
Variable auf den Wert Ihrer neuen App-Gruppe fest (z. B. aufgroup.com.yourcompanyname.SoupChef
).
Konfigurieren der Buildeinstellungen
In Visual Studio für Mac oder Visual Studio 2017:
Öffnen Sie die Optionen/Eigenschaften für das SoupChef-Projekt . Legen Sie auf der Registerkarte "Signierung des iOS-Bündels" die Signaturidentität auf das neue app-spezifische Bereitstellungsprofil fest, das Sie zuvor erstellt haben.
Öffnen Sie die Optionen/Eigenschaften für das Projekt "SoupChefIntents ". Legen Sie auf der Registerkarte "Signierung des iOS-Bündels" die Signaturidentität auf das zuvor erstellte neue Erweiterungserweiterungsprofil fest.
Öffnen Sie die Optionen/Eigenschaften für das Projekt "SoupChefIntentsUI ". Legen Sie auf der Registerkarte "Signierung des iOS-Bündels" die Signaturidentität auf das zuvor erstellte neue Erweiterungsprofil für die Intents-BEnutzeroberfläche fest.
Mit diesen Änderungen wird die App auf einem iOS-Gerät ausgeführt.
Automatische Bereitstellung
Sie können die automatische Bereitstellung verwenden, um viele dieser Bereitstellungsaufgaben direkt in der IDE auszuführen. Die automatische Bereitstellung richtet jedoch keine App-Gruppen ein. Sie müssen die Dateien "Entitlements.plist " manuell mit dem Namen der App-Gruppe konfigurieren, die Sie verwenden möchten, das Apple Developer Portal besuchen, um die App-Gruppe zu erstellen, diese App-Gruppe jeder App-ID zuzuweisen, die durch die automatische Bereitstellung erstellt wurde, die Bereitstellungsprofile (App, Intents Extension, Intents UI-Erweiterung) neu zu erstellen, um die neu erstellte App-Gruppe einzuschließen, und laden Sie sie herunter, und installieren Sie sie.