Share via


Tareas en segundo plano de watchOS en Xamarin

Con watchOS 3, hay tres maneras principales de que una aplicación de inspección pueda mantener actualizada su información:

  • Usar una de las diversas tareas en segundo plano nuevas.
  • Tener una de sus complicaciones en la cara del reloj (dando tiempo adicional para actualizar).
  • Tener el usuario anclado a la aplicación al nuevo Dock (donde se mantiene en la memoria y se actualiza con frecuencia).

Mantener actualizada una aplicación

Antes de analizar todas las formas en que un desarrollador puede mantener actualizados y actualizados los datos y la interfaz de usuario de una aplicación watchOS, esta sección echará un vistazo a un conjunto típico de patrones de uso y cómo un usuario podría moverse entre sus iPhone y su Apple Watch durante todo el día en función de la hora del día y la actividad que están realizando actualmente (como conducir).

Considere el ejemplo siguiente:

Cómo puede moverse un usuario entre su iPhone y su Apple Watch a lo largo del día

  1. Por la mañana, mientras espera en línea un café, el usuario examina las noticias actuales en su iPhone durante varios minutos.
  2. Antes de salir de la cafetería, revisan rápidamente el clima con una complicación en su cara de reloj.
  3. Antes del almuerzo, usan la aplicación Mapas en el iPhone para encontrar un restaurante cercano y reservar una reserva para satisfacer a un cliente.
  4. Mientras viajas al restaurante, reciben una notificación en su Apple Watch y con un vistazo rápido, saben que su cita de almuerzo se está ejecutando tarde.
  5. Por la noche, usan la aplicación Mapas en iPhone para comprobar el tráfico antes de conducir a casa.
  6. En el camino a casa, reciben una notificación de iMessage en su Apple Watch pidiendo que recojan algo de leche y usen la característica respuesta rápida para enviar la respuesta "Ok".

Debido a la naturaleza de "vista rápida" (menos de tres segundos) de cómo un usuario quiere usar una aplicación de Apple Watch, normalmente no hay tiempo suficiente para que la aplicación capture la información deseada y actualice su interfaz de usuario antes de mostrarla al usuario.

Mediante el uso de las nuevas API que Apple ha incluido en watchOS 3, la aplicación puede programar una actualización en segundo plano y tener la información deseada lista antes de que el usuario lo solicite. Tome el ejemplo de la complicación meteorológica descrita anteriormente:

Un ejemplo de complicación meteorológica

  1. La aplicación programa la reactivación por parte del sistema en un momento específico.
  2. La aplicación captura la información que necesitará para generar la actualización.
  3. La aplicación vuelve a generar su interfaz de usuario para reflejar los nuevos datos.
  4. Cuando el usuario mira la complicación de la aplicación, tiene información actualizada sin que el usuario tenga que esperar a la actualización.

Como se ha visto anteriormente, el sistema watchOS reactiva la aplicación mediante una o varias tareas, de las cuales tiene un grupo muy limitado disponible:

El sistema watchOS reactiva la aplicación mediante una o varias tareas

Apple sugiere que la mayor parte de esta tarea (ya que es un recurso tan limitado para la aplicación) manteniendo en ella hasta que la aplicación haya terminado el proceso de actualización.

El sistema entrega estas tareas llamando al nuevo método HandleBackgroundTasks del WKExtensionDelegate delegado. Por ejemplo:

using System;
using Foundation;
using WatchKit;

namespace MonkeyWatch.MonkeySeeExtension
{
  public class ExtensionDelegate : WKExtensionDelegate
  {
    #region Constructors
    public ExtensionDelegate ()
    {
    }
    #endregion

    #region Override Methods
    public override void HandleBackgroundTasks (NSSet<WKRefreshBackgroundTask> backgroundTasks)
    {
      // Handle background request here
      ...
    }
    #endregion
  }
}

Cuando la aplicación haya terminado la tarea especificada, la devuelve al sistema marcando que se completó:

La tarea vuelve al sistema marcando que se completó

Nuevas tareas en segundo plano

WatchOS 3 presenta varias tareas en segundo plano que una aplicación puede usar para actualizar su información asegurándose de que tiene el contenido que necesita el usuario antes de abrirla:

  • Actualización de la aplicación en segundo plano: la tarea WKApplicationRefreshBackgroundTask permite a la aplicación actualizar su estado en segundo plano. Normalmente, esto incluirá otra tarea, como descargar contenido nuevo desde Internet mediante NSUrlSession.
  • Actualización de instantáneas en segundo plano: la tarea WKSnapshotRefreshBackgroundTask permite a la aplicación actualizar tanto su contenido como su interfaz de usuario antes de que el sistema tome una instantánea que se usará para rellenar dock.
  • Conectividad de inspección en segundo plano: la tarea WKWatchConnectivityRefreshBackgroundTask se inicia para la aplicación cuando recibe datos en segundo plano del iPhone emparejado.
  • Sesión de dirección URL en segundo plano: la tarea WKURLSessionRefreshBackgroundTask se inicia para la aplicación cuando una transferencia en segundo plano requiere autorización o se completa (correctamente o en error).

