Entrega en Xamarin.iOS

En este artículo se explica cómo trabajar con Handoff en una aplicación de Xamarin.iOS para transferir actividades de usuario entre aplicaciones que se ejecutan en otros dispositivos del usuario.

Apple presentó Handoff en iOS 8 y OS X Yosemite (10.10) para proporcionar un mecanismo común para que el usuario transfiera las actividades iniciadas en uno de sus dispositivos, a otro dispositivo que ejecute la misma aplicación u otra aplicación que admita la misma actividad.

Ejemplo de realización de una operación de entrega

En este artículo se echará un vistazo rápido a la habilitación del uso compartido de actividades en una aplicación xamarin.iOS y se trata el marco handoff en detalle:

Acerca de Handoff

Apple introdujo Handoff (también conocida como continuidad) en iOS 8 y OS X Yosemite (10.10) como una manera de que el usuario inicie una actividad en uno de sus dispositivos (ya sea iOS o Mac) y continúe con esa misma actividad en otro de sus dispositivos (como se identifica en la cuenta de iCloud del usuario).

Handoff se expandió en iOS 9 para admitir también nuevas funcionalidades de búsqueda mejoradas. Para obtener más información, consulte nuestra documentación de mejoras de búsqueda.

Por ejemplo, el usuario puede iniciar un correo electrónico en su iPhone y continuar sin problemas el correo electrónico en su Equipo Mac, con toda la misma información de mensaje rellenada y el cursor en la misma ubicación en la que lo dejó en iOS.

Cualquiera de las aplicaciones que comparten el mismo identificador de equipo puede usar Handoff para continuar con las actividades del usuario entre aplicaciones, siempre y cuando estas aplicaciones se entreguen a través de iTunes App Store o estén firmadas por un desarrollador registrado (para aplicaciones De Mac, Enterprise o Ad Hoc).

Las aplicaciones basadas en o tienen automáticamente compatibilidad con Handoff integrada y requieren cambios NSDocumentUIDocument mínimos para admitir Handoff.

Continuación de las actividades del usuario

La clase (junto con algunos pequeños cambios en y ) proporciona compatibilidad para definir la actividad de un usuario que puede continuar en otro de los dispositivos NSUserActivityUIKit del AppKit usuario.

Para que una actividad se pase a otro de los dispositivos del usuario, se debe encapsular en una instancia de , marcada como actividad actual, tener su carga establecida (los datos usados para realizar la continuación) y, a continuación, la actividad debe transmitirse a NSUserActivity ese dispositivo. NSUserActivity

Handoff pasa el mínimo mínimo de información para definir la actividad que se va a continuar, con paquetes de datos más grandes sincronizados a través de iCloud.

En el dispositivo receptor, el usuario recibirá una notificación de que una actividad está disponible para su continuación. Si el usuario decide continuar la actividad en el nuevo dispositivo, se inicia la aplicación especificada (si aún no se está ejecutando) y la carga de se usa para reiniciar NSUserActivity la actividad.

Información general sobre las actividades continuas del usuario

Solo las aplicaciones que comparten el mismo identificador de equipo para desarrolladores y responden a un tipo de actividad determinado son aptas para la continuación. Una aplicación define los tipos de actividad que admite en la NSUserActivityTypes clave de su archivo NSUserActivityTypes Dado esto, un dispositivo continuo elige la aplicación para realizar la continuación en función del identificador de equipo, el tipo de actividad y, opcionalmente, el título de la actividad.

La aplicación receptora usa información del diccionario del para configurar su interfaz de usuario y restaurar el estado de la actividad dada para que la transición aparezca sin problemas NSUserActivityUserInfo para el usuario final.

Si la continuación requiere más información de la que se puede enviar de forma eficaz a través de , la aplicación de reanudación puede enviar una llamada a la aplicación de origen y establecer una o varias secuencias para transmitir los datos NSUserActivity necesarios. Por ejemplo, si la actividad edita un documento de texto grande con varias imágenes, se requiere streaming para transferir la información necesaria para continuar con la actividad en el dispositivo receptor. Para obtener más información, vea la sección Continuación Secuencias siguiente.

