Předání v Xamarin.iOS

Tento článek popisuje práci s předáním v aplikaci Xamarin.iOS za účelem přenosu uživatelských aktivit mezi aplikacemi spuštěnými na jiných zařízeních uživatele.

Apple představil Handoff v iOSu 8 a OS X Yosemite (10.10), aby uživateli poskytl 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á na povolení sdílení aktivit v aplikaci Xamarin.iOS a podrobně se zabývá architekturou Handoff:

Informace o handoffu

Předání (označované také jako kontinuita) zavedl Apple v systémech iOS 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 ve stejné aktivitě na jiných zařízeních (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 spustit e-mail na svém i Telefon 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.

Jakékoli z vašich aplikací, které sdílejí stejné ID týmu, mají nárok na používání funkce Handoff k pokračování uživatelských aktivit v aplikacích, pokud jsou tyto aplikace doručovány prostřednictvím iTunes App Storu 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 handoffu.

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

Třída NSUserActivity (spolu s některými 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ředala jinému ze zařízení uživatele, musí být zapouzdřená v instanci NSUserActivity, označená jako aktuální aktivita, mít nastavenou datovou část (data použitá k provedení pokračování) a aktivita se pak musí přenést do tohoto zařízení.

Předání předá úplné minimum informací, aby bylo možné definovat aktivitu, která se má pokračovat, s většími datovými pakety, které se synchronizují 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 části 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 . Vzhledem k tomu vybere další zařízení aplikaci, která bude pokračovat na základě ID týmu, typu aktivity a volitelného názvu aktivity.

Přijímající aplikace používá informace ze slovníku NSUserActivity' UserInfo s ke konfiguraci uživatelského rozhraní a obnovení stavu dané aktivity tak, 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 NSUserActivityaplikace , 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 nebo NSDocumentUIDocument aplikace založené na funkcích, podporují funkce Handoff integrovanou. 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 přeje si pokračovat na jiném zařízení. Editor dokumentů například vytvoří aktivitu pro každý aktuálně otevřený dokument. Aktuální aktivita je ale k dispozici pouze frontmostní dokument (zobrazený v okně úplně na frontu nebo kartě).

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 prostřednictvím 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 v aktualizovaném a synchronizovaném stavu 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í), volá UserActivityWillSave metodu delegáta.

Budete muset implementovat metodu UserActivityWillSave a provést všechny změny NSUserActivity (například UserInfoTitle, atd.), 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ěkterou 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 respondéru a implementujete metodu UpdateUserActivityState . Další informace najdete v části Podpůrné předání v části Responders níže.

Podpora architektury aplikací

Jak UIKit (iOS) tak AppKit (OS X) poskytují integrovanou podporu handoffu NSDocumentv systémech , Responder () (UIResponder/NSResponder) a AppDelegate třídách. I když každý operační systém implementuje handoff trochu jinak, základní mechanismus a rozhraní API jsou stejné.

Aktivity uživatelů v dokumentových aplikacích

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. Obě NSDocument a UIDocument automaticky naplní UserInfo vlastnost NSUserActivityFileURL jeho hodnotou.

V OS X NSUserActivity se spravovaná a přidružená AppKit k respondentům automaticky stane aktuální aktivitou, když se okno dokumentu stane hlavním oknem. V iOSu musíte pro NSUserActivity objekty spravované UIKitmetodou volání BecomeCurrent buď explicitně, nebo mít vlastnost dokumentu UserActivity nastavenou UIViewController na, když se aplikace dostane do popředí.

AppKit automaticky obnoví všechny UserActivity vlastnosti vytvořené tímto způsobem v OS X. K tomu dochází v případě, ContinueUserActivity že metoda vrátí false nebo pokud je neplementovaná. V takovém případě je dokument otevřen 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 respondenti

AppKit Aktivitu UIKit uživatele můžete automaticky spravovat, pokud ji nastavíte jako vlastnost objektu UserActivity respondéru. Pokud byl stav změněn, budete muset nastavit NeedsSave vlastnost respondéru UserActivity na truehodnotu . Systém automaticky uloží UserActivity v případě potřeby po poskytnutí doby reakce na aktualizaci stavu voláním jeho UpdateUserActivityState metody.

Pokud více respondentů sdílí jednu NSUserActivity instanci, obdrží UpdateUserActivityState zpětné volání, když systém aktualizuje objekt aktivity uživatele. Respondér musí volat metodu AddUserInfoEntries , aby aktualizoval NSUserActivityslovník 's UserInfo , aby odrážel aktuální stav aktivity v tomto okamžiku. Slovník UserInfo se před každým UpdateUserActivityState voláním vymaže.

Chcete-li zrušit přidružení k aktivitě, může respondér nastavit jeho UserActivity vlastnost na null. 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 Responders 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í handoffu. Když uživatel odpoví na oznámení předání, spustí se příslušná aplikace (pokud ještě není spuštěná) a WillContinueUserActivityWithType zavolá se metoda AppDelegate . V tomto okamžiku by aplikace měla uživatele informovat, že pokračování začíná.

Instance NSUserActivity se doručí při AppDelegateContinueUserActivity zavolání metody . V tuto chvíli byste měli nakonfigurovat uživatelské rozhraní aplikace a pokračovat v dané aktivitě.

Další informace najdete v části Implementace předání níže.

Povolení předání v aplikaci Xamarin

Vzhledem k požadavkům na zabezpečení, které služba Handoff vyžaduje, musí být aplikace Xamarin.iOS, která používá architekturu Handoff, správně nakonfigurovaná na portálu pro vývojáře Apple 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, identifikátory a profily.

  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 zkontrolována pro dané ID:

    Enable the iCloud service for the given ID

  5. Uložte provedené změny.

  6. Klikněte na Vývoj zřizovacích profilů>a vytvořte pro aplikaci 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 použité 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ů.

S těmito nastaveními 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 zařízení a zřizováním vašich aplikací.

Implementace předání

Aktivity uživatelů můžou pokračovat mezi aplikacemi, které jsou podepsané se stejným ID týmu vývojáře a podporují stejný typ aktivity. Implementace předání 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 jeden typ aktivity uživatele a podporuje procházení seznamu dostupných položek jako jiné.

Aplikace může vytvořit libovolný počet typů aktivit uživatelů, jeden pro libovolnou funkci, kterou 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ů je možné 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. Daná aplikace může například vytvořit čtyři různé typy aktivit, které využívají různé jednotlivé aplikace 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 jsou jednotlivé aplikace menší a zaměřují se 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. V poli bude jedna položka pro každou aktivitu, kterou aplikace podporuje. Apple navrhuje pro identifikátor typu aktivity použít zápis zpětného stylu DNS, aby nedocházelo ke kolizím. Příklad: com.company-name.appname.activity pro konkrétní aktivity založené na aplikacích nebo com.company-name.activity pro aktivity, které se můžou spouštět napříč více aplikacemi.

Identifikátor typu aktivity se používá při vytváření NSUserActivity instance k identifikaci typu aktivity. Pokud 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á v zobrazení webového prohlížeče otevřenou jinou adresu URL. Uživatel bude moct pokračovat na libovolné kartě na jiném zařízení s iOSem, na kterém je aplikace spuštěná.

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 aktivity uživatelů

Když vytvoříme novou instanci třídy, určíme NSUserActivityDelegate instanciNSUserActivity, která bude sledovat změny stavu aktivity. Následující kód můžete například použít 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 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, například 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 NSUserActivity instance za poslední chvíli před odesláním.

Vytvoření instance NSUserActivity

Každá aktivita, kterou vaše aplikace chce poskytnout možnost pokračování 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 příslušné 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ří novou 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 výše vytvořené instance NSUserActivityDelegate , aby sledovala 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, NSData, NSDate, NSDictionary, , NSNull, , NSNumber, NSSetNSStringnebo NSURL. NSURL hodnoty dat, které odkazují 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 NSMutableDictionary jsme vytvořili objekt a naplnili ho jedním klíčem, který poskytuje adresu URL, kterou si uživatel právě prohlížel na dané kartě. AddUserInfoEntries Metoda 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, musíte použít Toky pokračování. 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 iCloud, o dostupnosti kontinuovatelných uživatelských aktivit. Pokud se uživatel rozhodne pokračovat v aktivitě na novém zařízení, spustí systém příslušnou aplikaci (na základě ID týmu a typu aktivity) a informace o tom AppDelegate , že bude pokračovat.

Nejprve se WillContinueUserActivityWithType volá metoda, aby aplikace mohla informovat uživatele, že pokračování se chystá začít. Následující kód v souboru AppDelegate.cs ukázkové aplikace používáme ke 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í zaregistruje a AppDelegate má veřejnou PreparingToHandoff metodu, 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...");
}