Estas tareas se tratará con detalles en las secciones siguientes.

WKApplicationRefreshBackgroundTask

WKApplicationRefreshBackgroundTask es una tarea genérica que se puede programar para que la aplicación se active en una fecha futura:

WKApplicationRefreshBackgroundTask se activa en una fecha futura

Dentro del tiempo de ejecución de la tarea, la aplicación puede realizar cualquier tipo de procesamiento local, como actualizar una escala de tiempo de complicaciones o capturar algunos datos necesarios con NSUrlSession.

WKURLSessionRefreshBackgroundTask

El sistema enviará un WKURLSessionRefreshBackgroundTask cuando la aplicación haya terminado de descargar y procesar los datos:

WKURLSessionRefreshBackgroundTask cuando los datos han terminado de descargarse

Una aplicación no se deja en ejecución mientras los datos se descargan en segundo plano. En su lugar, la aplicación programa la solicitud de datos y, a continuación, se suspende y el sistema controla la descarga de los datos, solo se vuelve a despertar la aplicación cuando se completa la descarga.

WKSnapshotRefreshBackgroundTask

En watchOS 3, Apple ha agregado el Dock, donde los usuarios pueden anclar sus aplicaciones favoritas y acceder rápidamente a ellas. Cuando el usuario presiona el botón lateral en Apple Watch, se mostrará una galería de instantáneas de aplicaciones ancladas. El usuario puede deslizar el dedo hacia la izquierda o hacia la derecha para encontrar la aplicación deseada y, a continuación, pulsar la aplicación para iniciarla para reemplazar la instantánea por la interfaz de la aplicación en ejecución.

Reemplazar la instantánea por la interfaz de aplicaciones en ejecución

El sistema toma periódicamente instantáneas de la interfaz de usuario de la aplicación (enviando un WKSnapshotRefreshBackgroundTask) y usa esas instantáneas para rellenar Dock. WatchOS ofrece a la aplicación la oportunidad de actualizar su contenido y la interfaz de usuario antes de que se tome esta instantánea.

Las instantáneas son muy importantes en watchOS 3, ya que funcionan como imágenes de vista previa e inicio para la aplicación. Si el usuario se establece en una aplicación en Dock, se expandirá a pantalla completa, escribirá el primer plano y empezará a ejecutarse, por lo que es imperativo que la instantánea esté actualizada:

Si el usuario se establece en una aplicación en Dock, se expandirá a pantalla completa

De nuevo, el sistema emitirá un WKSnapshotRefreshBackgroundTask para que la aplicación pueda prepararse (actualizando los datos y la interfaz de usuario) antes de tomar la instantánea:

La aplicación puede prepararse actualizando los datos y la interfaz de usuario antes de tomar la instantánea

Una vez la aplicación marca el WKSnapshotRefreshBackgroundTask, el sistema tomará automáticamente una instantánea de la interfaz de usuario de la aplicación.

Importante

Es importante programar WKSnapshotRefreshBackgroundTask siempre una vez que la aplicación haya recibido nuevos datos y actualizado su interfaz de usuario o el usuario no verá la información modificada.

Además, cuando el usuario recibe una notificación de la aplicación y lo pulsa para llevar la aplicación al primer plano, la instantánea debe estar actualizada, ya que actúa como la pantalla de inicio también:

El usuario recibe una notificación de la aplicación y la pulsa para ponerla en primer plano

Si ha transcurrido más de una hora desde que el usuario ha interactuado con una aplicación watchOS, podrá volver a su estado predeterminado. El estado predeterminado puede significar diferentes cosas para diferentes aplicaciones y, en función del diseño de una aplicación, es posible que no tenga un estado predeterminado en absoluto.

WKWatchConnectivityRefreshBackgroundTask

En watchOS 3, Apple ha integrado la conectividad de reloj con la API de actualización en segundo plano a través del nuevo WKWatchConnectivityRefreshBackgroundTask. Con esta nueva característica, una aplicación iPhone puede entregar datos nuevos a su homólogo de la aplicación de inspección, mientras que la aplicación watchOS se ejecuta en segundo plano:

Una aplicación iPhone puede entregar datos nuevos a su homólogo de la aplicación de inspección, mientras que la aplicación watchOS se ejecuta en segundo plano