Como se indicó anteriormente, las aplicaciones basadas en tienen automáticamente compatibilidad con NSDocumentUIDocument Handoff integrada. Para más información, consulte la sección Supporting Handoff in Document-Based Apps a continuación.

La clase NSUserActivity

La clase es el objeto principal de un intercambio handoff y se usa para encapsular el estado de una actividad de usuario que NSUserActivity está disponible para la continuación. Una aplicación crea una instancia de una copia de para cualquier actividad que admita y NSUserActivity desee continuar en otro dispositivo. Por ejemplo, el editor de documentos crearía una actividad para cada documento abierto actualmente. Sin embargo, solo el documento de nivel superior (que se muestra en la ventana o pestaña más adelante) es la actividad actual y, por tanto, está disponible para su continuación.

Una instancia de NSUserActivity se identifica mediante sus propiedades y ActivityTypeTitle . La UserInfo propiedad dictionary se usa para llevar información sobre el estado de la actividad. Establezca la NeedsSave propiedad en si desea cargar true diferidamente la información de estado a través del NSUserActivity delegado de . Use el método para combinar nuevos datos de otros clientes en el diccionario según AddUserInfoEntries sea necesario para conservar el estado de la UserInfo actividad.

La clase NSUserActivityDelegate

se usa para mantener la información del diccionario de un objeto actualizado y sincronizado con NSUserActivityDelegate el estado actual de la NSUserActivityUserInfo actividad. Cuando el sistema necesita que se actualice la información de la actividad (por ejemplo, antes de la continuación en otro dispositivo), llama al UserActivityWillSave método del delegado.

Deberá implementar el método y realizar cualquier cambio en UserActivityWillSaveNSUserActivity (como UserInfo , , Title etc.). para asegurarse de que sigue reflejando el estado de la actividad actual. Cuando el sistema llama UserActivityWillSave al método , se NeedsSave borrará la marca. Si modifica cualquiera de las propiedades de datos de la actividad, deberá volver a NeedsSave establecer true en .

En lugar de usar UserActivityWillSave el método presentado anteriormente, opcionalmente puede tener o administrar la actividad del usuario UIKitAppKit automáticamente. Para ello, establezca la propiedad del objeto del UserActivity respondedor e implemente el UpdateUserActivityState método . Consulte la sección Entrega de soporte técnico en respondedores a continuación para obtener más información.

Compatibilidad con App Framework

Tanto UIKit (iOS) como (OS X) proporcionan compatibilidad integrada con Handoff en las clases AppKitNSDocument , Respondedor ( ) y UIResponder/NSResponderAppDelegate . Aunque cada sistema operativo implementa Handoff de forma ligeramente diferente, el mecanismo básico y las API son los mismos.

Actividades del usuario en Document-Based Apps

Las aplicaciones iOS y OS X basadas en documentos tienen automáticamente compatibilidad integrada con Handoff. Para activar esta compatibilidad, deberá agregar una clave y un valor para cada entrada en el NSUbiquitousDocumentUserActivityTypeCFBundleDocumentTypes archivo NSUbiquitousDocumentUserActivityType de la aplicación.

Si esta clave está presente, y crean automáticamente instancias para documentos basados en NSDocumentUIDocumentNSUserActivity iCloud del tipo especificado. Deberá proporcionar un tipo de actividad para cada tipo de documento que admita la aplicación y varios tipos de documento pueden usar el mismo tipo de actividad. Tanto NSDocument como UIDocument rellenan automáticamente la propiedad de con UserInfo el valor de su NSUserActivityFileURL propiedad.

En OS X, el administrado por y asociado a los respondedores se convierte automáticamente en la actividad actual cuando la ventana del documento NSUserActivity se convierte en la ventana AppKit principal. En iOS, para los objetos administrados por , debe llamar al método explícitamente o tener la propiedad del documento establecida en cuando la aplicación llega NSUserActivityUIKit al primer BecomeCurrentUserActivityUIViewController plano.

