Předání v Xamarin.iOS

Tento článek popisuje práci s handoffem v aplikaci Xamarin.iOS pro přenos uživatelských aktivit mezi aplikacemi běžícími na jiných zařízeních uživatele.

Apple zavedl handoff v iOSu 8 a OS X Yosemite (10.10) a poskytl uživateli společný mechanismus pro přenos aktivit spuštěných na jednom ze svých zařízení, do jiného zařízení se stejnou aplikací nebo jinou aplikací, která podporuje stejnou aktivitu.

An example of performing a Handoff operation

Tento článek se rychle podíváme na povolení sdílení aktivit v aplikaci Xamarin.iOS a podrobně se podíváme na architekturu Handoff:

Informace o handoffu

Předání (označované také jako kontinuita) zavedl Apple v iOSu 8 a OS X Yosemite (10.10) jako způsob, jak uživatel zahájit aktivitu na jednom ze svých zařízení (iOS nebo Mac) a pokračovat v této stejné aktivitě na jiném ze svých zařízení (jak je identifikováno účtem iCloud uživatele).

Předání bylo rozšířeno v iOSu 9, aby podporovalo také nové rozšířené možnosti vyhledávání. Další informace najdete v naší dokumentaci k vylepšením vyhledávání .

Uživatel může například začít e-mail na svém iPhone a bezproblémově pokračovat v e-mailu na svém Macu se všemi stejnými informacemi o zprávě vyplněnými a kurzorem ve stejném umístění, kde ho nechal v iOSu.

Všechny vaše aplikace, které sdílejí stejné ID týmu, mají nárok na používání handoffu k pokračování uživatelských aktivit napříč aplikacemi, pokud jsou tyto aplikace dodávány buď prostřednictvím App Store iTunes, nebo podepsané registrovaným vývojářem (pro Mac, Enterprise nebo ad hoc aplikace).

Všechny NSDocument nebo UIDocument založené aplikace mají automaticky integrovanou podporu handoffu a vyžadují minimální změny podpory Handoff.

Pokračování uživatelských aktivit

Třída NSUserActivity (spolu s malými změnami UIKit a AppKit) poskytuje podporu pro definování aktivity uživatele, která může potenciálně pokračovat na jiném zařízení uživatele.

Aby se aktivita předávala do jiných zařízení uživatele, musí být zapouzdřená v instanci NSUserActivity, označená jako aktuální aktivita, mít datovou část nastavenou (data použitá k pokračování) a aktivita se pak musí přenést do tohoto zařízení.

Předání předává úplné minimum informací, aby se definovala aktivita, která se má pokračovat, s většími datovými pakety synchronizovanými přes iCloud.

Na přijímajícím zařízení obdrží uživatel oznámení, že aktivita je k dispozici pro pokračování. Pokud se uživatel rozhodne pokračovat v aktivitě na novém zařízení, spustí se zadaná aplikace (pokud ještě není spuštěná) a datová část z této NSUserActivity aktivity se použije k restartování aktivity.

An overview of Continuing User Activities

K pokračování mají nárok jenom aplikace, které sdílejí stejné ID týmu pro vývojáře a reagují na daný typ aktivity . Aplikace definuje typy aktivit, které podporuje pod NSUserActivityTypes klíčem souboru Info.plist . V takovém případě další zařízení zvolí aplikaci, která bude pokračovat na základě ID týmu, typu aktivity a volitelně názvu aktivity.

Přijímající aplikace používá informace ze slovníku's NSUserActivityUserInfo ke konfiguraci jeho uživatelského rozhraní a obnovení stavu dané aktivity, aby přechod byl pro koncového uživatele bezproblémový.

Pokud pokračování vyžaduje více informací, než je možné efektivně odesílat prostřednictvím aplikace NSUserActivity, může aplikace obnovení odeslat volání do původní aplikace a vytvořit jeden nebo více datových proudů pro přenos požadovaných dat. Pokud například aktivita upravovala velký textový dokument s více obrázky, streamování by vyžadovalo přenos informací potřebných k pokračování aktivity na přijímajícím zařízení. Další informace najdete v části Podpora pokračování Toky níže.