Al iniciar una inserción de complicaciones, el contexto de la aplicación, el envío de un archivo o la actualización de la información del usuario desde la aplicación iPhone reactivará la aplicación Apple Watch en segundo plano.

Cuando se reactiva la aplicación de inspección a través de WKWatchConnectivityRefreshBackgroundTask, deberá usar los métodos de API estándar para recibir los datos de la aplicación iPhone.

Flujo de datos WKWatchConnectivityRefreshBackgroundTask

  1. Asegúrese de que la sesión se ha activado.
  2. Supervise la nueva propiedad HasContentPending siempre que el valor sea true, la aplicación todavía tiene datos que procesar. Como antes, la aplicación debe mantenerse en la tarea hasta que haya terminado de procesar todos los datos.
  3. Cuando no haya más datos que procesar (HasContentPending = false), marque la tarea completada para devolverla al sistema. Si no lo hace, se agotará el tiempo de ejecución en segundo plano asignado de la aplicación, lo que da lugar a un informe de bloqueo.

Ciclo de vida de la API en segundo plano

Colocar todas las partes de la nueva API de tareas en segundo plano juntas, un conjunto típico de interacciones tendría el siguiente aspecto:

Ciclo de vida de la API en segundo plano

  1. En primer lugar, la aplicación watchOS programa una tarea en segundo plano que se va a despertar como punto en el futuro.
  2. El sistema despierta la aplicación y envía una tarea.
  3. La aplicación procesa la tarea para completar el trabajo necesario.
  4. Como resultado del procesamiento de la tarea, es posible que la aplicación tenga que programar más tareas en segundo plano para completar más trabajo en el futuro, como descargar más contenido mediante NSUrlSession.
  5. La aplicación marca la tarea completada y la devuelve al sistema.

Uso responsable de los recursos

Es fundamental que una aplicación watchOS se comporte de forma responsable dentro de este ecosistema limitando su purga en los recursos compartidos del sistema.

Eche un vistazo al escenario siguiente:

Una aplicación watchOS limita su purga en los recursos compartidos del sistema

  1. El usuario inicia una aplicación watchOS a las 1:00 p. m.
  2. La aplicación programa una tarea para reactivar y descargar contenido nuevo en una hora a las 2:00 p. m.
  3. A las 1:50 p. m., el usuario vuelve a abrir la aplicación, lo que le permite actualizar sus datos y la interfaz de usuario en este momento.
  4. En lugar de permitir que la tarea vuelva a activar la aplicación en 10 minutos, la aplicación debe volver a programar la tarea para que se ejecute una hora más tarde a las 2:50 p. m.

Aunque cada aplicación es diferente, Apple sugiere encontrar patrones de uso, como los mostrados anteriormente, para ayudar a conservar los recursos del sistema.

Implementación de tareas en segundo plano

Por ejemplo, este documento usará la aplicación de deportes MonkeySoccer falsa que informa de puntuaciones de fútbol al usuario.

Eche un vistazo al siguiente escenario de uso típico:

Escenario de uso típico

El equipo de fútbol favorito del usuario está jugando un gran partido de 7:00 p. m. a 9:00 p. m., por lo que la aplicación debe esperar que el usuario esté comprobando la puntuación con regularidad y decida en un intervalo de actualización de 30 minutos.

  1. El usuario abre la aplicación y programa una tarea para la actualización en segundo plano 30 minutos después. La API en segundo plano solo permite ejecutar un tipo de tarea en segundo plano en un momento dado.
  2. La aplicación recibe la tarea y actualiza sus datos y la interfaz de usuario y, a continuación, programa otra tarea en segundo plano 30 minutos más tarde. Es importante que el desarrollador recuerde programar otra tarea en segundo plano, o que la aplicación nunca se volverá a despertar para obtener más actualizaciones.
  3. De nuevo, la aplicación recibe la tarea y actualiza sus datos, actualiza la interfaz de usuario y programa otra tarea en segundo plano 30 minutos más tarde.
  4. El mismo proceso se repite de nuevo.
  5. La última tarea en segundo plano se recibe y la aplicación actualiza de nuevo sus datos y la interfaz de usuario. Puesto que esta es la puntuación final, no programa una nueva actualización en segundo plano.

Programación de la actualización en segundo plano

Dado el escenario anterior, la aplicación MonkeySoccer puede usar el código siguiente para programar una actualización en segundo plano:

private void ScheduleNextBackgroundUpdate ()
{
  // Create a fire date 30 minutes into the future
  var fireDate = NSDate.FromTimeIntervalSinceNow (30 * 60);

  // Create
  var userInfo = new NSMutableDictionary ();
  userInfo.Add (new NSString ("LastActiveDate"), NSDate.FromTimeIntervalSinceNow(0));
  userInfo.Add (new NSString ("Reason"), new NSString ("UpdateScore"));

  // Schedule for update
  WKExtension.SharedExtension.ScheduleBackgroundRefresh (fireDate, userInfo, (error) => {
    // Was the Task successfully scheduled?
    if (error == null) {
      // Yes, handle if needed
    } else {
      // No, report error
    }
  });
}

Crea un nuevo NSDate de 30 minutos en el futuro cuando la aplicación quiere estar en estado de desabaste y crea un NSMutableDictionary para contener los detalles de la tarea solicitada. El método ScheduleBackgroundRefresh de SharedExtension se usa para solicitar la programación de la tarea.

El sistema devolverá un NSError si no pudo programar la tarea solicitada.

Procesamiento de la actualización

A continuación, eche un vistazo más detallado a la ventana de 5 minutos en la que se muestran los pasos necesarios para actualizar la puntuación:

Ventana de 5 minutos en la que se muestran los pasos necesarios para actualizar la puntuación

  1. A las 7:30:02 p. m., el sistema despierta la aplicación y se le da la tarea en segundo plano de actualización. Su primera prioridad es obtener las puntuaciones más recientes del servidor. Consulte Programación de una NSUrlSession a continuación.
  2. A las 7:30:05 la aplicación completa la tarea original, el sistema pone la aplicación en suspensión y continúa descargando los datos solicitados en segundo plano.
  3. Cuando el sistema completa la descarga, crea una nueva tarea para reactivar la aplicación para que pueda procesar la información descargada. Consulte Control de tareas en segundo plano y Control de la descarga completa de aquí abajo.
  4. La aplicación guarda la información actualizada y marca la tarea completada. Es posible que el desarrollador se sienta tentado a actualizar la interfaz de usuario de la aplicación en este momento, pero Apple sugiere programar una tarea de instantánea para controlar ese proceso. Consulte Programación de una actualización de instantáneas de aquí abajo.
  5. La aplicación recibe la tarea instantánea, actualiza su interfaz de usuario y marca la tarea completada. Consulte Control de una actualización de instantáneas de aquí abajo.

Programación de una NSUrlSession

El código siguiente se puede usar para programar la descarga de las puntuaciones más recientes:

private void ScheduleURLUpdateSession ()
{
  // Create new configuration
  var configuration = NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration ("com.example.urlsession");

  // Create new session
  var backgroundSession = NSUrlSession.FromConfiguration (configuration);

  // Create and start download task
  var downloadTask = backgroundSession.CreateDownloadTask (new NSUrl ("https://example.com/gamexxx/currentScores.json"));
  downloadTask.Resume ();
}

Configura y crea un nuevo NSUrlSession y, a continuación, usa esa sesión para crear una nueva tarea de descarga mediante el método CreateDownloadTask. Llama al método Resume de la tarea de descarga para iniciar la sesión.

Control de tareas en segundo plano

Al invalidar el método HandleBackgroundTasks de WKExtensionDelegate, la aplicación puede controlar las tareas en segundo plano entrantes:

using System;
using System.Collections.Generic;
using Foundation;
using WatchKit;

namespace MonkeySoccer.MonkeySoccerExtension
{
  public class ExtensionDelegate : WKExtensionDelegate
  {
    #region Computed Properties
    public List<WKRefreshBackgroundTask> PendingTasks { get; set; } = new List<WKRefreshBackgroundTask> ();
    #endregion

    ...

    #region Public Methods
    public void CompleteTask (WKRefreshBackgroundTask task)
    {
      // Mark the task completed and remove from the collection
      task.SetTaskCompleted ();
      PendingTasks.Remove (task);
    }
    #endregion

    #region Override Methods
    public override void HandleBackgroundTasks (NSSet<WKRefreshBackgroundTask> backgroundTasks)
    {
      // Handle background request
      foreach (WKRefreshBackgroundTask task in backgroundTasks) {
        // Is this a background session task?
        var urlTask = task as WKUrlSessionRefreshBackgroundTask;
        if (urlTask != null) {
          // Create new configuration
          var configuration = NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration (urlTask.SessionIdentifier);

          // Create new session
          var backgroundSession = NSUrlSession.FromConfiguration (configuration, new BackgroundSessionDelegate (this, task), null);

          // Keep track of all pending tasks
          PendingTasks.Add (task);
        } else {
          // Ensure that all tasks are completed
          task.SetTaskCompleted ();
        }
      }
    }
    #endregion

    ...
  }
}