AppKit restaurará automáticamente cualquier UserActivity propiedad creada de esta manera en OS X. Esto ocurre si el ContinueUserActivity método devuelve o si no se ha false simplificado. En esta situación, el documento se abre con el método de y, a continuación, OpenDocument recibirá una llamada al método NSDocumentControllerRestoreUserActivityState .

Consulte la sección Supporting Handoff in Document-Based Apps a continuación para obtener más información.

Actividades de usuario y respondedores

Tanto como pueden administrar automáticamente una actividad de usuario si la establece como propiedad de un objeto UIKitAppKit de UserActivity respondedor. Si se ha modificado el estado, deberá establecer la NeedsSave propiedad del respondedor UserActivity en true . El sistema guardará automáticamente cuando sea necesario, después de dar tiempo al respondedor para UserActivity actualizar el estado mediante una llamada a su método UpdateUserActivityState .

Si varios respondedores comparten una sola instancia, reciben una devolución de NSUserActivity llamada cuando el sistema actualiza el objeto de actividad del UpdateUserActivityState usuario. El respondedor debe llamar al AddUserInfoEntries método para actualizar el diccionario de para reflejar el estado de actividad actual en este NSUserActivityUserInfo momento. El UserInfo diccionario se borra antes de cada UpdateUserActivityState llamada.

Para desasociarse de una actividad, un respondedor puede establecer su UserActivity propiedad en null . Cuando una instancia administrada de App Framework no tiene más respondedores o documentos NSUserActivity asociados, se invalida automáticamente.

Consulte la sección Entrega de soporte técnico en respondedores a continuación para obtener más información.

Actividades del usuario y AppDelegate

El de la aplicación AppDelegate es su punto de entrada principal al controlar una continuación handoff. Cuando el usuario responde a una notificación handoff, se inicia la aplicación adecuada (si aún no se está ejecutando) y se llama WillContinueUserActivityWithTypeAppDelegate al método de . En este momento, la aplicación debe informar al usuario de que se está iniciando la continuación.

La NSUserActivity instancia se entrega cuando se llama al método del AppDelegateContinueUserActivity . En este momento, debe configurar la interfaz de usuario de la aplicación y continuar con la actividad dada.

Consulte la sección Implementing Handoff (Implementación de handoff) a continuación para obtener más información.

Habilitación de Handoff en una aplicación xamarin

Debido a los requisitos de seguridad impuestos por Handoff, una aplicación de Xamarin.iOS que usa el marco Handoff debe configurarse correctamente tanto en apple Portal para desarrolladores como en el archivo de proyecto de Xamarin.iOS.

Haga lo siguiente:

  1. Inicie sesión en apple Portal para desarrolladores.

  2. Haga clic en Certificados, Perfiles de identificadores.

  3. Si aún no lo ha hecho, haga clic en Identificadores y cree un identificador para la aplicación (por ejemplo, ), de lo contrario, edite el identificador existente.

  4. Asegúrese de que se ha comprobado el identificador especificado en el servicio iCloud:

    Habilitación del servicio iCloud para el identificador especificado

  5. Guarde los cambios.

  6. Haga clic en Desarrollo de perfilesde aprovisionamiento y cree un nuevo perfil de aprovisionamiento de desarrollo para la aplicación:

    Creación de un nuevo perfil de aprovisionamiento de desarrollo para la aplicación

  7. Descargue e instale el nuevo perfil de aprovisionamiento o use Xcode para descargar e instalar el perfil.

  8. Edite las opciones del proyecto de Xamarin.iOS y asegúrese de que usa el perfil de aprovisionamiento que acaba de crear:

    Selección del perfil de aprovisionamiento que acaba de crear

  9. A continuación, edite el archivo Info.plist y asegúrese de que usa el identificador de aplicación que se usó para crear el perfil de aprovisionamiento:

    Establecer id. de aplicación

  10. Desplácese hasta la sección Modos en segundo plano y compruebe los siguientes elementos:

    Habilitación de los modos en segundo plano necesarios

  11. Guarde los cambios en todos los archivos.