Jak je uvedeno výše, NSDocument nebo UIDocument založené aplikace mají automaticky integrovanou podporu handoff. Další informace najdete v části Podpůrné předání v části Document-Based Apps níže.

Třída NSUserActivity

Třída NSUserActivity je primárním objektem výměny handoff a slouží k zapouzdření stavu aktivity uživatele, která je k dispozici pro pokračování. Aplikace vytvoří instanci kopie NSUserActivity jakékoli aktivity, kterou podporuje, a chce pokračovat na jiném zařízení. Editor dokumentů by například vytvořil aktivitu pro každý aktuálně otevřený dokument. Pouze první dokument (zobrazený v okně nebo kartě frontmost) je ale aktuální aktivita a k dispozici pro pokračování.

Instance NSUserActivity je identifikována jeho ActivityType i Title vlastnostmi. Vlastnost slovníku UserInfo slouží k přenosu informací o stavu aktivity. NeedsSave Vlastnost nastavte, true pokud chcete opožděně načíst informace o stavu přes NSUserActivitydelegáta. AddUserInfoEntries Pomocí metody můžete sloučit nová data z jiných klientů do slovníku UserInfo podle potřeby, aby se zachoval stav aktivity.

NSUserActivityDelegate – třída

Slouží NSUserActivityDelegate k udržování informací ve slovníku NSUserActivityUserInfo aktuální a synchronizované s aktuálním stavem aktivity. Pokud systém potřebuje informace v aktivitě, které se mají aktualizovat (například před pokračováním na jiném zařízení), zavolá UserActivityWillSave metodu delegáta.

Budete muset implementovat metodu UserActivityWillSave a provést všechny změny NSUserActivity (například UserInfo, Titleatd.), aby se zajistilo, že stále odráží stav aktuální aktivity. Když systém volá metodu UserActivityWillSave , NeedsSave příznak se vymaže. Pokud upravíte některé z vlastností dat aktivity, budete muset znovu nastavit NeedsSavetrue .

Místo použití UserActivityWillSave výše uvedené metody můžete volitelně mít UIKit nebo AppKit spravovat aktivitu uživatele automaticky. Uděláte to tak, že nastavíte vlastnost objektu UserActivity reagovače a implementujete metodu UpdateUserActivityState . Další informace najdete v části Podpůrné předání v části Odpovědi níže.

Podpora rozhraní App Framework

Jak UIKit (iOS) tak AppKit (OS X) poskytují integrovanou podporu handoffu v nástroji NSDocument, Responder (NSResponderUIResponder/) a AppDelegate třídách. Zatímco každý operační systém implementuje handoff mírně jinak, základní mechanismus a rozhraní API jsou stejné.

Aktivity uživatelů v aplikacích Document-Based

Aplikace pro iOS a OS X založené na dokumentech automaticky podporují integrované funkce Handoff. Pokud chcete tuto podporu aktivovat, budete muset přidat NSUbiquitousDocumentUserActivityType klíč a hodnotu pro každou CFBundleDocumentTypes položku v souboru Info.plist aplikace.

Pokud je tento klíč k dispozici, a NSDocumentUIDocument automaticky vytvoří NSUserActivity instance pro dokumenty založené na iCloudu zadaného typu. Budete muset zadat typ aktivity pro každý typ dokumentu, který aplikace podporuje, a více typů dokumentů může používat stejný typ aktivity. Vlastnost NSDocumentUIDocument vlastnosti vlastnosti NSUserActivity se automaticky naplní UserInfo hodnotou jejich FileURL vlastnosti.

V OS X se spravovaná a přidružená AppKit k reagujícím automaticky stane aktuální aktivitou, NSUserActivity když se okno dokumentu stane hlavním oknem. Pro objekty spravované v NSUserActivityUIKitiOSu musíte buď explicitně zavolat BecomeCurrent metodu, nebo mít vlastnost dokumentu UserActivity nastavenou UIViewController v případě, že se aplikace dostane do popředí.