El método HandleBackgroundTasks recorre en ciclos todas las tareas que el sistema ha enviado a la aplicación (en backgroundTasks) buscando un WKUrlSessionRefreshBackgroundTask. Si se encuentra uno, vuelve a unirse a la sesión y adjunta un NSUrlSessionDownloadDelegate para controlar la finalización de la descarga (consulte Control de la descarga completando de aquí abajo):

// Create new session
var backgroundSession = NSUrlSession.FromConfiguration (configuration, new BackgroundSessionDelegate (this, task), null);

Mantiene un identificador en la tarea hasta que se haya completado agregándolo a una colección:

public List<WKRefreshBackgroundTask> PendingTasks { get; set; } = new List<WKRefreshBackgroundTask> ();
...

// Keep track of all pending tasks
PendingTasks.Add (task);

Todas las tareas enviadas a la aplicación deben completarse, para cualquier tarea que no se controle actualmente, marque que se ha completado:

if (urlTask != null) {
  ...
} else {
  // Ensure that all tasks are completed
  task.SetTaskCompleted ();
}

Control de la descarga completada

La aplicación MonkeySoccer usa el siguiente NSUrlSessionDownloadDelegate delegado para controlar la descarga completando y procesando los datos solicitados:

using System;
using Foundation;
using WatchKit;

namespace MonkeySoccer.MonkeySoccerExtension
{
  public class BackgroundSessionDelegate : NSUrlSessionDownloadDelegate
  {
    #region Computed Properties
    public ExtensionDelegate WatchExtensionDelegate { get; set; }

    public WKRefreshBackgroundTask Task { get; set; }
    #endregion

    #region Constructors
    public BackgroundSessionDelegate (ExtensionDelegate extensionDelegate, WKRefreshBackgroundTask task)
    {
      // Initialize
      this.WatchExtensionDelegate = extensionDelegate;
      this.Task = task;
    }
    #endregion

    #region Override Methods
    public override void DidFinishDownloading (NSUrlSession session, NSUrlSessionDownloadTask downloadTask, NSUrl location)
    {
      // Handle the downloaded data
      ...

      // Mark the task completed
      WatchExtensionDelegate.CompleteTask (Task);

    }
    #endregion
  }
}

Cuando se inicializa, mantiene un identificador tanto para el ExtensionDelegate como para el WKRefreshBackgroundTask que lo generó. Invalida el método DidFinishDownloading para controlar la finalización de la descarga. A continuación, usa el método CompleteTask de ExtensionDelegate para informar a la tarea de que se ha completado y quitarla de la colección de tareas pendientes. Consulte Control de tareas en segundo plano de arriba.

Programación de una actualización de instantáneas

El código siguiente se puede usar para programar una tarea de instantáneas para actualizar la interfaz de usuario con las puntuaciones más recientes:

private void ScheduleSnapshotUpdate ()
{
  // Create a fire date of now
  var fireDate = NSDate.FromTimeIntervalSinceNow (0);

  // Create user info dictionary
  var userInfo = new NSMutableDictionary ();
  userInfo.Add (new NSString ("lastActiveDate"), NSDate.FromTimeIntervalSinceNow (0));
  userInfo.Add (new NSString ("reason"), new NSString ("UpdateScore"));

  // Schedule for update
  WKExtension.SharedExtension.ScheduleSnapshotRefresh (fireDate, userInfo, (error) => {
    // Was the Task successfully scheduled?
    if (error == null) {
      // Yes, handle if needed
    } else {
      // No, report error
    }
  });
}

Como en el método ScheduleURLUpdateSession anterior, crea un nuevo NSDate para cuando la aplicación quiere estar despertada y crea un NSMutableDictionary para contener los detalles de la tarea solicitada. El método ScheduleSnapshotRefresh de SharedExtension se usa para solicitar la programación de la tarea.

El sistema devolverá un NSError si no pudo programar la tarea solicitada.

Control de una actualización de instantáneas

Para controlar la tarea de instantáneas, el método HandleBackgroundTasks (consulte Control de tareas en segundo plano de arriba) se modifica para tener un aspecto similar al siguiente:

public override void HandleBackgroundTasks (NSSet<WKRefreshBackgroundTask> backgroundTasks)
{
  // Handle background request
  foreach (WKRefreshBackgroundTask task in backgroundTasks) {
    // Take action based on task type
    if (task is WKUrlSessionRefreshBackgroundTask) {
      var urlTask = task as WKUrlSessionRefreshBackgroundTask;

      // Create new configuration
      var configuration = NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration (urlTask.SessionIdentifier);

      // Create new session
      var backgroundSession = NSUrlSession.FromConfiguration (configuration, new BackgroundSessionDelegate (this, task), null);

      // Keep track of all pending tasks
      PendingTasks.Add (task);
    } else if (task is WKSnapshotRefreshBackgroundTask) {
      var snapshotTask = task as WKSnapshotRefreshBackgroundTask;

      // Update UI
      ...

      // Create a expiration date 30 minutes into the future
      var expirationDate = NSDate.FromTimeIntervalSinceNow (30 * 60);

      // Create user info dictionary
      var userInfo = new NSMutableDictionary ();
      userInfo.Add (new NSString ("lastActiveDate"), NSDate.FromTimeIntervalSinceNow (0));
      userInfo.Add (new NSString ("reason"), new NSString ("UpdateScore"));

      // Mark task complete
      snapshotTask.SetTaskCompleted (false, expirationDate, userInfo);
    } else {
      // Ensure that all tasks are completed
      task.SetTaskCompleted ();
    }
  }
}

El método comprueba el tipo de Tarea que se está procesando. Si es un objeto WKSnapshotRefreshBackgroundTask que obtiene acceso a la tarea:

var snapshotTask = task as WKSnapshotRefreshBackgroundTask;

El método actualiza la interfaz de usuario y, a continuación, crea un NSDate para indicar al sistema cuándo la instantánea estará obsoleta. Crea un NSMutableDictionary con información de usuario para describir la nueva instantánea y marca la tarea de instantánea completada con esta información:

// Mark task complete
snapshotTask.SetTaskCompleted (false, expirationDate, userInfo);

Además, también indica a la tarea de instantánea que la aplicación no vuelve al estado predeterminado (en el primer parámetro). Las aplicaciones que no tienen ningún concepto de estado predeterminado siempre deben establecer esta propiedad en true.

Utilizar eficazmente

Como se ve en el ejemplo anterior de la ventana de cinco minutos que la aplicación MonkeySoccer tomó para actualizar sus puntuaciones, trabajando de forma eficaz y usando las nuevas tareas en segundo plano watchOS 3, la aplicación solo estaba activa durante un total de 15 segundos:

La aplicación solo estaba activa durante un total de 15 segundos

Esto reduce el impacto que tendrá la aplicación tanto en los recursos de Apple Watch disponibles como en la duración de la batería, y también permite que la aplicación funcione mejor con otras aplicaciones que se ejecutan en el reloj.

Funcionamiento de la programación

Mientras una aplicación watchOS 3 está en primer plano, siempre está programada para ejecutarse y puede realizar cualquier tipo de procesamiento necesario, como actualizar datos o volver a dibujar su interfaz de usuario. Cuando la aplicación se mueve en segundo plano, normalmente se suspende por el sistema y se detienen todas las operaciones en tiempo de ejecución.

Mientras la aplicación está en segundo plano, el sistema puede estar dirigido a ejecutar rápidamente una tarea específica. Por lo tanto, en watchOS 2, el sistema podría reactivar temporalmente una aplicación en segundo plano para hacer cosas como controlar una notificación de aspecto largo o actualizar la complicación de la aplicación. En watchOS 3, hay varias formas nuevas de ejecutar una aplicación en segundo plano.

Mientras una aplicación está en segundo plano, el sistema impone varios límites:

  • Solo se da unos segundos para completar cualquier tarea determinada. El sistema tiene en cuenta no solo la cantidad de tiempo transcurrido, sino también la cantidad de energía de CPU que consume la aplicación para derivar este límite.
  • Cualquier aplicación que supere sus límites se eliminará con los siguientes códigos de error:
    • CPU: 0xc51bad01
    • Time: 0xc51bad02
  • El sistema impondrá límites diferentes en función del tipo de tarea en segundo plano que ha pedido a la aplicación que realice. Por ejemplo, las tareas de WKApplicationRefreshBackgroundTask y WKURLSessionRefreshBackgroundTask se proporcionan un poco más tiempo de ejecución sobre otros tipos de tareas en segundo plano.

Complicaciones y actualizaciones de aplicaciones

Además de las nuevas tareas en segundo plano que Apple ha agregado a watchOS 3, las complicaciones de una aplicación watchOS pueden tener un efecto sobre cómo y cuándo la aplicación recibe actualizaciones en segundo plano.

Las complicaciones son pequeños elementos visuales que proporcionan información útil de un vistazo. Dependiendo de la cara de reloj seleccionada, el usuario tiene la capacidad de personalizar una cara de reloj con una o varias complicaciones que puede proporcionar una aplicación de inspección en watchOS 3.