Con esta configuración, la aplicación ya está lista para acceder a las API de Handoff Framework. Para obtener información detallada sobre el aprovisionamiento, consulte nuestras guías de aprovisionamiento de dispositivos y aprovisionamiento de aplicaciones.

Implementación de Handoff

Las actividades del usuario se pueden continuar entre las aplicaciones que están firmadas con el mismo identificador de equipo de desarrollador y admiten el mismo tipo de actividad. La implementación de Handoff en una aplicación xamarin.iOS requiere crear un objeto de actividad de usuario (en o ), actualizar el estado del objeto para realizar un seguimiento de la actividad y continuar la actividad en un dispositivo UIKitAppKit receptor.

Identificación de actividades del usuario

El primer paso para implementar Handoff es identificar los tipos de actividades de usuario que admite la aplicación y ver cuáles de esas actividades son buenas candidatas para la continuación en otro dispositivo. Por ejemplo: una aplicación ToDo podría admitir la edición de elementos como un tipo de actividad de usuario yadmitir la exploración de la lista de elementos disponibles como otra.

Una aplicación puede crear tantos tipos de actividad de usuario como sean necesarios, uno para cualquier función que la aplicación proporciona. Para cada tipo de actividad de usuario, la aplicación tendrá que realizar un seguimiento de cuándo comienza y finaliza una actividad del tipo, y debe mantener la información de estado actualizada para continuar con esa tarea en otro dispositivo.

Las actividades del usuario se pueden continuar en cualquier aplicación firmada con el mismo identificador de equipo sin ninguna asignación uno a uno entre las aplicaciones de envío y recepción. Por ejemplo, una aplicación determinada puede crear cuatro tipos diferentes de actividades que consumen diferentes aplicaciones individuales en otro dispositivo. Se trata de una ocurrencia común entre una versión de Mac de la aplicación (que podría tener muchas características y funciones) y aplicaciones iOS, donde cada aplicación es más pequeña y se centra en una tarea específica.

Crear identificadores de tipo de actividad

El identificador de tipo de actividad es una cadena corta que se agrega a la matriz del archivo Info.plist de la aplicación que se usa para identificar de forma única un tipo de actividad de usuario determinado. Habrá una entrada en la matriz para cada actividad que admita la aplicación. Apple sugiere usar una notación de estilo DNS inverso para el identificador de tipo de actividad para evitar colisiones. Por ejemplo: com.company-name.appname.activity para actividades específicas basadas en aplicaciones o com.company-name.activity para actividades que se pueden ejecutar en varias aplicaciones.

El identificador de tipo de actividad se usa al crear NSUserActivity una instancia de para identificar el tipo de actividad. Cuando se continúa una actividad en otro dispositivo, el tipo de actividad (junto con el identificador de equipo de la aplicación) determina qué aplicación se va a iniciar para continuar con la actividad.

Por ejemplo, vamos a crear una aplicación de ejemplo denominada MonkeyBrowser(descargar aquí). Esta aplicación presentará cuatro pestañas, cada una con una dirección URL diferente abierta en una vista del explorador web. El usuario podrá continuar con cualquier pestaña en otro dispositivo iOS que ejecute la aplicación.

Para crear los identificadores de tipo de actividad necesarios para admitir este comportamiento, edite el archivo Info.plist y cambie a la vista Origen. Agregue una NSUserActivityTypes clave y cree los identificadores siguientes:

Clave NSUserActivityTypes e identificadores necesarios en el editor plist

Hemos creado cuatro nuevos identificadores de tipo de actividad, uno para cada una de las pestañas de la aplicación De ejemplo De MonoBrowser. Al crear sus propias aplicaciones, reemplace el contenido de la matriz por los identificadores de tipo de actividad NSUserActivityTypes específicos de las actividades que admite la aplicación.