AppKit automaticky obnoví libovolnou UserActivity vlastnost vytvořenou tímto způsobem v OS X. K tomu dochází v případě, ContinueUserActivity že metoda vrátí false nebo pokud není neplementovaná. V takovém případě se dokument otevře metodou OpenDocument metody NSDocumentController a pak obdrží RestoreUserActivityState volání metody.

Další informace najdete v části Podpůrné předání v části Document-Based Apps níže.

Aktivity uživatelů a reagující

Aktivitu UIKit uživatele můžete AppKit automaticky spravovat, pokud ji nastavíte jako vlastnost objektu UserActivity reagovače. Pokud byl stav změněn, budete muset nastavit NeedsSave vlastnost reagátora UserActivity na true. Systém automaticky uloží UserActivity , pokud je to potřeba, po poskytnutí doby reakce na aktualizaci stavu voláním jeho UpdateUserActivityState metody.

Pokud několik reagujících sdílí jednu NSUserActivity instanci, obdrží UpdateUserActivityState zpětné volání, když systém aktualizuje objekt aktivity uživatele. Odpovědět musí volat metodu AddUserInfoEntries , aby aktualizoval NSUserActivityslovník 's UserInfo , aby odrážel aktuální stav aktivity v tomto okamžiku. Slovník UserInfo je před každým UpdateUserActivityState voláním vymazán.

Pokud chcete zrušit přidružení k aktivitě, může odpovědět jeho UserActivity vlastnost na nullhodnotu . Pokud spravovaná NSUserActivity instance architektury aplikace nemá přidružené další reagující nebo dokumenty, automaticky se zneplatní.

Další informace najdete v části Podpůrné předání v části Odpovědi níže.

Aktivity uživatelů a AppDelegate

Vaše aplikace AppDelegate je jejím primárním vstupním bodem při zpracování pokračování předání. Když uživatel odpoví na oznámení o předání, spustí se příslušná aplikace (pokud ještě není spuštěná) a WillContinueUserActivityWithType zavolá se metoda volání AppDelegate . V tomto okamžiku by měla aplikace informovat uživatele, že pokračování začíná.

Instance NSUserActivity se doručí při AppDelegatevolání metody ' ContinueUserActivity . V tomto okamžiku byste měli nakonfigurovat uživatelské rozhraní aplikace a pokračovat v dané aktivitě.

Další informace najdete v části Implementace handoffu níže.

Povolení předání v aplikaci Xamarin

Vzhledem k požadavkům na zabezpečení uloženým handoffem musí být aplikace Xamarin.iOS, která používá architekturu Handoff, správně nakonfigurovaná na portálu Apple Developer Portal i v souboru projektu Xamarin.iOS.

Postupujte následovně:

  1. Přihlaste se k portálu Apple Developer Portal.

  2. Klikněte na certifikáty, profily identifikátorů&.

  3. Pokud jste to ještě neudělali, klikněte na Identifikátory a vytvořte ID aplikace (např com.company.appname. ), jinak upravte stávající ID.

  4. Ujistěte se, že je služba iCloud zaškrtnutá pro dané ID:

    Enable the iCloud service for the given ID

  5. Uložte provedené změny.

  6. Klikněte na ZřizováníprofilůDevelopment> a vytvořte pro vás nový profil zřizování vývoje:

    Create a new development provisioning profile for the app

  7. Stáhněte a nainstalujte nový zřizovací profil nebo použijte Xcode ke stažení a instalaci profilu.

  8. Upravte možnosti projektu Xamarin.iOS a ujistěte se, že používáte profil zřizování, který jste právě vytvořili:

    Select the provisioning profile just created

  9. Dále upravte soubor Info.plist a ujistěte se, že používáte ID aplikace, které se použilo k vytvoření zřizovacího profilu:

    Set App ID

  10. Přejděte do části Režimy pozadí a zkontrolujte následující položky:

    Enable the required background modes

  11. Uložte změny do všech souborů.