Si el usuario incluye una de las complicaciones de la aplicación en su cara de reloj, proporciona a la aplicación las siguientes ventajas actualizadas:

  • Hace que el sistema mantenga la aplicación en un estado listo para iniciarse, donde intenta iniciar la aplicación en segundo plano, lo mantiene en memoria y le da tiempo adicional para actualizar.
  • Se garantizan al menos 50 actualizaciones de inserción al día.

El desarrollador siempre debe esforzarse por crear complicaciones atractivas para que sus aplicaciones muestran al usuario a agregarlos a su cara de reloj por las razones enumeradas anteriormente.

En watchOS 2, las complicaciones eran la forma principal de que una aplicación recibió tiempo de ejecución mientras estaba en segundo plano. En watchOS 3, se garantiza que una aplicación de complicaciones reciba varias actualizaciones por hora, pero puede usar WKExtensions para solicitar más tiempo de ejecución para actualizar sus complicaciones.

Eche un vistazo al código siguiente que se usa para actualizar la complicación desde la aplicación iPhone conectada:

using System;
using WatchConnectivity;
using UIKit;
using Foundation;
using System.Collections.Generic;
using System.Linq;
...

private void UpdateComplication ()
{

  // Get session and the number of remaining transfers
  var session = WCSession.DefaultSession;
  var transfers = session.RemainingComplicationUserInfoTransfers;

  // Create user info dictionary
  var iconattrs = new Dictionary<NSString, NSObject>
    {
      {new NSString ("lastActiveDate"), NSDate.FromTimeIntervalSinceNow (0)},
      {new NSString ("reason"), new NSString ("UpdateScore")}
    };

  var userInfo = NSDictionary<NSString, NSObject>.FromObjectsAndKeys (iconattrs.Values.ToArray (), iconattrs.Keys.ToArray ());

  // Take action based on the number of transfers left
  if (transfers < 1) {
    // No transfers left, either attempt to send or inform
    // user of situation.
    ...
  } else if (transfers < 11) {
    // Running low on transfers, only send on important updates
    // else conserve for a significant change.
    ...
  } else {
    // Send data
    session.TransferCurrentComplicationUserInfo (userInfo);
  }
}

Usa la propiedad RemainingComplicationUserInfoTransfers de WCSession para ver cuántas transferencias de alta prioridad ha dejado la aplicación durante el día y, a continuación, realiza acciones en función de ese número. Si la aplicación comienza a ejecutarse poco en las transferencias, puede evitar el envío de actualizaciones secundarias y enviar información solo cuando hay un cambio significativo.

Programación y Dock

En watchOS 3, Apple ha agregado el Dock, donde los usuarios pueden anclar sus aplicaciones favoritas y acceder rápidamente a ellas. Cuando el usuario presiona el botón lateral en Apple Watch, se mostrará una galería de instantáneas de aplicaciones ancladas. El usuario puede deslizar el dedo hacia la izquierda o hacia la derecha para encontrar la aplicación deseada y, a continuación, pulsar la aplicación para iniciarla para reemplazar la instantánea por la interfaz de la aplicación en ejecución.

El Dock

El sistema toma periódicamente instantáneas de la interfaz de usuario de la aplicación y las usa para rellenar la documentación. WatchOS ofrece a la aplicación la oportunidad de actualizar su contenido y su interfaz de usuario antes de tomar esta instantánea.

Las aplicaciones que se han anclado al dock pueden esperar lo siguiente:

  • Recibirán un mínimo de una actualización por hora. Esto incluye una tarea de actualización de aplicaciones y una tarea de instantáneas.
  • El presupuesto de actualización se distribuye entre todas las aplicaciones de Dock. Por lo tanto, cuantos menos aplicaciones haya anclado el usuario, más actualizaciones potenciales recibirá cada aplicación.
  • La aplicación se mantendrá en memoria para que la aplicación se reanude rápidamente cuando se selecciona desde Dock.

La última aplicación que ejecutó el usuario se considerará la aplicación Usados más recientemente y ocupará la última ranura en Dock. Desde allí, el usuario puede elegir anclarlo permanentemente al Dock. Los usados más recientemente se tratarán como cualquier otra aplicación favorita que el usuario ya haya anclado a Dock.

Importante

Las aplicaciones que solo se han agregado a la pantalla principal no se proporcionarán programación normal. Para recibir actualizaciones periódicas de programación y en segundo plano, se debe agregar una aplicación a Dock.

Como se ha indicado anteriormente en este documento, las instantáneas son muy importantes en watchOS 3, ya que funcionan como imágenes de vista previa e inicio para la aplicación. Si el usuario se establece en una aplicación en Dock, se expandirá a pantalla completa, escribirá el primer plano y empezará a ejecutarse, por lo que es imperativo que la instantánea esté actualizada.