Seguimiento de los cambios de actividad del usuario

Cuando creamos una nueva instancia de la clase , especificaremos una instancia para realizar el seguimiento de los cambios NSUserActivity en el estado de la NSUserActivityDelegate actividad. Por ejemplo, el código siguiente se puede usar para realizar un seguimiento de los cambios de estado:

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

Se UserActivityReceivedData llama al método cuando un flujo de continuación ha recibido datos de un dispositivo de envío. Para obtener más información, vea la sección compatibilidad con la Secuencias siguiente.

Se UserActivityWasContinued llama al método cuando otro dispositivo ha tomado el control de una actividad del dispositivo actual. Según el tipo de actividad, como agregar un nuevo elemento a una lista de tareas todo, es posible que la aplicación necesite anular la actividad en el dispositivo de envío.

Se llama al método antes de que los cambios en la actividad se guarden y UserActivityWillSave sincronicen en los dispositivos disponibles localmente. Puede usar este método para realizar cualquier cambio de última hora en la UserInfo propiedad de la instancia antes de NSUserActivity enviarla.

Creación de una instancia de NSUserActivity

Cada actividad que la aplicación desea proporcionar la posibilidad de continuar en otro dispositivo debe encapsularse en una NSUserActivity instancia de . La aplicación puede crear tantas actividades como sea necesario y la naturaleza de esas actividades depende de la funcionalidad y las características de la aplicación en cuestión. Por ejemplo, una aplicación de correo electrónico podría crear una actividad para crear un mensaje y otra para leer un mensaje.

En nuestra aplicación de ejemplo, se crea un nuevo cada vez que el usuario escribe una nueva dirección URL en una de las vistas NSUserActivity del explorador web con pestañas. El código siguiente almacena el estado de una pestaña determinada:

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

Crea un nuevo con uno de los tipos de actividad de usuario creados anteriormente y proporciona un título legible NSUserActivity para la actividad. Se asocia a una instancia de la creada anteriormente para observar los cambios de estado e informa a iOS de que esta actividad de usuario NSUserActivityDelegate es la actividad actual.

Rellenar el diccionario UserInfo

Como hemos visto anteriormente, la propiedad de la clase es un de pares clave-valor usados para definir el UserInfo estado de una actividad NSUserActivityNSDictionary determinada. Los valores UserInfo almacenados en deben ser uno de los siguientes tipos: NSArray , , , , , , , NSData o NSDateNSDictionaryNSNullNSNumberNSSetNSStringNSURL . NSURL Los valores de datos que apuntan a documentos de iCloud se ajustarán automáticamente para que apunten a los mismos documentos en un dispositivo receptor.

En el ejemplo anterior, creamos un objeto y lo rellenamos con una sola clave que proporciona la dirección URL que el usuario estaba viendo actualmente NSMutableDictionary en la pestaña especificada. El método de la actividad de usuario se usó para actualizar la actividad con los datos que se usarán para restaurar AddUserInfoEntries la actividad en el dispositivo receptor:

// 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 recomienda mantener la información enviada al mínimo para asegurarse de que la actividad se envía de forma oportuna al dispositivo receptor. Si se requiere información más grande, como es necesario enviar una imagen adjunta a un documento que se va a editar, debe usar la propiedad Continuation Secuencias. Para más información, consulte Secuencias continuación de soporte técnico.

Continuación de una actividad

Handoff informará automáticamente a los dispositivos iOS y OS X locales que se encuentran en proximidad física al dispositivo de origen y que han iniciado sesión en la misma cuenta de iCloud, de la disponibilidad de las actividades de usuario continuas. Si el usuario decide continuar con una actividad en un dispositivo nuevo, el sistema iniciará la aplicación adecuada (según el identificador de equipo y el tipo de actividad) e información sobre su AppDelegate continuación.

En primer lugar, WillContinueUserActivityWithType se llama al método para que la aplicación pueda informar al usuario de que la continuación está a punto de comenzar. Usamos el código siguiente en el archivo AppDelegate.cs de nuestra aplicación de ejemplo para controlar un inicio de continuació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;
}