Díky těmto nastavením je teď aplikace připravená pro přístup k rozhraním API rozhraní Handoff Framework. Podrobné informace o zřizování najdete v našich průvodcích zřizováním a zřizováním aplikací .

Implementace předání

Aktivity uživatelů můžete pokračovat mezi aplikacemi, které jsou podepsané stejným ID týmu pro vývojáře a podporují stejný typ aktivity. Implementace handoff v aplikaci Xamarin.iOS vyžaduje, abyste vytvořili objekt aktivity uživatele (buď v UIKit nebo AppKit), aktualizovali stav objektu tak, aby sledoval aktivitu a pokračovali v aktivitě na přijímajícím zařízení.

Identifikace aktivit uživatelů

Prvním krokem při implementaci handoffu je identifikace typů aktivit uživatelů, které vaše aplikace podporuje, a zjištění, které z těchto aktivit jsou vhodnými kandidáty na pokračování na jiném zařízení. Aplikace ToDo může například podporovat úpravy položek jako jednoho typu aktivity uživatele a podporovat procházení seznamu dostupných položek jako jiného.

Aplikace může vytvořit libovolný počet typů aktivit uživatelů, které aplikace poskytuje. U každého typu aktivity uživatele bude aplikace muset sledovat, kdy aktivita typu začíná a končí, a musí udržovat aktuální informace o stavu, aby tato úloha pokračovala na jiném zařízení.

Aktivity uživatelů můžou pokračovat v jakékoli aplikaci podepsané pomocí stejného ID týmu bez mapování 1:1 mezi odesílajícími a přijímajícími aplikacemi. Například daná aplikace může vytvořit čtyři různé typy aktivit, které jsou spotřebovány různými aplikacemi na jiném zařízení. Jedná se o běžný výskyt mezi verzí aplikace pro Mac (která může mít mnoho funkcí a funkcí) a aplikacemi pro iOS, kde je každá aplikace menší a zaměřená na konkrétní úlohu.

Vytváření identifikátorů typu aktivity

Identifikátor typu aktivity je krátký řetězec přidaný do NSUserActivityTypes pole souboru Info.plist aplikace, který slouží k jedinečné identifikaci daného typu aktivity uživatele. Pro každou aktivitu, kterou aplikace podporuje, bude v poli jedna položka. Apple navrhuje použít pro identifikátor typu aktivity zápis typu aktivity reverzní dns, aby nedocházelo ke kolizím. Například: com.company-name.appname.activity pro konkrétní aktivity založené na aplikacích nebo com.company-name.activity pro aktivity, které můžou běžet napříč více aplikacemi.

Identifikátor typu aktivity se používá při vytváření NSUserActivity instance k identifikaci typu aktivity. Když aktivita pokračuje na jiném zařízení, typ aktivity (spolu s ID týmu aplikace) určuje, která aplikace se má spustit, aby pokračovala v aktivitě.

Jako příklad vytvoříme ukázkovou aplikaci s názvem MonkeyBrowser (stáhněte si ji zde). Tato aplikace bude prezentovat čtyři karty, z nichž každá má otevřenou jinou adresu URL ve webovém zobrazení prohlížeče. Uživatel bude moct pokračovat na libovolné kartě na jiném zařízení s iOSem, na kterém běží aplikace.

Chcete-li vytvořit požadované identifikátory typu aktivity pro podporu tohoto chování, upravte soubor Info.plist a přepněte do zobrazení Zdroj . NSUserActivityTypes Přidejte klíč a vytvořte následující identifikátory:

The NSUserActivityTypes key and required identifiers in the plist editor

Vytvořili jsme čtyři nové identifikátory typu aktivity, jeden pro každou kartu v ukázkové aplikaci MonkeyBrowser . Při vytváření vlastních aplikací nahraďte obsah NSUserActivityTypes pole identifikátory typu aktivity specifické pro aktivity, které vaše aplikace podporuje.

Sledování změn aktivit uživatelů