Bude ContinueUserActivityAppDelegate 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í ve skutečnosti předformuluje předání a obnoví aktivitu na aktuálním zařízení. V případě příkladu se na dané kartě zobrazí stejná adresa URL, kterou 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 zahrnuje UIApplicationRestorationHandler volání aktivity založené na dokumentech nebo respondentech. Při zavolání budete muset obslužné rutině obnovení předat NSArray nebo obnovitelné objekty. Příklad:

completionHandler (new NSObject[]{Tab4});

Pro každý předaný objekt bude volána jeho RestoreUserActivityState metoda. Každý objekt pak může pomocí dat ve slovníku UserInfo obnovit svůj vlastní stav. 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 automaticky obnovit. Další informace najdete v části Podpůrné předání v části Document-Based Apps níže.

Neúspěšné předání 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 kolekce, 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 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í.

Předání nativní aplikace do webového prohlížeč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ých situacích může webové rozhraní poskytovat požadované funkce a aktivita může pokračovat. Například e-mailový účet uživatele může poskytnout webové základní 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 příslušnou 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, použije systém 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 účastnila tohoto typu předání, musí 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žijteterminálovou aplikaci a openssl příkaz s certifikátem a klíčem vydaným certifikační autoritou, která je důvěryhodná 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 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 , jakýkoli jiný protokol vyvolá výjimku.