En el ejemplo anterior, cada controlador de vistas se registra con y tiene un método público que muestra un indicador de actividad y un mensaje que permite al usuario saber que la actividad está a punto de entregarse al AppDelegatePreparingToHandoff dispositivo actual. Ejemplo:

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

Se ContinueUserActivity llamará al AppDelegate de para continuar realmente la actividad determinada. De nuevo, desde nuestra aplicación de ejemplo:

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

El método público de cada controlador de vista realmente preforma la entrega PerformHandoff y restaura la actividad en el dispositivo actual. En el caso del ejemplo, muestra la misma dirección URL en una pestaña determinada que el usuario estaba explorando en un dispositivo diferente. Ejemplo:

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

}

El método incluye un que se puede llamar para reanudar la actividad basada en documentos o ContinueUserActivityUIApplicationRestorationHandler respondedores. Deberá pasar un objeto o objetos restaurables al controlador de restauración NSArray cuando se llame a . Por ejemplo:

completionHandler (new NSObject[]{Tab4});

Para cada objeto pasado, se RestoreUserActivityState llamará a su método. A continuación, cada objeto puede usar los datos del UserInfo diccionario para restaurar su propio estado. Por ejemplo:

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

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

En el caso de las aplicaciones basadas en documentos, si no implementa el método o devuelve , o puede reanudar ContinueUserActivityfalse automáticamente la UIKitAppKit actividad. Consulte la sección Supporting Handoff in Document-Based Apps a continuación para obtener más información.

Entrega con errores correctamente

Dado que Handoff se basa en la transmisión de información entre dispositivos iOS y OS X conectados de forma flexible, el proceso de transferencia a veces puede producir un error. Debe diseñar la aplicación para controlar estos errores correctamente e informar al usuario de cualquier situación que surja.

En caso de error, se DidFailToContinueUserActivitiy llamará al AppDelegate método de . Por ejemplo:

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

Debe usar el proporcionado para NSError proporcionar información al usuario sobre el error.

Entrega de aplicación nativa a explorador web

Es posible que un usuario quiera continuar con una actividad sin tener instalada una aplicación nativa adecuada en el dispositivo deseado. En algunas situaciones, una interfaz basada en web puede proporcionar la funcionalidad necesaria y la actividad todavía se puede continuar. Por ejemplo, la cuenta de correo electrónico del usuario puede proporcionar una interfaz de usuario base web para crear y leer mensajes.

Si la aplicación nativa de origen conoce la dirección URL de la interfaz web (y la sintaxis necesaria para identificar el elemento especificado que se va a continuar), puede codificar esta información en la propiedad de la WebpageURLNSUserActivity instancia. Si el dispositivo receptor no tiene instalada una aplicación nativa adecuada para controlar la continuación, se puede llamar a la interfaz web proporcionada.

Entrega de explorador web a aplicación nativa

Si el usuario usaba una interfaz basada en web en el dispositivo de origen y una aplicación nativa en el dispositivo receptor reclama la parte del dominio de la propiedad , el sistema usará esa aplicación para controlar la WebpageURL continuación. El nuevo dispositivo recibirá una instancia que marca el tipo de actividad como y contendrá la dirección URL que visitaba el usuario; el diccionario NSUserActivityBrowsingWeb estará WebpageURLUserInfo vacío.

Para que una aplicación participe en este tipo de Handoff, debe reclamar el dominio en un derecho con el com.apple.developer.associated-domains formato <service>:<fully qualified domain name> (por ejemplo: activity continuation:company.com ).

Si el dominio especificado coincide con el valor de una propiedad, Handoff descarga una lista de los nombres de aplicación aprobados del sitio WebpageURL web en ese dominio. El sitio web debe proporcionar una lista de los iD aprobados en un archivo JSON firmado denominado apple-app-site-association (por ejemplo, ).