Když vytvoříme novou instanci NSUserActivity třídy, určíme NSUserActivityDelegate instanci, která bude sledovat změny stavu aktivity. Následující kód můžete použít například ke sledování změn stavu:

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 UserActivityReceivedData se volá, když stream pro pokračování přijal data z odesílajícího zařízení. Další informace najdete v části Podpora pokračování Toky níže.

Metoda UserActivityWasContinued se volá, když jiné zařízení převzalo aktivitu z aktuálního zařízení. V závislosti na typu aktivity, jako je přidání nové položky do seznamu úkolů, může aplikace aktivitu na odesílajícím zařízení přerušit.

Tato UserActivityWillSave metoda se volá před uložením a synchronizací jakýchkoli změn aktivity napříč místně dostupnými zařízeními. Tuto metodu můžete použít k provedení jakýchkoli změn UserInfo vlastnosti instance za poslední minutu NSUserActivity před odesláním.

Vytvoření instance NSUserActivity

Každá aktivita, kterou vaše aplikace chce poskytnout možnost pokračovat na jiném zařízení, musí být zapouzdřena v NSUserActivity instanci. Aplikace může vytvořit libovolný počet aktivit a povaha těchto aktivit závisí na funkcích a funkcích dané aplikace. E-mailová aplikace může například vytvořit jednu aktivitu pro vytvoření nové zprávy a druhou pro čtení zprávy.

V naší ukázkové aplikaci se vytvoří nový NSUserActivity pokaždé, když uživatel zadá novou adresu URL v jednom ze zobrazení webového prohlížeče s kartami. Následující kód ukládá stav dané 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 ();

Vytvoří nový NSUserActivity pomocí některého z výše vytvořených typů aktivity uživatele a poskytne pro aktivitu čitelný název člověka. Připojí se k instanci NSUserActivityDelegate vytvořené výše a sleduje změny stavu a informuje iOS, že tato aktivita uživatele je aktuální aktivita.

Naplnění slovníku UserInfo

Jak jsme viděli výše, UserInfo vlastnost NSUserActivity třídy je NSDictionary dvojice klíč-hodnota sloužící k definování stavu dané aktivity. Hodnoty uložené v UserInfo jednom z následujících typů: NSArray, , NSDataNSDate, NSDictionary, , NSNull, , NSNumber, , NSSet, , , NSStringnebo NSURL. NSURL hodnoty dat, které ukazují na dokumenty iCloudu, se automaticky upraví tak, aby ukazovaly na stejné dokumenty na přijímajícím zařízení.

V předchozím příkladu jsme vytvořili NSMutableDictionary objekt a naplnili ho jedním klíčem s adresou URL, kterou si uživatel právě prohlíží na dané kartě. Metoda AddUserInfoEntries aktivity uživatele se použila k aktualizaci aktivity daty, která se použijí k obnovení aktivity na přijímajícím zařízení:

// 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 navrhuje zachovat informace odeslané na nejmenší minimum, aby se zajistilo, že se aktivita odešle včas do přijímajícího zařízení. Pokud se vyžadují větší informace, třeba obrázek připojený k dokumentu, který je potřeba upravit, je potřeba odeslat, měli byste použít funkci Pokračování Toky. Další podrobnosti najdete v části Podpůrné pokračování Toky níže.

Pokračování aktivity

Předání automaticky informuje místní zařízení s iOSem a OS X, která jsou ve fyzické blízkosti původního zařízení a přihlásí se ke stejnému účtu iCloudu, o dostupnosti kontinuovatelných aktivit uživatelů. Pokud se uživatel rozhodne pokračovat v aktivitě na novém zařízení, systém spustí příslušnou aplikaci (na základě ID týmu a typu aktivity) a informace o tom AppDelegate , že se má pokračovat.

Nejprve se WillContinueUserActivityWithType volá metoda, aby aplikace mohla informovat uživatele, že pokračování se chystá začít. V souboru AppDelegate.cs ukázkové aplikace používáme následující kód pro zpracování pokračování:

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;
}