Podpora předání v dokumentových aplikacích

Jak je uvedeno výše, v iOSu a OS X budou aplikace založené na dokumentech automaticky podporovat 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 designátorem aplikace reverzní 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 .

Na automaticky vytvořený objekt aktivity uživatele (dostupný prostřednictvím vlastnosti dokumentu UserActivity ) můžou odkazovat jiné objekty v aplikaci a použít k obnovení stavu při pokračování. Chcete-li například sledovat výběr položek a umístění dokumentu. Tuto vlastnost aktivity NeedsSave musíte 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 ho můžete použít k zachování synchronizovaného dokumentu při přesouvání do iCloudu. Vlastnost UserActivity bude při zavření dokumentu neplatná.

Další informace najdete v dokumentaci k podpoře aktivit uživatelů společnosti Apple v dokumentaci k aplikacím založeným na dokumentech.

Podpora předání v respondérech

K aktivitám můžete přidružit respondenty (zděděné z UIResponder iOSu nebo NSResponder OS X) nastavením jejich UserActivity vlastností. Systém automaticky uloží UserActivity vlastnost v odpovídajících časech a zavolá metodu respondéru UpdateUserActivityState , která přidá aktuální data do objektu User Activity pomocí AddUserInfoEntriesFromDictionary metody.

Podpora Toky pokračování

Může se jednat o situace, kdy množství informací potřebných k pokračování aktivity nelze efektivně přenést počáteční datovou částí předání. 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 truehodnotu . 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 navazová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í přijímá delegát aktivity uživatele datové proudy voláním jeho DidReceiveInputStream metody k poskytnutí dat požadovaných k pokračování aktivity uživatele na obnovovacím zařízení.

Použijete NSInputStream k poskytování přístupu jen pro čtení k datům datových proudů a NSOutputStream k poskytnutí přístupu jen pro zápis. Datové proudy 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. Takže se data zapsaná do výstupního datového proudu na původním zařízení čtou ze vstupního datového proudu na pokračujícím zařízení a naopak.

I v situacích, kdy se vyžaduje stream pro pokračování, by mezi těmito dvěma aplikacemi měla existovat minimální komunikace mezi oběma aplikacemi.

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živatelů prostřednictvím handoffu vyžaduje pečlivý návrh kvůli všem různým součástem. 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ší možnou datovou část, aby souvisela se stavem aktivity, který se má pokračovat. Čím je datová část větší, tím déle trvá pokračování.
  • Pokud pro úspěšné pokračování musíte přenést velké objemy dat, vezměte v úvahu náklady spojené s konfigurací a režií na síť.
  • U velké aplikace pro Mac je běžné vytvářet aktivity uživatelů, které zpracovává několik menších aplikací specifických pro úkoly 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 selhávají správně.
  • Při zadávání typů aktivit použijte reverzní zápis DNS, abyste se vyhnuli kolizím. Pokud je aktivita specifická pro danou aplikaci, měla by být její název součástí definice typu (například com.myCompany.myEditor.editing). Pokud aktivita může fungovat napříč více aplikacemi, přetáhně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 bude Handoff volat metodu delegáta UserActivityWillSave , abyste mohli podle potřeby aktualizovat UserInfo slovník.
  • Protože proces předání 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á začít.

Ukázková 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é uživatel může 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 nová NSUserActivity karta obsahující 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 blízkosti výše uvedeného zařízení se 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 na 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í UserActivityWasContinued metody na jeho NSUserActivityDelegate oznámení, že aktivita uživatele byla úspěšně přenesena do jiného zařízení.

Shrnutí

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