Puede haber ocasiones en las que el sistema decida que necesita una instantánea nueva de la interfaz de usuario de la aplicación. En estas situaciones, la solicitud de instantánea no contará con el presupuesto en tiempo de ejecución de la aplicación. A continuación se desencadena una solicitud de instantánea del sistema:

  • Una actualización de escala de tiempo de complicaciones.
  • Interacción del usuario con la notificación de una aplicación.
  • Cambiar del primer plano al estado de segundo plano.
  • Después de una hora de estar en el estado de segundo plano, por lo que la aplicación puede volver al estado predeterminado.
  • Cuando watchOS arranca por primera vez.

Procedimientos recomendados

Apple sugiere los siguientes procedimientos recomendados al trabajar con tarea en segundo plano:

  • Programe con tanta frecuencia como sea necesario actualizar la aplicación. Cada vez que la aplicación se ejecuta, debe volver a evaluar sus necesidades futuras y ajustar esta programación según sea necesario.
  • Si el sistema envía una tarea de actualización en segundo plano y la aplicación no requiere una actualización, aplaza el trabajo hasta que realmente se requiera una actualización.
  • Tenga en cuenta todas las oportunidades de tiempo de ejecución disponibles para una aplicación:
    • Activación en primer plano y acoplamiento.
    • Notificaciones.
    • Actualizaciones de complicaciones.
    • Actualizaciones en segundo plano.
  • Use ScheduleBackgroundRefresh para tiempo de ejecución en segundo plano de uso general, como:
    • Sondear el sistema para obtener información.
    • Programar futuro NSURLSessions para solicitar datos en segundo plano.
    • Transiciones de tiempo conocidas.
    • Desencadenar actualizaciones de complicaciones.

Procedimientos recomendados de instantáneas

Al trabajar con actualizaciones de instantáneas, Apple realiza las sugerencias siguientes:

  • Invalide las instantáneas solo cuando sea necesario, por ejemplo, cuando hay un cambio de contenido significativo.
  • Evite la invalidación de instantáneas de alta frecuencia. Por ejemplo, una aplicación de temporizador no debe actualizar la instantánea cada segundo, solo debe realizarse cuando el temporizador haya finalizado.

Flujo de datos de la aplicación

Apple sugiere lo siguiente para trabajar con el flujo de datos:

Diagrama de flujo de datos de la aplicación

Un evento externo (como Conectividad de inspección) activa la aplicación. Esto obliga a la aplicación a actualizar su modelo de datos (que representa el estado actual de las aplicaciones). Como resultado del cambio del modelo de datos, la aplicación tendrá que actualizar sus complicaciones, solicitar una nueva instantánea, posiblemente iniciar un NSURLSession en segundo plano para extraer más datos y programar más actualizaciones en segundo plano.

El ciclo de vida de la aplicación

Debido a Dock y la capacidad de anclar aplicaciones favoritas a ella, Apple piensa que los usuarios se moverán entre aplicaciones mucho más, mucho más a menudo, lo hicieron con watchOS 2. Como resultado, la aplicación debe estar lista para controlar este cambio y moverse entre los estados en primer plano y en segundo plano rápidamente.

Apple tiene las siguientes sugerencias:

  • Asegúrese de que la aplicación finaliza cualquier tarea en segundo plano lo antes posible al escribir la activación en primer plano.
  • Asegúrese de finalizar todo el trabajo en primer plano antes de escribir el fondo llamando a NSProcessInfo.PerformExpiringActivity.
  • Al probar una aplicación en el simulador de watchOS, no se aplicará ninguno de los presupuestos de tareas para que una aplicación pueda actualizar tanto como sea necesario para probar correctamente una característica.
  • Pruebe siempre el hardware real de Apple Watch para asegurarse de que la aplicación no se está ejecutando más allá de sus presupuestos antes de publicar en iTunes Connect.
  • Apple sugiere mantener apple Watch en el cargador mientras se prueba y depura.
  • Asegúrese de que tanto el inicio en frío como la reanudación de una aplicación se prueban exhaustivamente.
  • Compruebe que se están completando todas las tareas de la aplicación.
  • Puede variar el número de aplicaciones ancladas en Dock para probar los escenarios de mejor y peor caso.

Resumen

En este artículo se han tratado las mejoras que Apple ha realizado para watchOS y cómo se pueden usar para mantener actualizada una aplicación de inspección. En primer lugar, se trataron todas las nuevas tareas en segundo plano que Apple ha agregado en watchOS 3. A continuación, se trata el ciclo de vida de la API en segundo plano y cómo implementar tareas en segundo plano en una aplicación de Xamarin watchOS. Por último, se explica cómo funciona la programación y se proporcionan algunos procedimientos recomendados.