Ve výše uvedeném příkladu se každý kontroler zobrazení registruje s AppDelegate veřejnou PreparingToHandoff metodou, která zobrazuje indikátor aktivity a zprávu s oznámením, že se aktivita chystá předat aktuálnímu zařízení. Příklad:

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 Bude ContinueUserActivity volána, aby skutečně pokračovala v dané aktivitě. Znovu z naší ukázkové aplikace:

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;
}

Veřejná PerformHandoff metoda každého kontroleru zobrazení skutečně předformuluje předání a obnoví aktivitu na aktuálním zařízení. V případě příkladu zobrazí stejnou adresu URL na dané kartě, na které uživatel procházel na jiném zařízení. Příklad:

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 ();

}

Tato ContinueUserActivity metoda obsahuje UIApplicationRestorationHandler , že můžete volat obnovení aktivity založené na dokumentech nebo respondentech. Při zavolání budete muset předat NSArray nebo obnovitelné objekty obslužné rutině obnovení. Příklad:

completionHandler (new NSObject[]{Tab4});

Pro každý předaný objekt bude volána jeho RestoreUserActivityState metoda. Každý objekt pak může data ve slovníku UserInfo použít k obnovení vlastního stavu. Příklad:

public override void RestoreUserActivityState (NSUserActivity activity)
{
    base.RestoreUserActivityState (activity);

    // Log activity
    Console.WriteLine ("Restoring Activity {0}", activity.Title);
}

Pokud u dokumentových aplikací neimplementujete metodu ContinueUserActivity nebo ji vrátíte false, UIKit nebo AppKit můžete aktivitu obnovit automaticky. Další informace najdete v části Podpůrné předání v části Document-Based Apps níže.

Neúspěšné handoff elegantně

Vzhledem k tomu, že Handoff spoléhá na přenos informací mezi volně připojenými zařízeními s iOSem a OS X, může proces přenosu někdy selhat. Aplikaci byste měli navrhnout tak, aby zpracovávala tyto chyby elegantně a informovala uživatele o všech situacích, které nastanou.

V případě selhání DidFailToContinueUserActivitiy bude volána metoda metody AppDelegate . Příklad:

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);
}

Zadané informace byste měli použít NSError k poskytnutí informací uživateli o selhání.

Handoff nativní aplikace pro webový prohlížeč

Uživatel může chtít pokračovat v aktivitě, aniž by měl na požadovaném zařízení nainstalovanou příslušnou nativní aplikaci. V některýchsituacích E-mailový účet uživatele může například poskytnout webové uživatelské rozhraní pro psaní a čtení zpráv.

Pokud původní, nativní aplikace zná adresu URL webového rozhraní (a požadovanou syntaxi pro identifikaci dané položky, která pokračuje), může tyto informace zakódovat ve WebpageURL vlastnosti NSUserActivity instance. Pokud přijímající zařízení nemá nainstalovanou odpovídající nativní aplikaci pro zpracování pokračování, je možné volat poskytnuté webové rozhraní.

Předání webového prohlížeče do nativní aplikace

Pokud uživatel používal webové rozhraní na původním zařízení a nativní aplikace na přijímajícím zařízení deklaruje část WebpageURL domény vlastnosti, systém použije tuto aplikaci, která bude pokračovat. Nové zařízení obdrží NSUserActivity instanci, která označí typ aktivity jako BrowsingWeb a WebpageURL bude obsahovat adresu URL, kterou uživatel navštívil, UserInfo slovník bude prázdný.

Aby se aplikace zúčastnila tohoto typu předání, musí si doménu nárokovat ve com.apple.developer.associated-domains formátu <service>:<fully qualified domain name> (například: activity continuation:company.com).

