Übergabe in Xamarin.iOS
In diesem Artikel wird die Arbeit mit Handoff in einer Xamarin.iOS-App behandelt, um Benutzeraktivitäten zwischen Apps zu übertragen, die auf den anderen Geräten des Benutzers ausgeführt werden.
Apple hat Handoff in iOS 8 und OS X Yosemite (10.10) eingeführt, um einen gemeinsamen Mechanismus zu schaffen, mit dem der Benutzer*innen Aktivitäten, die sie auf einem ihrer Geräte begonnen haben, auf ein anderes Gerät übertragen können, auf dem die gleiche App oder eine andere App läuft, die dieselbe Aktivität unterstützt.
In diesem Artikel wird die Aktivierung der Aktivitätsfreigabe in einer Xamarin.iOS-App schnell erläutert und das Handoff-Framework ausführlich behandelt:
Informationen zur Übergabe
Handoff (auch bekannt als Kontinuität) wurde von Apple in iOS 8 und OS X Yosemite (10.10) eingeführt, damit Benutzer*innen eine Aktivität auf einem ihrer Geräte (entweder iOS oder Mac) starten und diese Aktivität auf einem anderen ihrer Geräte (wie durch das iCloud-Konto der Benutzer*innen identifiziert) fortsetzen können.
Handoff wurde in iOS 9 erweitert, um auch neue, erweiterte Suchfunktionen zu unterstützen. Weitere Informationen finden Sie in unserer Dokumentation zu Suchverbesserungen.
Beispielsweise kann der Benutzer eine E-Mail auf dem i Telefon starten und die E-Mail auf dem Mac nahtlos fortsetzen, wobei alle gleichen Nachrichteninformationen ausgefüllt sind und sich der Cursor an derselben Stelle befindet, an der sie in iOS verbleibt.
Jede Ihrer Apps, die dieselbe Team-ID gemeinsam nutzen, ist berechtigt, die Benutzeraktivitäten über Apps hinweg fortzusetzen, solange diese App entweder über den iTunes App Store übermittelt oder von einem registrierten Entwickler (für Mac- oder Enterprise- oder Ad-Hoc-Apps) signiert wurde.
Alle NSDocument
oder UIDocument
basierte Apps verfügen automatisch über integrierte Handoff-Unterstützung und erfordern minimale Änderungen zur Unterstützung von Handoff.
Fortsetzen von Benutzeraktivitäten
Die NSUserActivity
Klasse (zusammen mit einigen kleinen Änderungen UIKit
an und AppKit
) bietet Unterstützung für die Definition der Benutzeraktivität, die möglicherweise auf einem anderen Gerät des Benutzers fortgesetzt werden kann.
Damit eine Aktivität an eine andere der Geräte des Benutzers übergeben werden kann, muss sie in einer Instanz NSUserActivity
gekapselt werden, die als "Aktuelle Aktivität" gekennzeichnet ist, die Nutzlast festgelegt ist (die Zum Ausführen der Fortsetzung verwendeten Daten), und die Aktivität muss dann an dieses Gerät übertragen werden.
Handoff übergibt das minimale Minimum an Informationen, um die Aktivität zu definieren, die fortgesetzt werden soll, wobei größere Datenpakete über iCloud synchronisiert werden.
Auf dem empfangenden Gerät erhält der Benutzer eine Benachrichtigung, dass eine Aktivität für die Fortsetzung verfügbar ist. Wenn der Benutzer die Aktivität auf dem neuen Gerät fortsetzen möchte, wird die angegebene App gestartet (sofern noch nicht ausgeführt), und die Nutzlast wird NSUserActivity
verwendet, um die Aktivität neu zu starten.
Nur Apps, die dieselbe Entwicklerteam-ID gemeinsam nutzen und auf einen bestimmten Aktivitätstyp reagieren, sind für die Fortsetzung berechtigt. Eine App definiert die Aktivitätstypen, die sie unter dem NSUserActivityTypes
Schlüssel der Info.plist-Datei unterstützt. In diesem Fall wählt ein fortlaufendes Gerät die App aus, um die Fortsetzung basierend auf der Team-ID, dem Aktivitätstyp und optional dem Aktivitätstitel auszuführen.
Die empfangende App verwendet Informationen aus dem NSUserActivity
UserInfo
Wörterbuch, um die Benutzeroberfläche zu konfigurieren und den Status der angegebenen Aktivität wiederherzustellen, sodass der Übergang für den Endbenutzer nahtlos erscheint.
Wenn für die Fortsetzung mehr Informationen erforderlich sind, als effizient über eine NSUserActivity
App gesendet werden können, kann die fortgesetzte App einen Aufruf an die Ursprungs-App senden und einen oder mehrere Datenströme einrichten, um die erforderlichen Daten zu übertragen. Wenn die Aktivität z. B. ein großes Textdokument mit mehreren Bildern bearbeitet hat, wäre streaming erforderlich, um die erforderlichen Informationen zu übertragen, um die Aktivität auf dem empfangenden Gerät fortzusetzen. Weitere Informationen finden Sie im Abschnitt "Unterstützende Fortsetzungsstreams " weiter unten.
Wie oben erwähnt, NSDocument
oder UIDocument
basierende Apps verfügen automatisch über integrierte Handoff-Unterstützung. Weitere Informationen finden Sie im Abschnitt "Unterstützende Übergabe in dokumentbasierten Apps " weiter unten.
Die NSUserActivity-Klasse
Die NSUserActivity
Klasse ist das primäre Objekt in einem Handoff-Austausch und wird verwendet, um den Status einer Benutzeraktivität zu kapseln, die für die Fortsetzung verfügbar ist. Eine App instanziiert eine Kopie aller NSUserActivity
unterstützten Aktivitäten und möchte auf einem anderen Gerät fortfahren. Beispielsweise würde der Dokument-Editor eine Aktivität für jedes derzeit geöffnete Dokument erstellen. Es ist jedoch nur das oberste Dokument (im vordersten Fenster oder tab) die aktuelle Aktivität und steht für die Fortsetzung zur Verfügung.
Eine Instanz von NSUserActivity
wird sowohl durch ihre eigenschaften Title
als auch durch sie ActivityType
identifiziert. Die UserInfo
Wörterbucheigenschaft wird verwendet, um Informationen zum Status der Aktivität zu übertragen. Legen Sie die NeedsSave
Eigenschaft auf true
fest, wenn Sie die Statusinformationen über die NSUserActivity
Stellvertretung laden möchten. Verwenden Sie die AddUserInfoEntries
Methode, um neue Daten aus anderen Clients nach Bedarf in das UserInfo
Wörterbuch zusammenzuführen, um den Status der Aktivität beizubehalten.
Die NSUserActivityDelegate-Klasse
Dies NSUserActivityDelegate
wird verwendet, um Informationen in einem NSUserActivity
Wörterbuch UserInfo
auf dem neuesten Stand zu halten und mit dem aktuellen Status der Aktivität zu synchronisieren. Wenn das System die Informationen in der Aktivität aktualisiert werden muss (z. B. vor der Fortsetzung auf einem anderen Gerät), ruft es die UserActivityWillSave
Methode des Delegaten auf.
Sie müssen die UserActivityWillSave
Methode implementieren und änderungen an den NSUserActivity
Änderungen vornehmen (z UserInfo
. B. , Title
usw.), um sicherzustellen, dass sie weiterhin den Status der aktuellen Aktivität widerspiegelt. Wenn das System die UserActivityWillSave
Methode aufruft, wird das NeedsSave
Flag gelöscht. Wenn Sie eine der Dateneigenschaften der Aktivität ändern, müssen Sie sie erneut festlegen NeedsSave
true
.
Statt die UserActivityWillSave
oben dargestellte Methode zu verwenden, können Sie optional die Benutzeraktivität automatisch verwenden UIKit
oder AppKit
verwalten. Legen Sie dazu die Eigenschaft des Responderobjekts UserActivity
fest, und implementieren Sie die UpdateUserActivityState
Methode. Weitere Informationen finden Sie im Abschnitt "Unterstützende Übergabe in Responders".
App-Framework-Unterstützung
Sowohl (iOS) als AppKit
auch UIKit
(OS X) bieten integrierte Unterstützung für Handoff in den NSDocument
Klassen , Responder (UIResponder
/NSResponder
) und AppDelegate
Klassen. Während jedes Betriebssystem Handoff etwas anders implementiert, sind der grundlegende Mechanismus und die APIs identisch.
Benutzeraktivitäten in dokumentbasierten Apps
Dokumentbasierte iOS- und OS X-Apps verfügen automatisch über integrierte Handoff-Unterstützung. Um diese Unterstützung zu aktivieren, müssen Sie für jeden Eintrag in der Datei "Info.plist" der App einen NSUbiquitousDocumentUserActivityType
Schlüssel und einen CFBundleDocumentTypes
Wert hinzufügen.
Wenn dieser Schlüssel vorhanden ist, erstellen NSUserActivity
Sie sowohl Instanzen NSDocument
UIDocument
für iCloud-basierte Dokumente des angegebenen Typs als auch automatisch. Sie müssen einen Aktivitätstyp für jeden Dokumenttyp bereitstellen, den die App unterstützt, und mehrere Dokumenttypen können denselben Aktivitätstyp verwenden. UIDocument
Sowohl die Eigenschaft als auch NSDocument
die UserInfo
Eigenschaft automatisch mit dem NSUserActivity
Wert ihrer FileURL
Eigenschaft auffüllen.
Unter OS X wird die NSUserActivity
verwaltete AppKit
und den Antwortenden zugeordnete Aktivität automatisch zur aktuellen Aktivität, wenn das Fenster des Dokuments zum Standard-Fenster wird. Unter iOS müssen Sie für NSUserActivity
Objekte, die von UIKit
verwalteten Objekten verwaltet werden, entweder explizit aufrufen BecomeCurrent
oder die Eigenschaft des UserActivity
Dokuments auf eine UIViewController
Festgelegte festlegen, wenn die App in den Vordergrund kommt.
AppKit
stellt alle UserActivity
auf os X erstellten Eigenschaften automatisch wieder her. Dies tritt auf, wenn die ContinueUserActivity
Methode zurückgegeben false
wird oder nicht implementiert ist. In diesem Fall wird das Dokument mit der OpenDocument
Methode des NSDocumentController
Dokuments geöffnet und empfängt dann einen RestoreUserActivityState
Methodenaufruf.
Weitere Informationen finden Sie im Abschnitt "Unterstützende Übergabe in dokumentbasierten Apps".
Benutzeraktivitäten und Antwortende
Beide und UIKit
AppKit
können eine Benutzeraktivität automatisch verwalten, wenn Sie sie als Eigenschaft eines UserActivity
Responder-Objekts festlegen. Wenn der Zustand geändert wurde, müssen Sie die NeedsSave
Eigenschaft des Antwortenden UserActivity
auf festlegen true
. Das System speichert den UserActivity
erforderlichen Zeitpunkt automatisch, nachdem der Antwortende Zeit zum Aktualisieren des Zustands durch Aufrufen der UpdateUserActivityState
Methode erhalten hat.
Wenn mehrere Antwortende eine einzelne NSUserActivity
Instanz freigeben, erhalten sie einen UpdateUserActivityState
Rückruf, wenn das System das Benutzeraktivitätsobjekt aktualisiert. Der Responder muss die AddUserInfoEntries
Methode aufrufen, um das NSUserActivity
Wörterbuch zu aktualisieren, um den aktuellen Aktivitätsstatus UserInfo
an diesem Punkt widerzuspiegeln. Das UserInfo
Wörterbuch wird vor jedem UpdateUserActivityState
Anruf gelöscht.
Um sich von einer Aktivität zu trennen, kann ein Responder seine UserActivity
Eigenschaft auf null
festlegen. Wenn eine verwaltete NSUserActivity
Instanz eines App-Frameworks keine weiteren antwortenden Personen oder Dokumente enthält, wird sie automatisch ungültig.
Weitere Informationen finden Sie im Abschnitt "Unterstützende Übergabe in Responders".
Benutzeraktivitäten und appDelegate
Die App ist AppDelegate
der primäre Einstiegspunkt bei der Behandlung einer Handoff-Fortsetzung. Wenn der Benutzer auf eine Handoff-Benachrichtigung antwortet, wird die entsprechende App gestartet (sofern noch nicht ausgeführt), und die WillContinueUserActivityWithType
Methode der AppDelegate
App wird aufgerufen. An diesem Punkt sollte die App den Benutzer darüber informieren, dass die Fortsetzung gestartet wird.
Die NSUserActivity
Instanz wird übermittelt, wenn die AppDelegate
Methode ContinueUserActivity
aufgerufen wird. Zu diesem Zeitpunkt sollten Sie die Benutzeroberfläche der App konfigurieren und die angegebene Aktivität fortsetzen.
Weitere Informationen finden Sie im Abschnitt "Implementieren von Handoff" weiter unten.
Aktivieren der Übergabe in einer Xamarin-App
Aufgrund der von Handoff auferlegten Sicherheitsanforderungen muss eine Xamarin.iOS-App, die das Handoff-Framework verwendet, sowohl im Apple Developer Portal als auch in der Xamarin.iOS-Projektdatei ordnungsgemäß konfiguriert sein.
Gehen Sie folgendermaßen vor:
Melden Sie sich beim Apple Developer Portal an.
Klicken Sie auf Zertifikate, Bezeichner und Profile.
Wenn Sie dies noch nicht getan haben, klicken Sie auf Bezeichner , und erstellen Sie eine ID für Ihre App (z. B.
com.company.appname
), sonst bearbeiten Sie Ihre vorhandene ID.Stellen Sie sicher, dass der iCloud-Dienst auf die angegebene ID überprüft wurde:
Speichern Sie die Änderungen.
Klicken Sie auf die Entwicklung von Bereitstellungsprofilen>, und erstellen Sie ein neues Entwicklungsbereitstellungsprofil für Ihre App:
Laden Sie entweder das neue Bereitstellungsprofil herunter, und installieren Sie es mit Xcode, um das Profil herunterzuladen und zu installieren.
Bearbeiten Sie Ihre Xamarin.iOS-Projektoptionen, und stellen Sie sicher, dass Sie das soeben erstellte Bereitstellungsprofil verwenden:
Bearbeiten Sie als Nächstes Ihre Info.plist-Datei , und stellen Sie sicher, dass Sie die App-ID verwenden, die zum Erstellen des Bereitstellungsprofils verwendet wurde:
Scrollen Sie zum Abschnitt "Hintergrundmodi" , und überprüfen Sie die folgenden Elemente:
Speichern Sie die Änderungen an allen Dateien.
Mit diesen Einstellungen ist die Anwendung jetzt bereit, auf die Handoff Framework-APIs zuzugreifen. Ausführliche Informationen zur Bereitstellung finden Sie in unseren Leitfäden zur Gerätebereitstellung und -bereitstellung.
Implementieren von Handoff
Benutzeraktivitäten können unter Apps fortgesetzt werden, die mit derselben Entwicklerteam-ID signiert sind und denselben Aktivitätstyp unterstützen. Die Implementierung von Handoff in einer Xamarin.iOS-App erfordert, dass Sie ein Benutzeraktivitätsobjekt (entweder in UIKit
oder AppKit
), den Status des Objekts aktualisieren, um die Aktivität nachzuverfolgen und die Aktivität auf einem empfangenden Gerät fortzusetzen.
Identifizieren von Benutzeraktivitäten
Der erste Schritt bei der Implementierung von Handoff besteht darin, die Arten von Benutzeraktivitäten zu identifizieren, die Ihre App unterstützt, und zu sehen, welche dieser Aktivitäten für die Fortsetzung auf einem anderen Gerät geeignet sind. Beispiel: Eine ToDo-App kann die Bearbeitung von Elementen als einen Benutzeraktivitätstyp unterstützen und das Durchsuchen der liste verfügbarer Elemente als eine andere unterstützen.
Eine App kann beliebig viele Benutzeraktivitätstypen erstellen, eine für jede funktion, die die App bereitstellt. Für jeden Benutzeraktivitätstyp muss die App nachverfolgen, wann eine Aktivität des Typs beginnt und endet, und muss aktuelle Statusinformationen Standard beibehalten, um diese Aufgabe auf einem anderen Gerät fortzusetzen.
Benutzeraktivitäten können für jede App fortgesetzt werden, die mit derselben Team-ID signiert ist, ohne eine 1:1-Zuordnung zwischen dem Senden und Empfangen von Apps durchzuführen. Beispielsweise kann eine bestimmte App vier verschiedene Arten von Aktivitäten erstellen, die von verschiedenen, einzelnen Apps auf einem anderen Gerät genutzt werden. Dies ist ein häufiges Vorkommen zwischen einer Mac-Version der App (die möglicherweise über viele Features und Funktionen verfügt) und iOS-Apps, bei denen jede App kleiner ist und sich auf eine bestimmte Aufgabe konzentriert.
Erstellen von Aktivitätstypbezeichnern
Der Aktivitätstypbezeichner ist eine kurze Zeichenfolge, die dem NSUserActivityTypes
Array der Info.plist-Datei der App hinzugefügt wird, die verwendet wird, um einen bestimmten Benutzeraktivitätstyp eindeutig zu identifizieren. Es gibt einen Eintrag im Array für jede Aktivität, die die App unterstützt. Apple schlägt vor, eine Reverse-DNS-Schreibweise für den Aktivitätstypbezeichner zu verwenden, um Kollisionen zu vermeiden. Beispiel: com.company-name.appname.activity
für bestimmte appbasierte Aktivitäten oder com.company-name.activity
für Aktivitäten, die über mehrere Apps hinweg ausgeführt werden können.
Der Aktivitätstypbezeichner wird beim Erstellen einer NSUserActivity
Instanz verwendet, um den Aktivitätstyp zu identifizieren. Wenn eine Aktivität auf einem anderen Gerät fortgesetzt wird, bestimmt der Aktivitätstyp (zusammen mit der Team-ID der App), welche App gestartet werden soll, um die Aktivität fortzusetzen.
Als Beispiel erstellen wir eine Beispiel-App namens MonkeyBrowser. Diese App stellt vier Registerkarten dar, wobei jeweils eine andere URL in einer Webbrowseransicht geöffnet ist. Der Benutzer kann jede Registerkarte auf einem anderen iOS-Gerät fortsetzen, auf dem die App ausgeführt wird.
Um die erforderlichen Aktivitätstypbezeichner zu erstellen, um dieses Verhalten zu unterstützen, bearbeiten Sie die Info.plist-Datei , und wechseln Sie zur Quellansicht . Fügen Sie einen NSUserActivityTypes
Schlüssel hinzu, und erstellen Sie die folgenden Bezeichner:
Wir haben vier neue Aktivitätstyp-IDs erstellt, eine für jede der Registerkarten in der Beispiel-MonkeyBrowser-App. Ersetzen Sie beim Erstellen Ihrer eigenen Apps den Inhalt des NSUserActivityTypes
Arrays durch die Aktivitätstypbezeichner, die für die von Ihrer App unterstützten Aktivitäten spezifisch sind.
Nachverfolgen von Benutzeraktivitätsänderungen
Wenn wir eine neue Instanz der NSUserActivity
Klasse erstellen, geben wir eine NSUserActivityDelegate
Instanz an, um Änderungen am Status der Aktivität nachzuverfolgen. Beispielsweise kann der folgende Code verwendet werden, um Zustandsänderungen nachzuverfolgen:
using System;
using CoreGraphics;
using Foundation;
using UIKit;
namespace MonkeyBrowse
{
public class UserActivityDelegate : NSUserActivityDelegate
{
#region Constructors
public UserActivityDelegate ()
{
}
#endregion
#region Override Methods
public override void UserActivityReceivedData (NSUserActivity userActivity, NSInputStream inputStream, NSOutputStream outputStream)
{
// Log
Console.WriteLine ("User Activity Received Data: {0}", userActivity.Title);
}
public override void UserActivityWasContinued (NSUserActivity userActivity)
{
Console.WriteLine ("User Activity Was Continued: {0}", userActivity.Title);
}
public override void UserActivityWillSave (NSUserActivity userActivity)
{
Console.WriteLine ("User Activity will be Saved: {0}", userActivity.Title);
}
#endregion
}
}
Die UserActivityReceivedData
Methode wird aufgerufen, wenn ein Fortsetzungsstream Daten von einem sendenden Gerät empfangen hat. Weitere Informationen finden Sie im Abschnitt "Unterstützende Fortsetzungsstreams " weiter unten.
Die UserActivityWasContinued
Methode wird aufgerufen, wenn ein anderes Gerät eine Aktivität vom aktuellen Gerät übernommen hat. Je nach Aktivitätstyp, z. B. dem Hinzufügen eines neuen Elements zu einer ToDo-Liste, muss die App möglicherweise die Aktivität auf dem sendenden Gerät abbrechen.
Die UserActivityWillSave
Methode wird aufgerufen, bevor Änderungen an der Aktivität gespeichert und auf lokal verfügbaren Geräten synchronisiert werden. Mit dieser Methode können Sie alle letzten Minutenänderungen an der UserInfo
Eigenschaft der NSUserActivity
Instanz vornehmen, bevor sie gesendet wird.
Erstellen einer NSUserActivity-Instanz
Jede Aktivität, die Ihre App bereitstellen möchte, muss in einer NSUserActivity
Instanz gekapselt werden. Die App kann beliebig viele Aktivitäten erstellen, und die Art dieser Aktivitäten hängt von der Funktionalität und den Features der betreffenden App ab. Beispielsweise kann eine E-Mail-App eine Aktivität zum Erstellen einer neuen Nachricht und eine andere zum Lesen einer Nachricht erstellen.
Für unsere Beispiel-App wird jedes Mal eine neue NSUserActivity
URL erstellt, wenn der Benutzer eine neue URL in einer der Webbrowseransicht im Registerkartenformat eingibt. Der folgende Code speichert den Status einer bestimmten Registerkarte:
public NSString UserActivityTab1 = new NSString ("com.xamarin.monkeybrowser.tab1");
public NSUserActivity UserActivity { get; set; }
...
UserActivity = new NSUserActivity (UserActivityTab1);
UserActivity.Title = "Weather Tab";
UserActivity.Delegate = new UserActivityDelegate ();
// Update the activity when the tab's URL changes
var userInfo = new NSMutableDictionary ();
userInfo.Add (new NSString ("Url"), new NSString (url));
UserActivity.AddUserInfoEntries (userInfo);
// Inform Activity that it has been updated
UserActivity.BecomeCurrent ();
Es erstellt eine neue NSUserActivity
Verwendung des oben erstellten Benutzeraktivitätstyps und stellt einen lesbaren Titel für die Aktivität bereit. Es wird an eine Instanz der NSUserActivityDelegate
oben erstellten Instanz angefügt, um auf Zustandsänderungen zu achten und iOS darüber zu informieren, dass diese Benutzeraktivität die aktuelle Aktivität ist.
Auffüllen des UserInfo-Wörterbuchs
Wie oben gezeigt, ist die UserInfo
Eigenschaft der NSUserActivity
Klasse ein NSDictionary
Schlüsselwertpaar, das zum Definieren des Zustands einer bestimmten Aktivität verwendet wird. Die gespeicherten UserInfo
Werte müssen einen der folgenden Typen aufweisen: NSArray
, , NSData
, NSDate
, NSDictionary
, NSNull
, NSNumber
, , NSSet
, NSString
oder NSURL
. NSURL
Datenwerte, die auf iCloud-Dokumente verweisen, werden automatisch angepasst, sodass sie auf dieselben Dokumente auf einem empfangenden Gerät verweisen.
Im obigen Beispiel haben wir ein NSMutableDictionary
Objekt erstellt und mit einem einzelnen Schlüssel aufgefüllt, der die URL angibt, die der Benutzer aktuell auf der angegebenen Registerkarte anzeigte. Die AddUserInfoEntries
Methode der Benutzeraktivität wurde verwendet, um die Aktivität mit den Daten zu aktualisieren, die zum Wiederherstellen der Aktivität auf dem empfangenden Gerät verwendet werden:
// Update the activity when the tab's URL changes
var userInfo = new NSMutableDictionary ();
userInfo.Add (new NSString ("Url"), new NSString (url));
UserActivity.AddUserInfoEntries (userInfo);
Apple schlägt vor, die informationen so gering wie möglich zu halten, um sicherzustellen, dass die Aktivität rechtzeitig an das empfangende Gerät gesendet wird. Wenn größere Informationen erforderlich sind, z. B. ein an ein Dokument angefügtes Bild, das bearbeitet werden muss, sollten Sie Fortsetzungsstreams verwenden. Weitere Informationen finden Sie im Abschnitt "Unterstützende Fortsetzungsstreams" weiter unten.
Fortsetzen einer Aktivität
Handoff informiert automatisch lokale iOS- und OS X-Geräte, die sich in physischer Nähe zum ursprünglichen Gerät befinden und bei demselben iCloud-Konto angemeldet sind, über die Verfügbarkeit von zusammenhängenden Benutzeraktivitäten. Wenn der Benutzer eine Aktivität auf einem neuen Gerät fortsetzen möchte, startet das System die entsprechende App (basierend auf der Team-ID und dem Aktivitätstyp) und informationen AppDelegate
darüber, dass die Fortsetzung erfolgen muss.
Zunächst wird die WillContinueUserActivityWithType
Methode aufgerufen, damit die App den Benutzer darüber informieren kann, dass die Fortsetzung beginnen soll. Wir verwenden den folgenden Code in der AppDelegate.cs Datei unserer Beispiel-App, um einen Fortsetzungsstart zu behandeln:
public NSString UserActivityTab1 = new NSString ("com.xamarin.monkeybrowser.tab1");
public NSString UserActivityTab2 = new NSString ("com.xamarin.monkeybrowser.tab2");
public NSString UserActivityTab3 = new NSString ("com.xamarin.monkeybrowser.tab3");
public NSString UserActivityTab4 = new NSString ("com.xamarin.monkeybrowser.tab4");
...
public FirstViewController Tab1 { get; set; }
public SecondViewController Tab2 { get; set;}
public ThirdViewController Tab3 { get; set; }
public FourthViewController Tab4 { get; set; }
...
public override bool WillContinueUserActivity (UIApplication application, string userActivityType)
{
// Report Activity
Console.WriteLine ("Will Continue Activity: {0}", userActivityType);
// Take action based on the user activity type
switch (userActivityType) {
case "com.xamarin.monkeybrowser.tab1":
// Inform view that it's going to be modified
Tab1.PreparingToHandoff ();
break;
case "com.xamarin.monkeybrowser.tab2":
// Inform view that it's going to be modified
Tab2.PreparingToHandoff ();
break;
case "com.xamarin.monkeybrowser.tab3":
// Inform view that it's going to be modified
Tab3.PreparingToHandoff ();
break;
case "com.xamarin.monkeybrowser.tab4":
// Inform view that it's going to be modified
Tab4.PreparingToHandoff ();
break;
}
// Inform system we handled this
return true;
}
Im obigen Beispiel registriert sich jeder Ansichtscontroller mit der und verfügt über eine öffentliche PreparingToHandoff
Methode, mit der AppDelegate
ein Aktivitätsindikator angezeigt wird, und eine Meldung, die dem Benutzer darüber informiert, dass die Aktivität an das aktuelle Gerät übergeben werden soll. Beispiel:
private void ShowBusy(string reason) {
// Display reason
BusyText.Text = reason;
//Define Animation
UIView.BeginAnimations("Show");
UIView.SetAnimationDuration(1.0f);
Handoff.Alpha = 0.5f;
//Execute Animation
UIView.CommitAnimations();
}
...
public void PreparingToHandoff() {
// Inform caller
ShowBusy ("Continuing Activity...");
}
AppDelegate
Der ContinueUserActivity
Wille wird aufgerufen, die angegebene Aktivität tatsächlich fortzusetzen. Erneut aus unserer Beispiel-App:
public override bool ContinueUserActivity (UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)
{
// Report Activity
Console.WriteLine ("Continuing User Activity: {0}", userActivity.ToString());
// Get input and output streams from the Activity
userActivity.GetContinuationStreams ((NSInputStream arg1, NSOutputStream arg2, NSError arg3) => {
// Send required data via the streams
// ...
});
// Take action based on the Activity type
switch (userActivity.ActivityType) {
case "com.xamarin.monkeybrowser.tab1":
// Preform handoff
Tab1.PerformHandoff (userActivity);
completionHandler (new NSObject[]{Tab1});
break;
case "com.xamarin.monkeybrowser.tab2":
// Preform handoff
Tab2.PerformHandoff (userActivity);
completionHandler (new NSObject[]{Tab2});
break;
case "com.xamarin.monkeybrowser.tab3":
// Preform handoff
Tab3.PerformHandoff (userActivity);
completionHandler (new NSObject[]{Tab3});
break;
case "com.xamarin.monkeybrowser.tab4":
// Preform handoff
Tab4.PerformHandoff (userActivity);
completionHandler (new NSObject[]{Tab4});
break;
}
// Inform system we handled this
return true;
}
Die öffentliche PerformHandoff
Methode jedes Ansichtscontrollers stellt die Übergabe tatsächlich vor und stellt die Aktivität auf dem aktuellen Gerät wieder her. Im Fall des Beispiels wird dieselbe URL auf einer bestimmten Registerkarte angezeigt, die der Benutzer auf einem anderen Gerät durchsucht hat. Beispiel:
private void HideBusy() {
//Define Animation
UIView.BeginAnimations("Hide");
UIView.SetAnimationDuration(1.0f);
Handoff.Alpha = 0f;
//Execute Animation
UIView.CommitAnimations();
}
...
public void PerformHandoff(NSUserActivity activity) {
// Hide busy indicator
HideBusy ();
// Extract URL from dictionary
var url = activity.UserInfo ["Url"].ToString ();
// Display value
URL.Text = url;
// Display the give webpage
WebView.LoadRequest(new NSUrlRequest(NSUrl.FromString(url)));
// Save activity
UserActivity = activity;
UserActivity.BecomeCurrent ();
}
Die ContinueUserActivity
Methode enthält eine UIApplicationRestorationHandler
Methode, die Sie für die Fortsetzung der dokument- oder responder-basierten Aktivität aufrufen können. Sie müssen beim Aufrufen ein NSArray
oder wiederherstellbare Objekte an den Wiederherstellungshandler übergeben. Zum Beispiel:
completionHandler (new NSObject[]{Tab4});
Für jedes übergebene Objekt wird seine RestoreUserActivityState
Methode aufgerufen. Jedes Objekt kann dann die Daten im UserInfo
Wörterbuch verwenden, um seinen eigenen Zustand wiederherzustellen. Zum Beispiel:
public override void RestoreUserActivityState (NSUserActivity activity)
{
base.RestoreUserActivityState (activity);
// Log activity
Console.WriteLine ("Restoring Activity {0}", activity.Title);
}
Bei dokumentbasierten Apps, wenn Sie die ContinueUserActivity
Methode nicht implementieren oder diese zurückgeben false
, UIKit
oder AppKit
die Aktivität automatisch fortsetzen können. Weitere Informationen finden Sie im Abschnitt "Unterstützende Übergabe in dokumentbasierten Apps".
Fehlerhafte Übergabe ordnungsgemäß
Da Handoff auf die Übertragung von Informationen zwischen einer Sammlung lose angeschlossenen iOS- und OS X-Geräten beruht, kann der Übertragungsprozess manchmal fehlschlagen. Sie sollten Ihre App so entwerfen, dass diese Fehler ordnungsgemäß behandelt werden, und den Benutzer über situationen informieren, die auftreten.
Im Falle eines Fehlers wird die DidFailToContinueUserActivitiy
Methode der AppDelegate
Methode aufgerufen. Zum Beispiel:
public override void DidFailToContinueUserActivitiy (UIApplication application, string userActivityType, NSError error)
{
// Log information about the failure
Console.WriteLine ("User Activity {0} failed to continue. Error: {1}", userActivityType, error.LocalizedDescription);
}
Sie sollten die bereitgestellten NSError
Informationen verwenden, um dem Benutzer Informationen über den Fehler bereitzustellen.
Native App in Webbrowser Handoff
Ein Benutzer möchte möglicherweise eine Aktivität fortsetzen, ohne eine entsprechende systemeigene App auf dem gewünschten Gerät installiert zu haben. In einigen Fällen kann eine webbasierte Schnittstelle die erforderliche Funktionalität bereitstellen, und die Aktivität kann weiterhin fortgesetzt werden. Beispielsweise kann das E-Mail-Konto des Benutzers eine Webbasisbenutzeroberfläche zum Verfassen und Lesen von Nachrichten bereitstellen.
Wenn die ursprüngliche App die URL für die Webschnittstelle kennt (und die erforderliche Syntax zum Identifizieren des angegebenen Elements, das fortgesetzt wird), kann sie diese Informationen in der WebpageURL
Eigenschaft der NSUserActivity
Instanz codieren. Wenn das empfangende Gerät keine entsprechende systemeigene App installiert hat, um die Fortsetzung zu verarbeiten, kann die bereitgestellte Webschnittstelle aufgerufen werden.
Webbrowser zur nativen App-Übergabe
Wenn der Benutzer eine webbasierte Schnittstelle auf dem ursprünglichen Gerät verwendet hat und eine systemeigene App auf dem empfangenden Gerät den Do Standard Teil der WebpageURL
Eigenschaft angibt, verwendet das System diese App, um die Fortsetzung zu behandeln. Das neue Gerät erhält eine NSUserActivity
Instanz, die den Aktivitätstyp als BrowsingWeb
und die WebpageURL
URL enthält, die der Benutzer besucht hat, das UserInfo
Wörterbuch ist leer.
Damit eine App an dieser Art von Handoff teilnimmt, muss sie das tun Standard in einer com.apple.developer.associated-domains
Berechtigung mit dem Format <service>:<fully qualified domain name>
(z. B.: activity continuation:company.com
).
Wenn die angegebene Do Standard dem Wert einer WebpageURL
Eigenschaft entspricht, lädt Handoff eine Liste genehmigter App-IDs von der Website dazu herunter Standard. Die Website muss eine Liste genehmigter IDs in einer signierten JSON-Datei mit dem Namen apple-app-site-association (z. B https://company.com/apple-app-site-association
. ) bereitstellen.
Diese JSON-Datei enthält ein Wörterbuch, das eine Liste der App-IDs im Formular <team identifier>.<bundle identifier>
angibt. Zum Beispiel:
{
"activitycontinuation": {
"apps": [ "YWBN8XTPBJ.com.company.FirstApp",
"YWBN8XTPBJ.com.company.SecondApp" ]
}
}
Verwenden Sie die Content-Type
application/pkcs7-mime
Terminal-App und einen Befehl mit einem Zertifikat und einem openssl
Schlüssel, die von einer von iOS vertrauenswürdigen Zertifizierungsstelle ausgestellt wurde (siehe https://support.apple.com/kb/ht5012 Liste). Zum Beispiel:
echo '{"activitycontinuation":{"apps":["YWBN8XTPBJ.com.company.FirstApp",
"YWBN8XTPBJ.com.company.SecondApp"]}}' > json.txt
cat json.txt | openssl smime -sign -inkey company.com.key
-signer company.com.pem
-certfile intermediate.pem
-noattr -nodetach
-outform DER > apple-app-site-association
Der openssl
Befehl gibt eine signierte JSON-Datei aus, die Sie auf Ihrer Website unter der URL der Apple-app-site-association platzieren. Zum Beispiel:
https://example.com/apple-app-site-association.
Die App erhält jede Aktivität, deren WebpageURL
Aufgaben Standard sich in ihrer com.apple.developer.associated-domains
Berechtigung befindet. Nur die http
https
Protokolle werden unterstützt, jedes andere Protokoll löst eine Ausnahme aus.
Unterstützung der Übergabe in dokumentbasierten Apps
Wie oben erwähnt, unterstützen dokumentbasierte iOS- und OS X-Apps automatisch die Übergabe von iCloud-basierten Dokumenten, wenn die Datei "Info.plist" der App einen CFBundleDocumentTypes
Schlüssel NSUbiquitousDocumentUserActivityType
enthält. Zum Beispiel:
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>NSRTFDPboardType</string>
. . .
<key>LSItemContentTypes</key>
<array>
<string>com.myCompany.rtfd</string>
</array>
. . .
<key>NSUbiquitousDocumentUserActivityType</key>
<string>com.myCompany.myEditor.editing</string>
</dict>
</array>
In diesem Beispiel ist die Zeichenfolge ein Reverse-DNS-App-Designator mit dem Namen der angefügten Aktivität. Wenn sie auf diese Weise eingegeben werden, müssen die Aktivitätstypeinträge nicht im NSUserActivityTypes
Array der Info.plist-Datei wiederholt werden.
Auf das automatisch erstellte Benutzeraktivitätsobjekt (verfügbar über die Eigenschaft des Dokuments) kann von anderen Objekten in der App verwiesen und zum Wiederherstellen des Zustands UserActivity
für die Fortsetzung verwendet werden. Beispielsweise zum Nachverfolgen der Elementauswahl und Dokumentposition. Sie müssen diese Aktivitätseigenschaft NeedsSave
true
immer dann festlegen, wenn sich der Zustand ändert und das UserInfo
Wörterbuch in der UpdateUserActivityState
Methode aktualisiert.
Die UserActivity
Eigenschaft kann von jedem Thread verwendet werden und entspricht dem KVO-Protokoll (Key-Value Observing), sodass es verwendet werden kann, um ein Dokument synchron zu halten, während es sich in und aus iCloud bewegt. Die UserActivity
Eigenschaft wird beim Schließen des Dokuments ungültig.
Weitere Informationen finden Sie in der Dokumentation zu dokumentbasierten Apps in der Apple-Dokumentation zur Benutzeraktivität.
Unterstützung von Handoff in Respondern
Sie können Antwortende (geerbt von iOS UIResponder
oder NSResponder
os X) zu Aktivitäten zuordnen, indem Sie deren UserActivity
Eigenschaften festlegen. Das System speichert die UserActivity
Eigenschaft automatisch zu den entsprechenden Zeiten, wobei die Methode des UpdateUserActivityState
Antwortenden aufgerufen wird, um dem User Activity-Objekt mithilfe der AddUserInfoEntriesFromDictionary
Methode aktuelle Daten hinzuzufügen.
Unterstützen von Fortsetzungsstreams
Dies kann situationen sein, in denen die Menge der informationen, die erforderlich sind, um eine Aktivität fortzusetzen, nicht effizient von der anfänglichen Handoff-Nutzlast übertragen werden kann. In diesen Fällen kann die empfangende App einen oder mehrere Datenströme zwischen sich selbst und der ursprünglichen App einrichten, um die Daten zu übertragen.
Die ursprüngliche App legt die SupportsContinuationStreams
Eigenschaft der NSUserActivity
Instanz auf true
. Zum Beispiel:
// Create a new user Activity to support this tab
UserActivity = new NSUserActivity (ThisApp.UserActivityTab1){
Title = "Weather Tab",
SupportsContinuationStreams = true
};
UserActivity.Delegate = new UserActivityDelegate ();
// Update the activity when the tab's URL changes
var userInfo = new NSMutableDictionary ();
userInfo.Add (new NSString ("Url"), new NSString (url));
UserActivity.AddUserInfoEntries (userInfo);
// Inform Activity that it has been updated
UserActivity.BecomeCurrent ();
Die empfangende App kann dann die GetContinuationStreams
Methode des NSUserActivity
Datenstroms AppDelegate
aufrufen, um den Datenstrom herzustellen. Zum Beispiel:
public override bool ContinueUserActivity (UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)
{
// Report Activity
Console.WriteLine ("Continuing User Activity: {0}", userActivity.ToString());
// Get input and output streams from the Activity
userActivity.GetContinuationStreams ((NSInputStream arg1, NSOutputStream arg2, NSError arg3) => {
// Send required data via the streams
// ...
});
// Take action based on the Activity type
switch (userActivity.ActivityType) {
case "com.xamarin.monkeybrowser.tab1":
// Preform handoff
Tab1.PerformHandoff (userActivity);
completionHandler (new NSObject[]{Tab1});
break;
case "com.xamarin.monkeybrowser.tab2":
// Preform handoff
Tab2.PerformHandoff (userActivity);
completionHandler (new NSObject[]{Tab2});
break;
case "com.xamarin.monkeybrowser.tab3":
// Preform handoff
Tab3.PerformHandoff (userActivity);
completionHandler (new NSObject[]{Tab3});
break;
case "com.xamarin.monkeybrowser.tab4":
// Preform handoff
Tab4.PerformHandoff (userActivity);
completionHandler (new NSObject[]{Tab4});
break;
}
// Inform system we handled this
return true;
}
Auf dem ursprünglichen Gerät empfängt der Benutzeraktivitätsdelegat die Datenströme, indem er seine DidReceiveInputStream
Methode aufruft, um die angeforderten Daten bereitzustellen, um die Benutzeraktivität auf dem reaktivierenden Gerät fortzusetzen.
Sie verwenden einen NSInputStream
schreibgeschützten Zugriff auf Datenstreams und einen NSOutputStream
schreibgeschützten Zugriff. Die Datenströme sollten auf Anforderungs- und Antwort weise verwendet werden, wobei die empfangende App weitere Daten anfordert und die ursprüngliche App sie bereitstellt. Daher werden daten, die in den Ausgabedatenstrom auf dem ursprünglichen Gerät geschrieben wurden, aus dem Eingabedatenstrom auf dem fortlaufenden Gerät gelesen und umgekehrt.
Auch in Situationen, in denen Fortsetzungsstream erforderlich ist, sollte die Kommunikation zwischen den beiden Apps minimal sein.
Weitere Informationen finden Sie in der Dokumentation zur Verwendung von Fortsetzungsstreams von Apple.
Bewährte Methoden für die Übergabe
Die erfolgreiche Implementierung der nahtlosen Fortsetzung einer Benutzeraktivität über Handoff erfordert ein sorgfältiges Design aufgrund aller beteiligten Komponenten. Apple schlägt vor, die folgenden bewährten Methoden für Ihre Handoff-aktivierten Apps zu übernehmen:
- Entwerfen Sie Ihre Benutzeraktivitäten so, dass die kleinste Nutzlast erforderlich ist, die möglich ist, um den Status der Aktivität zu verknüpfen, die fortgesetzt werden soll. Je größer die Nutzlast ist, desto länger dauert die Fortsetzung.
- Wenn Sie große Datenmengen für eine erfolgreiche Fortsetzung übertragen müssen, berücksichtigen Sie die Kosten für die Konfiguration und den Netzwerkaufwand.
- Es ist üblich, dass eine große Mac-App Benutzeraktivitäten erstellt, die von mehreren, kleineren aufgabenspezifischen Apps auf iOS-Geräten behandelt werden. Die verschiedenen App- und Betriebssystemversionen sollten so konzipiert sein, dass sie gut zusammenarbeiten oder ordnungsgemäß fehlschlagen.
- Verwenden Sie bei der Angabe Ihrer Aktivitätstypen die Reverse-DNS-Notation, um Kollisionen zu vermeiden. Wenn eine Aktivität für eine bestimmte App spezifisch ist, sollte der Name in die Typdefinition aufgenommen werden (z. B
com.myCompany.myEditor.editing
. ). Wenn die Aktivität über mehrere Apps hinweg funktionieren kann, legen Sie den App-Namen aus der Definition ab (z. Bcom.myCompany.editing
. ). - Wenn Ihre App den Status einer Benutzeraktivität (
NSUserActivity
) aktualisieren muss, legen Sie dieNeedsSave
Eigenschaft auftrue
. Zu geeigneten Zeiten ruft Handoff die Methode derUserActivityWillSave
Stellvertretung auf, damit Sie dasUserInfo
Wörterbuch nach Bedarf aktualisieren können. - Da der Übergabevorgang möglicherweise nicht sofort auf dem empfangenden Gerät initialisiert wird, sollten Sie die
AppDelegate
'sWillContinueUserActivity
implementieren und den Benutzer darüber informieren, dass eine Fortsetzung beginnt.
Beispiel-Handoff-App
Ein Beispiel für die Verwendung von Handoff in einer Xamarin.iOS-App ist die MonkeyBrowser-Beispiel-App . Die App verfügt über vier Registerkarten, mit denen der Benutzer das Web durchsuchen kann, jeweils mit einem bestimmten Aktivitätstyp: Wetter, Favorit, Kaffeepause und Arbeit.
Wenn der Benutzer auf einer beliebigen Registerkarte eine neue URL eingibt und auf die Schaltfläche "Gehe" tippt, wird eine neue NSUserActivity
Für diese Registerkarte erstellt, die die URL enthält, die der Benutzer gerade durchsucht:
Wenn eine andere der Geräte des Benutzers die MonkeyBrowser-App installiert hat, mit demselben Benutzerkonto bei iCloud angemeldet ist, sich im gleichen Netzwerk befindet und sich in unmittelbarer Nähe zum obigen Gerät befindet, wird die Handoff-Aktivität auf dem Startbildschirm angezeigt (in der unteren linken Ecke):
Wenn der Benutzer auf das Handoff-Symbol nach oben zieht, wird die App gestartet, und die in der NSUserActivity
App angegebene Benutzeraktivität wird auf dem neuen Gerät fortgesetzt:
Wenn die Benutzeraktivität erfolgreich an ein anderes Apple-Gerät gesendet wurde, erhält das sendende Gerät NSUserActivity
einen Aufruf der UserActivityWasContinued
Methode, NSUserActivityDelegate
um sie darüber zu informieren, dass die Benutzeraktivität erfolgreich auf ein anderes Gerät übertragen wurde.
Zusammenfassung
Dieser Artikel enthält eine Einführung in das Handoff-Framework, das verwendet wird, um eine Benutzeraktivität zwischen mehreren Apple-Geräten des Benutzers fortzusetzen. Als Nächstes wurde gezeigt, wie Handoff in einer Xamarin.iOS-App aktiviert und implementiert wird. Schließlich wurden die verschiedenen Verfügbaren Arten von Handoff-Fortsetzungen und die bewährten Methoden der Handoff erörtert.