Przekazywanie w środowisku Xamarin.iOS
W tym artykule opisano pracę z przekazywaniem w aplikacji platformy Xamarin.iOS w celu przeniesienia działań użytkownika między aplikacjami uruchomionymi na innych urządzeniach użytkownika.
Firma Apple wprowadziła funkcję Handoff w systemach iOS 8 i OS X Yosemite (10.10), aby zapewnić wspólny mechanizm przenoszenia działań wykonywanych na jednym z urządzeń na innym urządzeniu z tą samą aplikacją lub inną aplikacją, która obsługuje tę samą aktywność.
W tym artykule przedstawiono szybkie omówienie włączania udostępniania działań w aplikacji platformy Xamarin.iOS i omówiono szczegółowo strukturę Handoff:
Informacje o przekazach
Przekazywanie (znane również jako ciągłość) zostało wprowadzone przez firmę Apple w systemach iOS 8 i OS X Yosemite (10.10) jako sposób na rozpoczęcie działania na jednym z urządzeń (iOS lub Mac) i kontynuowanie tej samej aktywności na innych urządzeniach (zidentyfikowanych przez konto użytkownika w usłudze iCloud).
Przekazywanie zostało rozszerzone w systemie iOS 9, aby również obsługiwać nowe, ulepszone funkcje wyszukiwania. Aby uzyskać więcej informacji, zobacz dokumentację dotyczącą ulepszeń wyszukiwania.
Na przykład użytkownik może uruchomić wiadomość e-mail na swoim urządzeniu i Telefon i bezproblemowo kontynuować wiadomość e-mail na komputerze Mac, z wszystkimi tymi samymi informacjami o wiadomościach wypełnionymi i kursorem w tej samej lokalizacji, w której ją opuścili w systemie iOS.
Wszystkie aplikacje, które współużytkują ten sam identyfikator zespołu, kwalifikują się do korzystania z funkcji Handoff w celu kontynuowania działań użytkowników w aplikacjach, o ile ta aplikacja jest dostarczana za pośrednictwem sklepu iTunes App Store lub podpisanego przez zarejestrowanego dewelopera (w przypadku aplikacji Dla komputerów Mac, Enterprise lub Ad Hoc).
Wszystkie NSDocument
aplikacje lub UIDocument
oparte automatycznie mają wbudowaną obsługę przekazywania i wymagają minimalnych zmian w celu obsługi przekazywania.
Dalsze działania użytkownika
Klasa NSUserActivity
(wraz z niewielkimi zmianami w UIKit
systemach i AppKit
) zapewnia obsługę definiowania aktywności użytkownika, które potencjalnie mogą być kontynuowane na innych urządzeniach użytkownika.
Aby działanie zostało przekazane do innego urządzenia użytkownika, musi ono zostać hermetyzowane w wystąpieniu NSUserActivity
oznaczonym jako bieżące działanie, czy jest to zestaw ładunków (dane używane do wykonania kontynuacji), a następnie działanie musi zostać przesłane do tego urządzenia.
Przekazywanie przekazuje podstawowe informacje, aby zdefiniować działanie, które ma być kontynuowane, przy czym większe pakiety danych są synchronizowane za pośrednictwem usługi iCloud.
Na urządzeniu odbieranym użytkownik otrzyma powiadomienie, że działanie jest dostępne do kontynuacji. Jeśli użytkownik zdecyduje się kontynuować działanie na nowym urządzeniu, określona aplikacja zostanie uruchomiona (jeśli jeszcze nie jest uruchomiona), a ładunek z NSUserActivity
niego zostanie użyty do ponownego uruchomienia działania.
Tylko aplikacje, które współużytkują ten sam identyfikator zespołu deweloperów i odpowiadają na dany typ działania, kwalifikują się do kontynuacji. Aplikacja definiuje typy działań, które obsługuje w kluczu NSUserActivityTypes
pliku Info.plist . Biorąc pod uwagę to, ciągłe urządzenie wybiera aplikację do wykonania kontynuacji na podstawie identyfikatora zespołu, typu działania i opcjonalnie tytułu działania.
Aplikacja odbierającą używa informacji ze NSUserActivity
słownika w celu skonfigurowania UserInfo
interfejsu użytkownika i przywrócenia stanu danego działania, aby przejście było bezproblemowe dla użytkownika końcowego.
Jeśli kontynuacja wymaga więcej informacji niż można wysłać wydajnie za pośrednictwem NSUserActivity
aplikacji , wznawianie aplikacji może wysłać wywołanie do aplikacji źródłowej i ustanowić jeden lub więcej strumieni w celu przesłania wymaganych danych. Jeśli na przykład działanie edytowało duży dokument tekstowy z wieloma obrazami, przesyłanie strumieniowe będzie wymagane do przeniesienia informacji potrzebnych do kontynuowania działania na urządzeniu odbierającego. Aby uzyskać więcej informacji, zobacz sekcję Obsługa kontynuacji Strumienie poniżej.
Jak wspomniano powyżej, NSDocument
aplikacje UIDocument
oparte automatycznie mają wbudowaną obsługę przekazywania. Aby uzyskać więcej informacji, zobacz sekcję Obsługa przekazywania w aplikacjach opartych na dokumentach poniżej.
Klasa NSUserActivity
Klasa NSUserActivity
jest obiektem podstawowym w wymianie handoff i służy do hermetyzacji stanu działania użytkownika, który jest dostępny do kontynuacji. Aplikacja utworzy wystąpienie kopii dowolnego obsługiwanego NSUserActivity
działania i chce kontynuować na innym urządzeniu. Na przykład edytor dokumentów utworzy działanie dla każdego aktualnie otwartego dokumentu. Jednak tylko dokument z przodu (wyświetlany w najbardziej przednim oknie lub karcie) to bieżące działanie i dostępne dla kontynuacji.
Wystąpienie NSUserActivity
klasy jest identyfikowane zarówno przez jego ActivityType
właściwości, jak i Title
. Właściwość słownika UserInfo
służy do przenoszenia informacji o stanie działania. NeedsSave
Ustaw właściwość na wartość true
, jeśli chcesz opóźnić ładowanie informacji o stanie za pośrednictwem NSUserActivity
delegata . AddUserInfoEntries
Użyj metody , aby scalić nowe dane z innych klientów do UserInfo
słownika zgodnie z wymaganiami, aby zachować stan działania.
Klasa NSUserActivityDelegate
Element NSUserActivityDelegate
służy do przechowywania informacji w NSUserActivity
UserInfo
słowniku aktualnym i zsynchronizowanym z bieżącym stanem działania. Gdy system wymaga zaktualizowania informacji w działaniu (na przykład przed kontynuacją na innym urządzeniu), wywołuje UserActivityWillSave
metodę delegata.
Należy zaimplementować metodę UserActivityWillSave
i wprowadzić wszelkie zmiany w NSUserActivity
obiekcie (takim jak UserInfo
, Title
itp.), aby upewnić się, że nadal odzwierciedla stan bieżącej aktywności. Gdy system wywołuje metodę UserActivityWillSave
, flaga NeedsSave
zostanie wyczyszczone. Jeśli zmodyfikujesz dowolne właściwości danych działania, musisz ponownie ustawić wartość NeedsSave
true
.
Zamiast używać przedstawionej UserActivityWillSave
powyżej metody, możesz opcjonalnie automatycznie mieć UIKit
aktywność użytkownika lub AppKit
zarządzać nią. W tym celu ustaw właściwość obiektu odpowiadającego UserActivity
i zaimplementuj metodę UpdateUserActivityState
. Aby uzyskać więcej informacji, zobacz sekcję Pomocnicza przekazywanie w odpowiedziach poniżej.
Obsługa platformy aplikacji
Obie UIKit
metody (iOS) i AppKit
(OS X) zapewniają wbudowaną obsługę przekazywania w klasach NSDocument
, responder (NSResponder
UIResponder
/) i .AppDelegate
Chociaż każdy system operacyjny implementuje przekazywanie nieco inaczej, podstawowy mechanizm i interfejsy API są takie same.
Działania użytkownika w aplikacjach opartych na dokumentach
Aplikacje dla systemów iOS i OS X oparte na dokumentach automatycznie mają wbudowaną obsługę przekazywania. Aby aktywować tę obsługę, musisz dodać NSUbiquitousDocumentUserActivityType
klucz i wartość dla każdego CFBundleDocumentTypes
wpisu w pliku Info.plist aplikacji.
Jeśli ten klucz jest obecny, zarówno, jak NSDocument
i UIDocument
automatycznie utwórz NSUserActivity
wystąpienia dla dokumentów opartych na usłudze iCloud określonego typu. Musisz podać typ działania dla każdego typu dokumentu obsługiwanego przez aplikację, a wiele typów dokumentów może używać tego samego typu działania. Zarówno, NSDocument
jak i UIDocument
automatycznie wypełniają UserInfo
właściwość NSUserActivity
właściwości wartością właściwości FileURL
.
W systemie OS X NSUserActivity
zarządzane przez AppKit
i skojarzone z osobami odpowiadającymi automatycznie stają się bieżącym działaniem, gdy okno dokumentu stanie się głównym oknem. W systemie iOS w przypadku NSUserActivity
obiektów zarządzanych przez UIKit
program należy jawnie wywołać BecomeCurrent
metodę lub ustawić właściwość dokumentu UserActivity
na UIViewController
pierwszym planie, gdy aplikacja pojawi się na pierwszym planie.
AppKit
spowoduje automatyczne przywrócenie dowolnej UserActivity
właściwości utworzonej w ten sposób w systemie OS X. Dzieje się tak, jeśli ContinueUserActivity
metoda zwraca false
wartość lub jeśli jest ona nieimplementowana. W takiej sytuacji dokument zostanie otwarty przy OpenDocument
użyciu metody NSDocumentController
, a następnie otrzyma RestoreUserActivityState
wywołanie metody.
Aby uzyskać więcej informacji, zobacz sekcję Obsługa przekazywania w aplikacjach opartych na dokumentach poniżej.
Działania użytkowników i osoby reagujące
Zarówno UIKit
działanie użytkownika, jak i AppKit
może automatycznie zarządzać nim, jeśli ustawisz je jako właściwość obiektu odpowiadającego UserActivity
. Jeśli stan został zmodyfikowany, należy ustawić NeedsSave
właściwość obiektu odpowiadającego UserActivity
na true
wartość . System automatycznie zapisze UserActivity
w razie potrzeby czas odpowiedzi, aby zaktualizować stan, wywołując jego UpdateUserActivityState
metodę.
Jeśli wiele osób odpowiadających współużytkuje jedno NSUserActivity
wystąpienie, otrzymują wywołanie UpdateUserActivityState
zwrotne, gdy system aktualizuje obiekt aktywności użytkownika. Osoba odpowiadająca musi wywołać metodę AddUserInfoEntries
w celu zaktualizowania NSUserActivity
słownika UserInfo
w celu odzwierciedlenia bieżącego stanu działania w tym momencie. Słownik UserInfo
jest czyszczone przed każdym UpdateUserActivityState
wywołaniem.
Aby usunąć skojarzenie się z działania, obiekt odpowiadający może ustawić jego UserActivity
właściwość na null
. Jeśli wystąpienie zarządzane NSUserActivity
platformy aplikacji nie ma więcej skojarzonych osób odpowiadających ani dokumentów, jest ono automatycznie unieważniane.
Aby uzyskać więcej informacji, zobacz sekcję Pomocnicza przekazywanie w odpowiedziach poniżej.
Działania użytkownika i element AppDelegate
AppDelegate
Aplikacja jest podstawowym punktem wejścia podczas obsługi kontynuacji przekazywania. Gdy użytkownik odpowie na powiadomienie przekazanie, zostanie uruchomiona odpowiednia aplikacja (jeśli jeszcze nie jest uruchomiona), a WillContinueUserActivityWithType
metoda AppDelegate
metody zostanie wywołana. W tym momencie aplikacja powinna poinformować użytkownika o rozpoczęciu kontynuacji.
NSUserActivity
Wystąpienie jest dostarczane po wywołaniu AppDelegate
metody .ContinueUserActivity
W tym momencie należy skonfigurować interfejs użytkownika aplikacji i kontynuować daną aktywność.
Aby uzyskać więcej informacji, zobacz sekcję Implementowanie przekazywania poniżej.
Włączanie przekazywania w aplikacji platformy Xamarin
Ze względu na wymagania dotyczące zabezpieczeń nałożone przez handoff, aplikacja platformy Xamarin.iOS korzystająca z platformy Handoff musi być prawidłowo skonfigurowana zarówno w portalu dla deweloperów firmy Apple, jak i w pliku projektu Xamarin.iOS.
Należy wykonać następujące czynności:
Kliknij pozycję Certyfikaty, Identyfikatory i profile.
Jeśli jeszcze tego nie zrobiono, kliknij pozycję Identyfikatory i utwórz identyfikator aplikacji (np.
com.company.appname
), a następnie edytuj istniejący identyfikator.Upewnij się, że usługa iCloud została sprawdzona dla danego identyfikatora:
Zapisz zmiany.
Kliknij pozycję Tworzenie profilów> aprowizacji i utwórz nowy profil aprowizacji programowania dla aplikacji:
Pobierz i zainstaluj nowy profil aprowizacji lub użyj programu Xcode, aby pobrać i zainstalować profil.
Edytuj opcje projektu platformy Xamarin.iOS i upewnij się, że używasz właśnie utworzonego profilu aprowizacji:
Następnie zmodyfikuj plik Info.plist i upewnij się, że używasz identyfikatora aplikacji użytego do utworzenia profilu aprowizacji:
Przewiń do sekcji Tryby tła i sprawdź następujące elementy:
Zapisz zmiany we wszystkich plikach.
Po zastosowaniu tych ustawień aplikacja jest teraz gotowa do uzyskiwania dostępu do interfejsów API platformy Handoff Framework. Aby uzyskać szczegółowe informacje na temat aprowizacji, zobacz przewodniki Device Provisioning and Provisioning Your App (Aprowizowanie urządzeń i aprowizowanie aplikacji ).
Implementowanie przekazywania
Działania użytkowników można kontynuować wśród aplikacji podpisanych przy użyciu tego samego identyfikatora zespołu deweloperów i obsługiwać ten sam typ działania. Zaimplementowanie przekazywania w aplikacji platformy Xamarin.iOS wymaga utworzenia obiektu aktywności użytkownika (w systemie UIKit
lub AppKit
), zaktualizowania stanu obiektu w celu śledzenia działania i kontynuowania działania na urządzeniu odbierającego.
Identyfikowanie działań użytkownika
Pierwszym krokiem implementacji handoff jest zidentyfikowanie typów działań użytkownika, które obsługuje aplikacja, i zobaczenie, które z tych działań są dobrymi kandydatami do kontynuacji na innym urządzeniu. Na przykład: aplikacja ToDo może obsługiwać edytowanie elementów jako jeden typ działania użytkownika i obsługiwać przeglądanie listy dostępnych elementów jako innej.
Aplikacja może utworzyć dowolną liczbę typów aktywności użytkownika, która jest wymagana dla dowolnej funkcji, którą udostępnia aplikacja. Dla każdego typu działania użytkownika aplikacja musi śledzić, kiedy rozpoczyna się i kończy działanie typu, i musi zachować aktualne informacje o stanie, aby kontynuować to zadanie na innym urządzeniu.
Działania użytkownika mogą być kontynuowane w dowolnej aplikacji podpisanej przy użyciu tego samego identyfikatora zespołu bez żadnego mapowania jeden do jednego między wysyłaniem i odbieraniem aplikacji. Na przykład dana aplikacja może utworzyć cztery różne typy działań, które są używane przez różne, poszczególne aplikacje na innym urządzeniu. Jest to typowe wystąpienie między wersją aplikacji dla komputerów Mac (która może mieć wiele funkcji i funkcji) i aplikacjami systemu iOS, gdzie każda aplikacja jest mniejsza i koncentruje się na konkretnym zadaniu.
Tworzenie identyfikatorów typów działań
Identyfikator typu działania to krótki ciąg dodany do NSUserActivityTypes
tablicy pliku Info.plist aplikacji używany do unikatowego identyfikowania danego typu działania użytkownika. W tablicy będzie znajdować się jeden wpis dla każdego działania obsługiwanego przez aplikację. Firma Apple sugeruje użycie odwrotnej notacji w stylu DNS dla identyfikatora typu działania, aby uniknąć kolizji. Na przykład: com.company-name.appname.activity
w przypadku określonych działań opartych na aplikacji lub com.company-name.activity
działań, które mogą być uruchamiane w wielu aplikacjach.
Identyfikator typu działania jest używany podczas tworzenia NSUserActivity
wystąpienia do identyfikowania typu działania. Gdy działanie będzie kontynuowane na innym urządzeniu, typ działania (wraz z identyfikatorem zespołu aplikacji) określa, która aplikacja ma być uruchamiana, aby kontynuować działanie.
Na przykład utworzymy przykładową aplikację o nazwie MonkeyBrowser. Ta aplikacja będzie wyświetlać cztery karty, z których każdy ma inny adres URL otwarty w widoku przeglądarki internetowej. Użytkownik będzie mógł kontynuować dowolną kartę na innym urządzeniu z systemem iOS z uruchomioną aplikacją.
Aby utworzyć wymagane identyfikatory typów działań do obsługi tego zachowania, zmodyfikuj plik Info.plist i przejdź do widoku Źródło . NSUserActivityTypes
Dodaj klucz i utwórz następujące identyfikatory:
Utworzyliśmy cztery nowe identyfikatory typów działań, po jednym dla każdej karty w przykładowej aplikacji MonkeyBrowser . Podczas tworzenia własnych aplikacji zastąp zawartość NSUserActivityTypes
tablicy identyfikatorami typów działań specyficznymi dla działań, które obsługuje aplikacja.
Śledzenie zmian aktywności użytkownika
Podczas tworzenia nowego wystąpienia klasy określimy NSUserActivityDelegate
wystąpienie NSUserActivity
do śledzenia zmian stanu działania. Na przykład poniższy kod może służyć do śledzenia zmian stanu:
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
}
}
Metoda jest wywoływana UserActivityReceivedData
, gdy strumień kontynuacji odebrał dane z urządzenia wysyłającego. Aby uzyskać więcej informacji, zobacz sekcję Obsługa kontynuacji Strumienie poniżej.
Metoda jest wywoływana UserActivityWasContinued
, gdy inne urządzenie przejęło działanie z bieżącego urządzenia. W zależności od typu działania, takiego jak dodanie nowego elementu do listy zadań do wykonania, aplikacja może wymagać przerwania działania na urządzeniu wysyłającym.
Metoda jest wywoływana UserActivityWillSave
przed zapisaną i zsynchronizowaną ze wszystkimi zmianami działania na urządzeniach dostępnych lokalnie. Tej metody można użyć do wprowadzania jakichkolwiek zmian w ostatniej chwili we UserInfo
właściwości NSUserActivity
wystąpienia przed wysłaniem.
Tworzenie wystąpienia NSUserActivity
Każde działanie, które aplikacja chce zapewnić możliwość kontynuowania pracy na innym urządzeniu, musi być hermetyzowane w wystąpieniu NSUserActivity
. Aplikacja może tworzyć dowolną liczbę działań, a charakter tych działań zależy od funkcjonalności i funkcji danej aplikacji. Na przykład aplikacja poczty e-mail może utworzyć jedno działanie do tworzenia nowej wiadomości, a drugie do czytania wiadomości.
W naszej przykładowej aplikacji jest tworzony nowy NSUserActivity
za każdym razem, gdy użytkownik wprowadza nowy adres URL w jednym z kart widoku przeglądarki internetowej. Poniższy kod przechowuje stan danej karty:
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 ();
Tworzy nowy NSUserActivity
przy użyciu jednego z utworzonych powyżej typów działań użytkownika i udostępnia czytelny dla człowieka tytuł działania. Dołącza ono do wystąpienia utworzonego NSUserActivityDelegate
powyżej, aby obserwować zmiany stanu i informuje system iOS, że to działanie użytkownika jest bieżącym działaniem.
Wypełnianie słownika UserInfo
Jak widzieliśmy powyżej, UserInfo
właściwość NSUserActivity
klasy jest NSDictionary
par klucz-wartość używana do definiowania stanu danego działania. Wartości przechowywane w pliku UserInfo
muszą być jednym z następujących typów: NSArray
, , NSData
, NSDate
NSNumber
NSNull
NSSet
NSDictionary
NSString
lub .NSURL
NSURL
wartości danych, które wskazują dokumenty w usłudze iCloud, zostaną automatycznie dostosowane tak, aby wskazywały te same dokumenty na urządzeniu odbieranym.
W powyższym przykładzie utworzyliśmy NSMutableDictionary
obiekt i wypełniliśmy go pojedynczym kluczem, podając adres URL, który był obecnie wyświetlany przez użytkownika na danej karcie. Metoda AddUserInfoEntries
działania użytkownika została użyta do zaktualizowania działania przy użyciu danych, które zostaną użyte do przywrócenia działania na urządzeniu odbierającego:
// Update the activity when the tab's URL changes
var userInfo = new NSMutableDictionary ();
userInfo.Add (new NSString ("Url"), new NSString (url));
UserActivity.AddUserInfoEntries (userInfo);
Firma Apple sugeruje utrzymywanie informacji wysyłanych do najcięższego minimum, aby upewnić się, że działanie jest wysyłane w odpowiednim czasie do urządzenia odbierającego. Jeśli wymagane są większe informacje, takie jak obraz dołączony do dokumentu musi zostać wysłany, należy użyć Strumienie kontynuacji. Aby uzyskać więcej informacji, zobacz sekcję Obsługa kontynuacji Strumienie poniżej.
Kontynuowanie działania
Przekazywanie automatycznie informuje lokalne urządzenia z systemami iOS i OS X, które znajdują się w fizycznej odległości od urządzenia źródłowego i zalogowały się do tego samego konta w usłudze iCloud, o dostępności ciągłych działań użytkownika. Jeśli użytkownik zdecyduje się kontynuować działanie na nowym urządzeniu, system uruchomi odpowiednią aplikację (na podstawie identyfikatora zespołu i typu działania) i informacje, AppDelegate
które muszą wystąpić kontynuacja.
Najpierw metoda jest wywoływana, aby aplikacja mogła poinformować użytkownika, WillContinueUserActivityWithType
że kontynuacja ma się rozpocząć. W pliku AppDelegate.cs przykładowej aplikacji użyjemy następującego kodu, aby obsłużyć uruchamianie kontynuacji:
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;
}
W powyższym przykładzie każdy kontroler widoku rejestruje się w AppDelegate
obiekcie i ma publiczną PreparingToHandoff
metodę, która wyświetla wskaźnik aktywności i komunikat informujący użytkownika, że działanie ma zostać przekazane bieżącemu urządzeniu. Przykład:
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...");
}
Element ContinueUserActivity
zostanie wezwany AppDelegate
, aby rzeczywiście kontynuować daną aktywność. Ponownie z naszej przykładowej aplikacji:
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;
}
Publiczna PerformHandoff
metoda każdego kontrolera widoku faktycznie preformuje przekazanie i przywraca działanie na bieżącym urządzeniu. W przypadku przykładu wyświetla ten sam adres URL na danej karcie, którą użytkownik przeglądał na innym urządzeniu. Przykład:
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 ();
}
Metoda ContinueUserActivity
zawiera element UIApplicationRestorationHandler
, który można wywołać w celu wznowienia działania opartego na dokumencie lub odpowiedzi. Po wywołaniu należy przekazać NSArray
lub przywrócić obiekty do programu obsługi przywracania. Na przykład:
completionHandler (new NSObject[]{Tab4});
Dla każdego przekazanego obiektu zostanie wywołana jego RestoreUserActivityState
metoda. Każdy obiekt może następnie używać danych w słowniku UserInfo
do przywrócenia własnego stanu. Na przykład:
public override void RestoreUserActivityState (NSUserActivity activity)
{
base.RestoreUserActivityState (activity);
// Log activity
Console.WriteLine ("Restoring Activity {0}", activity.Title);
}
W przypadku aplikacji opartych na dokumentach, jeśli nie implementujesz ContinueUserActivity
metody lub zwraca false
wartość , UIKit
lub AppKit
może automatycznie wznowić działanie. Aby uzyskać więcej informacji, zobacz sekcję Obsługa przekazywania w aplikacjach opartych na dokumentach poniżej.
Niepowodzenie przekazywania w sposób wdzięczny
Ponieważ handoff opiera się na transmisji informacji między kolekcją luźno połączonych urządzeń z systemem iOS i OS X, proces transferu może czasami zakończyć się niepowodzeniem. Aplikacja powinna być zaprojektowana tak, aby obsługiwała te błędy bezpiecznie i informować użytkownika o wszelkich pojawiających się sytuacjach.
W przypadku awarii DidFailToContinueUserActivitiy
AppDelegate
metoda metody zostanie wywołana. Na przykład:
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);
}
Należy użyć podanej informacji NSError
, aby przekazać użytkownikowi informacje o awarii.
Przekazywanie aplikacji natywnej do przeglądarki internetowej
Użytkownik może chcieć kontynuować działanie bez konieczności zainstalowania odpowiedniej aplikacji natywnej na żądanym urządzeniu. W niektórych sytuacjach interfejs internetowy może zapewniać wymagane funkcje, a działanie nadal może być kontynuowane. Na przykład konto e-mail użytkownika może zapewnić internetowy podstawowy interfejs użytkownika do komponowania i odczytywania wiadomości.
Jeśli źródło, aplikacja natywna zna adres URL interfejsu internetowego (i wymaganą składnię identyfikującą dany element, który jest kontynuowany), może zakodować te informacje we WebpageURL
właściwości NSUserActivity
wystąpienia. Jeśli urządzenie odbierające nie ma zainstalowanej odpowiedniej aplikacji natywnej do obsługi kontynuacji, można wywołać podany interfejs internetowy.
Przekazywanie przeglądarki internetowej do aplikacji natywnej
Jeśli użytkownik używał interfejsu internetowego na urządzeniu źródłowym, a aplikacja natywna w odbierającym urządzeniu twierdzi, że część WebpageURL
domeny właściwości jest używana przez system, będzie używać tej aplikacji do obsługi kontynuacji. Nowe urządzenie otrzyma NSUserActivity
wystąpienie, które oznacza typ działania jako BrowsingWeb
i WebpageURL
będzie zawierać adres URL odwiedzany przez użytkownika, UserInfo
słownik będzie pusty.
Aby aplikacja brała udział w tym typie przekazywania, musi ona podawać domenę com.apple.developer.associated-domains
w uprawnieniach w formacie <service>:<fully qualified domain name>
(na przykład: activity continuation:company.com
).
Jeśli określona domena pasuje do WebpageURL
wartości właściwości, Handoff pobiera listę zatwierdzonych identyfikatorów aplikacji z witryny internetowej w tej domenie. Witryna internetowa musi podać listę zatwierdzonych identyfikatorów w podpisanym pliku JSON o nazwie apple-app-site-association (na przykład https://company.com/apple-app-site-association
).
Ten plik JSON zawiera słownik, który określa listę identyfikatorów aplikacji w formularzu <team identifier>.<bundle identifier>
. Na przykład:
{
"activitycontinuation": {
"apps": [ "YWBN8XTPBJ.com.company.FirstApp",
"YWBN8XTPBJ.com.company.SecondApp" ]
}
}
Aby podpisać plik JSON (tak, aby miał poprawność Content-Type
application/pkcs7-mime
), użyj aplikacji Terminal i openssl
polecenia z certyfikatem i kluczem wystawionym przez urząd certyfikacji zaufany przez system iOS (zobacz https://support.apple.com/kb/ht5012 listę). Na przykład:
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
Polecenie openssl
generuje podpisany plik JSON umieszczany w witrynie internetowej pod adresem URL skojarzenia apple-app-site-association . Na przykład:
https://example.com/apple-app-site-association.
Aplikacja otrzyma wszelkie działania, których WebpageURL
domena znajduje się w jej com.apple.developer.associated-domains
upoważnieniu. http
Obsługiwane są tylko protokoły ihttps
. Każdy inny protokół zgłosi wyjątek.
Obsługa przekazywania w aplikacjach opartych na dokumentach
Jak wspomniano powyżej, w systemach iOS i OS X aplikacje oparte na dokumentach będą automatycznie obsługiwać przekazywanie dokumentów opartych na usłudze iCloud, jeśli plik Info.plist aplikacji zawiera CFBundleDocumentTypes
klucz NSUbiquitousDocumentUserActivityType
. Na przykład:
<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>
W tym przykładzie ciąg jest inicjatorem odwrotnej aplikacji DNS o nazwie dołączonego działania. W przypadku wprowadzenia w ten sposób wpisy typu działania nie muszą być powtarzane w NSUserActivityTypes
tablicy pliku Info.plist .
Automatycznie utworzony obiekt aktywność użytkownika (dostępny za pośrednictwem właściwości dokumentu UserActivity
) może być przywoływały inne obiekty w aplikacji i używane do przywracania stanu kontynuacji. Na przykład w celu śledzenia zaznaczenia elementu i położenia dokumentu. Należy ustawić tę właściwość działań NeedsSave
na true
zawsze, gdy stan zmieni się i zaktualizuj UserInfo
słownik w metodzie UpdateUserActivityState
.
Właściwość UserActivity
może być używana z dowolnego wątku i jest zgodna z protokołem obserwującym klucz-wartość (KVO), dzięki czemu może służyć do synchronizowania dokumentu podczas przemieszczania się i z usługi iCloud. Właściwość UserActivity
zostanie unieważniona po zamknięciu dokumentu.
Aby uzyskać więcej informacji, zobacz dokumentację dotyczącą działań użytkowników firmy Apple w dokumentacji aplikacji opartych na dokumentach .
Obsługa przekazywania w osobach odpowiadających
Można skojarzyć osoby reagujące (dziedziczone z UIResponder
systemu iOS lub NSResponder
OS X) do działań, ustawiając ich UserActivity
właściwości. System automatycznie zapisuje UserActivity
właściwość w odpowiednim czasie, wywołując metodę obiektu UpdateUserActivityState
odpowiadającego w celu dodania bieżących danych do obiektu Aktywność użytkownika przy użyciu AddUserInfoEntriesFromDictionary
metody .
Obsługa Strumienie kontynuacji
Mogą to być sytuacje, w których ilość informacji wymaganych do kontynuowania działania nie może być wydajnie przenoszona przez początkowy ładunek przekazywania. W takich sytuacjach aplikacja odbierającą może ustanowić jeden lub więcej strumienia między samą aplikacją a aplikacją źródłową w celu transferu danych.
Aplikacja źródłowa ustawi SupportsContinuationStreams
właściwość NSUserActivity
wystąpienia na true
. Na przykład:
// 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 ();
Aplikacja odbierający może następnie wywołać metodę GetContinuationStreams
NSUserActivity
w pliku AppDelegate
, aby ustanowić strumień. Na przykład:
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;
}
Na urządzeniu źródłowym delegat aktywności użytkownika odbiera strumienie, wywołując jego DidReceiveInputStream
metodę w celu dostarczenia żądanych danych w celu kontynuowania aktywności użytkownika na wznawiającym urządzeniu.
Użyjesz elementu , NSInputStream
aby zapewnić dostęp tylko do odczytu do danych strumieniowych i NSOutputStream
zapewnić dostęp tylko do zapisu. Strumienie powinny być używane w sposób żądania i odpowiedzi, gdzie odbierana aplikacja żąda większej ilości danych, a źródłową aplikację ją udostępnia. Tak więc dane zapisane w strumieniu wyjściowym na urządzeniu źródłowym są odczytywane ze strumienia wejściowego na urządzeniu kontynuowanym i odwrotnie.
Nawet w sytuacjach, w których wymagany jest strumień kontynuacji, komunikacja między dwiema aplikacjami powinna być minimalna.
Aby uzyskać więcej informacji, zobacz dokumentację dotyczącą korzystania z kontynuacji Strumienie firmy Apple.
Najlepsze rozwiązania dotyczące przekazywania
Pomyślna implementacja bezproblemowej kontynuacji działania użytkownika za pośrednictwem przekazywania wymaga starannego projektowania ze względu na wszystkie zaangażowane składniki. Firma Apple sugeruje wdrożenie najlepszych rozwiązań dotyczących aplikacji obsługujących przekazywanie:
- Zaprojektuj działania użytkownika, aby wymagać najmniejszego ładunku możliwego do powiązania stanu działania, aby były kontynuowane. Większy ładunek, tym dłużej trwa kontynuowanie.
- Jeśli musisz przenieść duże ilości danych w celu pomyślnej kontynuacji, weź pod uwagę koszty związane z konfiguracją i obciążeniem sieci.
- Duża aplikacja dla komputerów Mac często tworzy działania użytkownika obsługiwane przez kilka mniejszych aplikacji specyficznych dla zadań na urządzeniach z systemem iOS. Różne wersje aplikacji i systemu operacyjnego powinny być zaprojektowane tak, aby działały dobrze lub bezproblemowo.
- Podczas określania typów działań użyj notacji odwrotnej DNS, aby uniknąć kolizji. Jeśli działanie jest specyficzne dla danej aplikacji, jej nazwa powinna zostać uwzględniona w definicji typu (na przykład
com.myCompany.myEditor.editing
). Jeśli działanie może działać w wielu aplikacjach, upuść nazwę aplikacji z definicji (na przykładcom.myCompany.editing
). - Jeśli aplikacja musi zaktualizować stan działania użytkownika (
NSUserActivity
) ustawNeedsSave
właściwość natrue
. W odpowiednim czasie funkcja Handoff wywoła metodę delegataUserActivityWillSave
, aby można było zaktualizowaćUserInfo
słownik zgodnie z potrzebami. - Ponieważ proces przekazywania może nie być natychmiast inicjowany na urządzeniu odbierającego, należy zaimplementować
AppDelegate
sWillContinueUserActivity
i poinformować użytkownika, że kontynuacja ma się rozpocząć.
Przykładowa aplikacja do przekazywania
Przykładem użycia funkcji Handoff w aplikacji platformy Xamarin.iOS jest przykładowa aplikacja MonkeyBrowser . Aplikacja ma cztery karty, których użytkownik może użyć do przeglądania internetu, z których każdy ma określony typ działania: Pogoda, Ulubione, Przerwy na kawę i Praca.
Na dowolnej karcie, gdy użytkownik wprowadzi nowy adres URL i naciśnie przycisk Przejdź , zostanie utworzona nowa NSUserActivity
karta zawierająca adres URL aktualnie przeglądający:
Jeśli na innym urządzeniu użytkownika jest zainstalowana aplikacja MonkeyBrowser , jest zalogowany do usługi iCloud przy użyciu tego samego konta użytkownika, znajduje się w tej samej sieci i blisko powyższego urządzenia, na ekranie głównym zostanie wyświetlone działanie przekazywania (w lewym dolnym rogu):
Jeśli użytkownik przeciągnie w górę ikonę Przekazywanie, aplikacja zostanie uruchomiona, a działanie użytkownika określone w elemecie NSUserActivity
będzie kontynuowane na nowym urządzeniu:
Gdy działanie użytkownika zostało pomyślnie wysłane do innego urządzenia Firmy Apple, urządzenie NSUserActivity
wysyłające otrzyma wywołanie UserActivityWasContinued
metody na nim NSUserActivityDelegate
, aby poinformować go, że działanie użytkownika zostało pomyślnie przeniesione na inne urządzenie.
Podsumowanie
W tym artykule przedstawiono wprowadzenie do platformy Handoff używanej do kontynuowania aktywności użytkownika między wieloma urządzeniami firmy Apple użytkownika. Następnie pokazano, jak włączyć i zaimplementować przekazywanie w aplikacji platformy Xamarin.iOS. Na koniec omówiła różne typy dostępnych kontynuacji handoff i najlepsze rozwiązania dotyczące przekazywania.