Pokud zadaná doména odpovídá WebpageURL hodnotě vlastnosti, handoff stáhne seznam schválených ID aplikací z webu v této doméně. Web musí obsahovat seznam schválených ID v podepsaném souboru JSON s názvem apple-app-site-association (například https://company.com/apple-app-site-association).

Tento soubor JSON obsahuje slovník, který určuje seznam ID aplikací ve formuláři <team identifier>.<bundle identifier>. Příklad:

{
    "activitycontinuation": {
        "apps": [    "YWBN8XTPBJ.com.company.FirstApp",
            "YWBN8XTPBJ.com.company.SecondApp" ]
    }
}

Pokud chcete podepsat soubor JSON (aby měl správnou hodnotu Content-Typeapplication/pkcs7-mime), použijte terminálovouopenssl aplikaci a příkaz s certifikátem a klíčem vydaným certifikační autoritou důvěryhodnou pro iOS (viz https://support.apple.com/kb/ht5012 seznam). Příklad:

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

Příkaz openssl vypíše podepsaný soubor JSON, který umístíte na svůj web na adresu URL přidružení apple-app-site-association . Příklad:

https://example.com/apple-app-site-association.

Aplikace obdrží jakoukoli aktivitu, jejíž WebpageURL doména je ve svém com.apple.developer.associated-domains nároku. Podporují se pouze protokoly httphttps , všechny ostatní protokoly vyvolá výjimku.

Podpora předání v aplikacích Document-Based

Jak je uvedeno výše, aplikace založené na dokumentech na iOS a OS X automaticky podporují předání dokumentů založených na iCloudu, pokud soubor Info.plist aplikace obsahuje CFBundleDocumentTypes klíč NSUbiquitousDocumentUserActivityType. Příklad:

<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>

V tomto příkladu je řetězec zpětného návrhu aplikace DNS s názvem připojené aktivity. Pokud je zadán tímto způsobem, položky typu aktivity se nemusí opakovat v NSUserActivityTypes poli souboru Info.plist .

Automaticky vytvořený objekt aktivity uživatele (dostupný prostřednictvím vlastnosti dokumentu UserActivity ) lze odkazovat na jiné objekty v aplikaci a použít k obnovení stavu při pokračování. Pokud chcete například sledovat výběr položek a umístění dokumentu. Tuto vlastnost aktivity NeedsSave je třeba nastavit vždy true , když se stav změní a aktualizuje UserInfo slovník v UpdateUserActivityState metodě.

Vlastnost UserActivity lze použít z libovolného vlákna a odpovídá protokolu KVO (key-value observing), takže se dá použít k zachování synchronizovaného dokumentu při přesouvání a z iCloudu. Vlastnost UserActivity bude při zavření dokumentu neplatná.

Další informace najdete v dokumentaci k Document-Based Apps v podpoře aktivit uživatelů společnosti Apple.

Podpora předání v respondérech

K aktivitám můžete přidružit reagující (zděděné z UIResponder iOSu nebo NSResponder OS X) nastavením jejich UserActivity vlastností. Systém automaticky uloží UserActivity vlastnost v příslušných časech a zavolá metodu respondenta UpdateUserActivityState , která přidá aktuální data do objektu AddUserInfoEntriesFromDictionary Aktivity uživatele pomocí metody.

Podpora Toky pokračování

Může se jednat o situace, kdy množství informací potřebných k pokračování aktivity nemůže být efektivně přeneseno počáteční datovou částí handoff. V těchto situacích může přijímající aplikace vytvořit jeden nebo více datových proudů mezi sebou a původní aplikací pro přenos dat.

Původní aplikace nastaví SupportsContinuationStreams vlastnost NSUserActivity instance na true. Příklad:

// 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 ();

Přijímající aplikace pak může volat GetContinuationStreams metodu NSUserActivity v jejím AppDelegate rámci pro navázání datového proudu. Příklad:

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 původním zařízení obdrží delegát aktivity uživatele datové proudy voláním jeho DidReceiveInputStream metody, aby poskytl data požadovaná k pokračování aktivity uživatele na zařízení.

Použijete k NSInputStream poskytování přístupu jen pro čtení k datům datového proudu a NSOutputStream k zajištění přístupu jen pro zápis. Streamy by se měly používat způsobem požadavku a odpovědi, kde přijímající aplikace požaduje více dat a původní aplikace je poskytuje. Aby se data zapsaná do výstupního streamu na původním zařízení načítala ze vstupního datového proudu na pokračujícím zařízení a naopak.

I v situacích, kdy je vyžadován stream pro pokračování, by mezi těmito dvěma aplikacemi měla být minimálně komunikace.

Další informace najdete v dokumentaci k používání Toky pokračování společnosti Apple.

Osvědčené postupy pro předání

Úspěšná implementace bezproblémového pokračování aktivity uživatele prostřednictvím handoff vyžaduje pečlivý návrh kvůli všem zahrnutým komponentám. Apple navrhuje přijetí následujících osvědčených postupů pro aplikace s podporou handoffu:

  • Navrhněte aktivity uživatelů tak, aby vyžadovaly nejmenší datovou část, která může souviset se stavem aktivity, která se má pokračovat. Čím větší je datová část, tím déle trvá pokračování.
  • Pokud potřebujete pro úspěšné pokračování přenášet velké objemy dat, vezměte v úvahu náklady spojené s konfigurací a režií sítě.
  • U velké aplikace pro Mac je běžné vytvářet aktivity uživatelů, které zpracovává několik menších aplikací specifických pro úlohy na zařízeních s iOSem. Různé verze aplikací a operačních systémů by měly být navržené tak, aby dobře fungovaly společně nebo správně selhaly.
  • Při zadávání typů aktivit použijte zpětné zápisy DNS, abyste se vyhnuli kolizím. Pokud je aktivita specifická pro danou aplikaci, měla by být její název zahrnuta do definice typu (například com.myCompany.myEditor.editing). Pokud aktivita může fungovat napříč více aplikacemi, umístěte název aplikace z definice (například com.myCompany.editing).
  • Pokud vaše aplikace potřebuje aktualizovat stav aktivity uživatele (NSUserActivity) nastavit NeedsSave vlastnost na true. V příslušných časech handoff zavolá metodu delegáta UserActivityWillSave , abyste mohli podle potřeby aktualizovat UserInfo slovník.
  • Protože proces Handoff nemusí okamžitě inicializovat na přijímajícím zařízení, měli byste implementovat AppDelegate's WillContinueUserActivity a informovat uživatele, že pokračování se chystá spustit.

Příklad aplikace Handoff

Jako příklad použití Handoff v aplikaci Xamarin.iOS jsme do této příručky zahrnuli ukázkovou aplikaci MonkeyBrowser . Aplikace má čtyři karty, které může uživatel použít k procházení webu, z nichž každý má daný typ aktivity: Počasí, Oblíbené, Přestávka na kávu a Práce.

Když uživatel na libovolné kartě zadá novou adresu URL a klepne na tlačítko Přejít , vytvoří se pro ni nová NSUserActivity karta, která obsahuje adresu URL, kterou uživatel právě prochází:

Example Handoff App

Pokud má jiná zařízení uživatele nainstalovanou aplikaci MonkeyBrowser , je přihlášená k iCloudu pomocí stejného uživatelského účtu, je ve stejné síti a v těsné blízkosti výše uvedeného zařízení se aktivita Handoff zobrazí na domovské obrazovce (v levém dolním rohu):

The Handoff Activity displayed on the home screen in the lower left hand corner

Pokud uživatel přetáhne ikonu Handoff nahoru, aplikace se spustí a aktivita uživatele zadaná v NSUserActivity novém zařízení bude pokračovat:

The User Activity continued on the new device

Když byla aktivita uživatele úspěšně odeslána na jiné zařízení Apple, odesílající zařízení NSUserActivity obdrží volání metody UserActivityWasContinued , NSUserActivityDelegate aby věděla, že aktivita uživatele byla úspěšně přenesena do jiného zařízení.

Souhrn

Tento článek poskytl úvod do architektury Handoff, která slouží k pokračování aktivity uživatele mezi více zařízeními Apple uživatele. Dále ukázala, jak povolit a implementovat Handoff v aplikaci Xamarin.iOS. Nakonec probral různé typy pokračování Handoff, které jsou k dispozici, a osvědčené postupy handoff.