Este archivo JSON contiene un diccionario que especifica una lista de los nombres de aplicación con el formato <team identifier>.<bundle identifier> . Por ejemplo:

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

Para firmar el archivo JSON (para que tenga el correcto de ), use la aplicación Terminal y un comando con un certificado y una clave emitidos por una entidad de certificación de confianza para iOS (consulte para obtener Content-Typeapplication/pkcs7-mime una Content-Typeopensslhttps://support.apple.com/kb/ht5012 lista). Por ejemplo:

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

El comando genera un archivo JSON firmado que se coloca en el sitio web en la dirección openssl URL openssl Por ejemplo:

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

La aplicación recibirá cualquier actividad cuyo WebpageURL dominio esté en su com.apple.developer.associated-domains derecho. Solo los httphttps protocolos y son compatibles, cualquier otro protocolo producirá una excepción.

Compatibilidad con Handoff en Document-Based Apps

Como se indicó anteriormente, en iOS y OS X, las aplicaciones basadas en documentos admitirán automáticamente la entrega de documentos basados en iCloud si el archivo Info.plist de la aplicación contiene una clave de NSUbiquitousDocumentUserActivityType . Por ejemplo:

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

En este ejemplo, la cadena es un designador de aplicación DE DNS inverso con el nombre de la actividad anexada. Si se escribe de esta manera, no es necesario repetir las entradas del tipo de actividad en la matriz NSUserActivityTypesNSUserActivityTypes

Otros objetos de la aplicación pueden hacer referencia al objeto Actividad de usuario creado automáticamente (disponible a través de la propiedad del documento) y usarse para restaurar el estado en la UserActivity continuación. Por ejemplo, para realizar un seguimiento de la selección de elementos y la posición del documento. Debe establecer esta propiedad activities en siempre NeedsSave que cambie el estado y actualizar el diccionario en el método trueUserInfoUpdateUserActivityState .

La propiedad se puede usar desde cualquier subproceso y se ajusta al protocolo de observación de clave-valor (KVO), por lo que se puede usar para mantener un documento sincronizado a medida que entra y sale de UserActivity iCloud. La UserActivity propiedad se invalidará cuando se cierre el documento.

Para obtener más información, consulte La compatibilidad con la actividad del usuario de Apple en Document-Based Apps.

Compatibilidad con handoff en respondedores

Puede asociar respondedores (heredados de en iOS o en OS X) a actividades UIResponderNSResponder estableciendo sus UserActivity propiedades. El sistema guarda automáticamente la propiedad en el momento adecuado, llamando al método del respondedor para agregar datos actuales al objeto UserActivity User Activity mediante el método UpdateUserActivityStateAddUserInfoEntriesFromDictionary .

Compatibilidad con la continuación Secuencias

puede ser situaciones en las que la cantidad de información necesaria para continuar con una actividad no se puede transferir de forma eficaz mediante la carga inicial de entrega. En estas situaciones, la aplicación receptora puede establecer una o varias secuencias entre sí y la aplicación de origen para transferir los datos.

La aplicación de origen establecerá la SupportsContinuationStreams propiedad de la instancia en NSUserActivitytrue . Por ejemplo:

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

A continuación, la aplicación receptora GetContinuationStreams puede llamar al método de en para establecer la NSUserActivityAppDelegate secuencia. Por ejemplo:

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

En el dispositivo de origen, el delegado de actividad de usuario recibe los flujos llamando a su método para proporcionar los datos solicitados para continuar con la actividad del usuario en el DidReceiveInputStream dispositivo que se reanuda.

Usará para proporcionar acceso de solo lectura a los datos de transmisión y para NSInputStream proporcionar acceso de solo NSOutputStream escritura. Las secuencias deben usarse de forma de solicitud y respuesta, donde la aplicación receptora solicita más datos y la aplicación de origen los proporciona. Por lo tanto, los datos escritos en el flujo de salida en el dispositivo de origen se leen desde el flujo de entrada en el dispositivo continuo y viceversa.

Incluso en situaciones en las que se requiere secuencia de continuación, debe haber una comunicación mínima de ida y vuelta entre las dos aplicaciones.

Para más información, consulte la documentación sobre el uso de continuación Secuencias Apple.

Prácticas recomendadas de entrega

La implementación correcta de la continuación sin problemas de una actividad de usuario a través de Handoff requiere un diseño cuidadosa debido a todos los distintos componentes implicados. Apple sugiere adoptar los siguientes procedimientos recomendados para las aplicaciones habilitadas para Handoff:

  • Diseñe las actividades del usuario para requerir la carga más pequeña posible para relacionar el estado de la actividad que se va a continuar. Cuanto mayor sea la carga, más tiempo tarda la continuación en iniciarse.
  • Si debe transferir grandes cantidades de datos para una continuación correcta, tenga en cuenta los costos implicados en la configuración y la sobrecarga de red.
  • Es habitual que una aplicación Mac grande cree actividades de usuario que se controlan mediante varias aplicaciones específicas de tareas más pequeñas en dispositivos iOS. Las distintas versiones de la aplicación y del sistema operativo deben diseñarse para funcionar bien juntos o producir errores correctamente.
  • Al especificar los tipos de actividad, use la notación de DNS inverso para evitar colisiones. Si una actividad es específica de una aplicación determinada, su nombre debe incluirse en la definición de tipo (por com.myCompany.myEditor.editing ejemplo, ). Si la actividad puede funcionar en varias aplicaciones, coloque el nombre de la aplicación de la definición (por com.myCompany.editing ejemplo, ).
  • Si la aplicación necesita actualizar el estado de una actividad de usuario ( NSUserActivity ), establezca la propiedad en NeedsSavetrue . En los momentos adecuados, Handoff llamará al método del delegado UserActivityWillSave para que pueda actualizar el diccionario según sea UserInfo necesario.
  • Dado que es posible que el proceso de entrega no se inicialice al instante en el dispositivo receptor, debe implementar e informar al usuario de que una continuación está a punto AppDelegateWillContinueUserActivity de iniciarse.

Aplicación de entrega de ejemplo

Como ejemplo de uso de Handoff en una aplicación xamarin.iOS, hemos incluido la aplicación de ejemplo MonkeyBrowser con esta guía. La aplicación tiene cuatro pestañas que el usuario puede usar para examinar la web, cada una con un tipo de actividad determinado: Tiempo, Favorito, Pausa de café y Trabajo.

En cualquier pestaña, cuando el usuario escribe una nueva dirección URL y pulsa el botón Ir, se crea un nuevo para esa pestaña que contiene la dirección URL que el usuario está explorando actualmente:

Aplicación de entrega de ejemplo

Si otro de los dispositivos del usuario tiene instalada la aplicación MonkeyBrowser, ha iniciado sesión en iCloud con la misma cuenta de usuario, está en la misma red y está cerca del dispositivo anterior, la actividad handoff se mostrará en la pantalla principal (en la esquina inferior izquierda):

La actividad de entrega que se muestra en la pantalla principal en la esquina inferior izquierda

Si el usuario arrastra hacia arriba el icono Handoff, se inicia la aplicación y la actividad de usuario especificada en se continuará NSUserActivity en el nuevo dispositivo:

La actividad del usuario continuó en el nuevo dispositivo.

Cuando la actividad de usuario se haya enviado correctamente a otro dispositivo de Apple, el dispositivo de envío recibirá una llamada al método en para que sepa que la actividad de usuario se ha transferido correctamente a otro NSUserActivityUserActivityWasContinuedNSUserActivityDelegate dispositivo.

Resumen

En este artículo se ha dado una introducción al marco handoff que se usa para continuar una actividad de usuario entre varios de los dispositivos Apple del usuario. A continuación, se mostró cómo habilitar e implementar Handoff en una aplicación xamarin.iOS. Por último, se han analizado los distintos tipos de continuaciones de entrega disponibles y los procedimientos recomendados de entrega.