Partilhar via


Tarefas em segundo plano do watchOS no Xamarin

Com o watchOS 3, há três maneiras principais de um aplicativo de relógio manter suas informações atualizadas:

  • Usando uma das várias novas tarefas em segundo plano.
  • Ter uma de suas complicações no mostrador do relógio (dando-lhe tempo extra para atualizar).
  • Ter o usuário fixando o aplicativo no novo Dock (onde é mantido na memória e atualizado com frequência).

Mantendo um aplicativo atualizado

Antes de discutir todas as maneiras pelas quais um desenvolvedor pode manter os dados e a Interface do Usuário de um aplicativo watchOS atualizados e atualizados, esta seção analisará um conjunto típico de padrões de uso e como um usuário pode se mover entre seu iPhone e seu Apple Watch ao longo do dia com base na hora do dia e na atividade que está fazendo atualmente (como dirigir).

Veja o exemplo seguinte:

Como um usuário pode se mover entre o iPhone e o Apple Watch ao longo do dia

  1. Pela manhã, enquanto espera na fila para um café, o usuário navega pelas notícias atuais em seu iPhone por vários minutos.
  2. Antes de sair do café, eles verificam rapidamente o tempo com uma complicação no mostrador do relógio.
  3. Antes do almoço, eles usam o aplicativo Mapas no iPhone para encontrar um restaurante próximo e reservar uma reserva para atender um cliente.
  4. Ao viajar para o restaurante, eles recebem uma notificação no Apple Watch e, com uma rápida olhada, sabem que seu compromisso de almoço está atrasado.
  5. À noite, eles usam o aplicativo Mapas no iPhone para verificar o trânsito antes de voltar para casa.
  6. No caminho para casa, eles recebem uma notificação do iMessage no Apple Watch pedindo para pegar um pouco de leite e usam o recurso de resposta rápida para enviar a resposta "OK".

Devido à natureza de "rápida olhada" (menos de três segundos) de como um usuário está querendo usar um aplicativo do Apple Watch, normalmente não há tempo suficiente para o aplicativo buscar as informações desejadas e atualizar sua interface do usuário antes de exibi-las ao usuário.

Usando as novas APIs que a Apple incluiu no watchOS 3, o aplicativo pode agendar uma atualização em segundo plano e ter as informações desejadas prontas antes que o usuário solicite. Veja o exemplo da Complicação do Tempo discutida acima:

Um exemplo da complicação do tempo

  1. O aplicativo agenda para ser acordado pelo sistema em um horário específico.
  2. O aplicativo busca as informações necessárias para gerar a atualização.
  3. O aplicativo regenera sua interface do usuário para refletir os novos dados.
  4. Quando o usuário olha para a Complicação do aplicativo, ele tem informações atualizadas sem que o usuário precise esperar pela atualização.

Como visto acima, o sistema watchOS ativa o aplicativo usando uma ou mais Tarefas, das quais tem um pool muito limitado disponível:

O sistema watchOS ativa o aplicativo usando uma ou mais Tarefas

A Apple sugere aproveitar ao máximo essa tarefa (já que é um recurso tão limitado ao aplicativo), mantendo-a até que o aplicativo termine o processo de atualização.

O sistema entrega essas tarefas chamando o novo HandleBackgroundTasks método do WKExtensionDelegate delegado. Por exemplo:

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

Quando o aplicativo tiver concluído a Tarefa fornecida, ele a devolverá ao sistema marcando-a como concluída:

A Tarefa retorna ao sistema marcando-a como concluída

Novas tarefas em segundo plano

O watchOS 3 introduz várias tarefas em segundo plano que um aplicativo pode usar para atualizar suas informações, garantindo que ele tenha o conteúdo que o usuário precisa antes de abrir o aplicativo, como:

  • Atualização do aplicativo em segundo plano - A tarefa WKApplicationRefreshBackgroundTask permite que o aplicativo atualize seu estado em segundo plano. Normalmente, isso incluirá outra tarefa, como baixar novo conteúdo da Internet usando um NSUrlSession.
  • Atualização de instantâneo em segundo plano - A tarefa WKSnapshotRefreshBackgroundTask permite que o aplicativo atualize seu conteúdo e sua interface do usuário antes que o sistema tire um instantâneo que será usado para preencher o Dock.
  • Conectividade de observação em segundo plano - A tarefa WKWatchConnectivityRefreshBackgroundTask é iniciada para o aplicativo quando ele recebe dados em segundo plano do iPhone emparelhado.
  • Sessão de URL em segundo plano - A tarefa WKURLSessionRefreshBackgroundTask é iniciada para o aplicativo quando uma transferência em segundo plano requer autorização ou é concluída (com êxito ou com erro).

Essas tarefas serão abordadas em detalhes nas seções abaixo.

WKApplicationRefreshBackgroundTask

O WKApplicationRefreshBackgroundTask é uma tarefa genérica que pode ser agendada para que o aplicativo seja acordado em uma data futura:

Um WKApplicationRefreshBackgroundTask acordado em uma data futura

Dentro do tempo de execução da Tarefa, o aplicativo pode fazer qualquer tipo de processamento local, como atualizar uma linha do tempo de Complicação ou buscar alguns dados necessários com um NSUrlSessionarquivo .

WKURLSessionRefreshBackgroundTask

O sistema enviará um WKURLSessionRefreshBackgroundTask quando os dados terminarem de ser baixados e estiverem prontos para serem processados pelo aplicativo:

O WKURLSessionRefreshBackgroundTask quando o download dos dados tiver terminado

Um aplicativo não é deixado em execução enquanto os dados são baixados em segundo plano. Em vez disso, o aplicativo agenda a solicitação de dados, então ela é suspensa e o sistema lida com o download dos dados, só despertando o aplicativo quando o download for concluído.

WKSnapshotRefreshBackgroundTask

No watchOS 3, a Apple adicionou o Dock onde os usuários podem fixar seus aplicativos favoritos e acessá-los rapidamente. Quando o usuário pressiona o botão lateral no Apple Watch, uma galeria de instantâneos fixos do aplicativo será exibida. O usuário pode deslizar para a esquerda ou para a direita para encontrar o aplicativo desejado e, em seguida, tocar no aplicativo para iniciá-lo substituindo o Instantâneo pela interface do aplicativo em execução.

Substituindo o instantâneo pela interface de aplicativos em execução

O sistema tira periodicamente instantâneos da interface do usuário do aplicativo (enviando um WKSnapshotRefreshBackgroundTask) e usa esses instantâneos para preencher o Dock. O watchOS dá ao aplicativo a oportunidade de atualizar seu conteúdo e interface do usuário antes que esse instantâneo seja tirado.

Os instantâneos são muito importantes no watchOS 3, uma vez que funcionam como imagens de visualização e de inicialização para o aplicativo. Se o usuário se instalar em um aplicativo no Dock, ele será expandido para tela cheia, entrará no primeiro plano e começará a ser executado, portanto, é imperativo que o Snapshot esteja atualizado:

Se o usuário se instalar em um aplicativo no Dock, ele será expandido para tela cheia

Novamente, o sistema emitirá um WKSnapshotRefreshBackgroundTask para que o aplicativo possa se preparar (atualizando os dados e a interface do usuário) antes que o instantâneo seja tirado:

O aplicativo pode se preparar atualizando os dados e a interface do usuário antes que o instantâneo seja tirado

Quando o aplicativo marcar como WKSnapshotRefreshBackgroundTask concluído, o sistema tirará automaticamente um instantâneo da interface do usuário do aplicativo.

Importante

É importante sempre agendar um WKSnapshotRefreshBackgroundTask após o aplicativo ter recebido novos dados e atualizado sua interface do usuário ou o usuário não verá as informações modificadas.

Além disso, quando o usuário recebe uma notificação do aplicativo e toca nela para trazer o aplicativo para o primeiro plano, o Snapshot precisa estar atualizado, pois também está atuando como a tela de inicialização:

O usuário recebe uma notificação do aplicativo e toca nela para trazer o aplicativo para o primeiro plano

Se tiver passado mais de uma hora desde que o usuário interagiu com um aplicativo watchOS, ele poderá retornar ao seu Estado Padrão. O Estado Padrão pode significar coisas diferentes para aplicativos diferentes e, com base no design de um aplicativo, ele pode não ter um Estado Padrão.

WKWatchConnectivityRefreshBackgroundTask

No watchOS 3, a Apple integrou a conectividade do relógio com a API Background Refresh por meio do novo WKWatchConnectivityRefreshBackgroundTask. Usando esse novo recurso, um aplicativo para iPhone pode fornecer dados novos para seu equivalente do aplicativo do relógio, enquanto o aplicativo watchOS está sendo executado em segundo plano:

Um aplicativo para iPhone pode fornecer dados atualizados para seu equivalente do aplicativo do relógio, enquanto o aplicativo watchOS está sendo executado em segundo plano

Iniciar um Push de Complicação, Contexto do Aplicativo, enviar um arquivo ou atualizar as Informações do Usuário do aplicativo para iPhone ativará o aplicativo Apple Watch em segundo plano.

Quando o aplicativo do relógio é ativado por meio de um WKWatchConnectivityRefreshBackgroundTask ele precisará usar os métodos de API padrão para receber os dados do aplicativo do iPhone.

O fluxo de dados WKWatchConnectivityRefreshBackgroundTask

  1. Verifique se a Sessão foi ativada.
  2. Monitore a nova HasContentPending propriedade desde que o valor seja true, o aplicativo ainda tem dados para processar. Como antes, o aplicativo deve manter a Tarefa até concluir o processamento de todos os dados.
  3. Quando não houver mais dados a serem processados (HasContentPending = false), marque a Tarefa concluída para retorná-la ao sistema. Se isso não for feito, o tempo de execução em segundo plano alocado do aplicativo, resultando em um relatório de falha.

O ciclo de vida da API em segundo plano

Colocando todas as partes da nova API de Tarefas em Segundo Plano juntas, um conjunto típico de interações teria a seguinte aparência:

O ciclo de vida da API em segundo plano

  1. Primeiro, o aplicativo watchOS agenda uma tarefa em segundo plano para ser despertada como algum ponto no futuro.
  2. O aplicativo é acordado pelo sistema e enviado uma tarefa.
  3. O aplicativo processa a Tarefa para concluir qualquer trabalho necessário.
  4. Como resultado do processamento da Tarefa, o aplicativo pode precisar agendar mais Tarefas em segundo plano para concluir mais trabalho no futuro, como baixar mais conteúdo usando um NSUrlSessionarquivo .
  5. O aplicativo marca a Tarefa concluída e a retorna ao sistema.

Usando os recursos com responsabilidade

É fundamental que um aplicativo watchOS se comporte de forma responsável dentro desse ecossistema, limitando sua drenagem dos recursos compartilhados do sistema.

Dê uma olhada no seguinte cenário:

Um aplicativo watchOS limita seu esgotamento dos recursos compartilhados do sistema

  1. O usuário inicia um aplicativo watchOS às 13:00.
  2. O aplicativo agenda uma tarefa para acordar e baixar novos conteúdos em uma hora às 14h.
  3. Às 13h50, o usuário reabre o aplicativo, o que permite atualizar seus dados e a interface do usuário neste momento.
  4. Em vez de permitir que a Tarefa ative o aplicativo novamente em 10 minutos, o aplicativo deve reagendar a Tarefa para ser executada uma hora mais tarde, às 14h50.

Embora cada aplicativo seja diferente, a Apple sugere encontrar padrões de uso, como os mostrados acima, para ajudar a conservar os recursos do sistema.

Implementando tarefas em segundo plano

Por exemplo, este documento usará o falso aplicativo de esportes MonkeySoccer que relata as pontuações de futebol para o usuário.

Dê uma olhada no seguinte cenário de uso típico:

O cenário de uso típico

O time de futebol favorito do usuário está jogando uma grande partida das 19:00 às 21:00, então o aplicativo deve esperar que o usuário esteja verificando a pontuação regularmente e decida sobre um intervalo de atualização de 30 minutos.

  1. O usuário abre o aplicativo e agenda uma Tarefa para atualização em segundo plano 30 minutos depois. A API em segundo plano permite que apenas um tipo de tarefa em segundo plano seja executado em um determinado momento.
  2. O aplicativo recebe a Tarefa e atualiza seus dados e sua interface do usuário e, em seguida, agenda outra Tarefa em segundo plano 30 minutos depois. É importante que o desenvolvedor se lembre de agendar outra tarefa em segundo plano, ou o aplicativo nunca será despertado novamente para obter mais atualizações.
  3. Novamente, o aplicativo recebe a Tarefa e atualiza seus dados, atualiza sua interface do usuário e agenda outra Tarefa em segundo plano 30 minutos depois.
  4. O mesmo processo se repete novamente.
  5. A última tarefa em segundo plano é recebida e o aplicativo atualiza novamente seus dados e interface do usuário. Como esta é a pontuação final, não há agendamento para uma nova atualização em segundo plano.

Agendamento para atualização em segundo plano

Dado o cenário acima, o aplicativo MonkeySoccer pode usar o seguinte código para agendar uma atualização em 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
    }
  });
}

Ele cria um novo NSDate 30 minutos no futuro quando o aplicativo quer ser acordado e cria um NSMutableDictionary para manter os detalhes da tarefa solicitada. O ScheduleBackgroundRefresh método do SharedExtension é usado para solicitar que a tarefa seja agendada.

O sistema retornará um NSError se não foi possível agendar a tarefa solicitada.

Processando a atualização

Em seguida, dê uma olhada mais de perto na janela de 5 minutos que mostra as etapas necessárias para atualizar a pontuação:

A janela de 5 minutos mostrando as etapas necessárias para atualizar a pontuação

  1. Às 19:30:02 o aplicativo é despertado pelo sistema e recebe a atualização em segundo plano da Tarefa. Sua primeira prioridade é obter as últimas pontuações do servidor. Consulte Agendando uma NSUrlSession abaixo.
  2. Às 7:30:05 o aplicativo conclui a tarefa original, o sistema coloca o aplicativo em repouso e continua a baixar os dados solicitados em segundo plano.
  3. Quando o sistema conclui o download, ele cria uma nova Tarefa para ativar o aplicativo para que ele possa processar as informações baixadas. Consulte Manipulando tarefas em segundo plano e Manipulando a conclusão do download abaixo.
  4. O aplicativo salva as informações atualizadas e marca a Tarefa concluída. O desenvolvedor pode ficar tentado a atualizar a interface do usuário do aplicativo neste momento, no entanto, a Apple sugere agendar uma tarefa de instantâneo para lidar com esse processo. Consulte Agendando uma atualização de instantâneo abaixo.
  5. O aplicativo recebe a Tarefa de Instantâneo, atualiza sua Interface do Usuário e marca a Tarefa concluída. Consulte Manipulando uma atualização de instantâneo abaixo.

Agendando uma NSUrlSession

O código a seguir pode ser usado para agendar o download das pontuações mais recentes:

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

Ele configura e cria um novo NSUrlSession, em seguida, usa essa sessão para criar uma nova tarefa de download usando o CreateDownloadTask método. Ele chama o Resume método da tarefa de download para iniciar a sessão.

Manipulando tarefas em segundo plano

Ao substituir o HandleBackgroundTasks método do WKExtensionDelegate, o aplicativo pode lidar com as tarefas em segundo plano de entrada:

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

    ...
  }
}

O HandleBackgroundTasks método percorre todas as Tarefas que o sistema enviou ao aplicativo (em backgroundTasks) procurando um WKUrlSessionRefreshBackgroundTaskarquivo . Se um for encontrado, ele reingressa na sessão e anexa um NSUrlSessionDownloadDelegate para lidar com a conclusão do download (consulte Manipulando a conclusão do download abaixo):

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

Ele mantém um identificador na Tarefa até que ela seja concluída, adicionando-a a uma coleção:

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

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

Todas as Tarefas enviadas para o aplicativo precisam ser concluídas, para qualquer tarefa que não esteja sendo manipulada no momento, marque-a como concluída:

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

Manipulando a conclusão do download

O aplicativo MonkeySoccer usa o seguinte NSUrlSessionDownloadDelegate delegado para lidar com a conclusão do download e processar os dados 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
  }
}

Quando inicializado, ele mantém uma alça para o ExtensionDelegate e o WKRefreshBackgroundTask que o gerou. Ele substitui o DidFinishDownloading método para manipular a conclusão do download. Em seguida, usa o CompleteTask método do ExtensionDelegate para informar a tarefa que ela foi concluída e removê-la da coleção de tarefas pendentes. Consulte Manipulando tarefas em segundo plano acima.

Agendando uma atualização de instantâneo

O código a seguir pode ser usado para agendar uma tarefa de instantâneo para atualizar a interface do usuário com as pontuações mais recentes:

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

Assim como ScheduleURLUpdateSession o método acima, ele cria um novo NSDate para quando o aplicativo deseja ser acordado e cria um NSMutableDictionary para manter os detalhes da tarefa solicitada. O ScheduleSnapshotRefresh método do SharedExtension é usado para solicitar que a tarefa seja agendada.

O sistema retornará um NSError se não foi possível agendar a tarefa solicitada.

Manipulando uma atualização de snapshot

Para manipular a Tarefa de Instantâneo, o HandleBackgroundTasks método (consulte Manipulando tarefas em segundo plano acima) é modificado para ter a seguinte aparência:

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

O método testa o tipo de Tarefa que está sendo processada. Se for um WKSnapshotRefreshBackgroundTask ele ganha acesso à tarefa:

var snapshotTask = task as WKSnapshotRefreshBackgroundTask;

O método atualiza a interface do usuário e, em seguida, cria um NSDate para informar ao sistema quando o instantâneo estará obsoleto. Ele cria um NSMutableDictionary com informações do usuário para descrever o novo instantâneo e marca a tarefa de instantâneo concluída com essas informações:

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

Além disso, ele também informa à Tarefa de Instantâneo que o aplicativo não está retornando ao Estado Padrão (no primeiro parâmetro). Os aplicativos que não têm o conceito de um Estado Padrão devem sempre definir essa propriedade como true.

Trabalhando com eficiência

Como visto no exemplo acima da janela de cinco minutos que o aplicativo MonkeySoccer levou para atualizar suas pontuações, trabalhando de forma eficiente e usando as novas tarefas em segundo plano do watchOS 3, o aplicativo ficou ativo apenas por um total de 15 segundos:

O aplicativo ficou ativo apenas por um total de 15 segundos

Isso reduz o impacto que o aplicativo terá nos recursos disponíveis do Apple Watch e na duração da bateria e também permite que o aplicativo funcione melhor com outros aplicativos executados no relógio.

Como funciona o agendamento

Embora um aplicativo watchOS 3 esteja em primeiro plano, ele está sempre programado para ser executado e pode fazer qualquer tipo de processamento necessário, como atualizar dados ou redesenhar sua interface do usuário. Quando o aplicativo se move para o segundo plano, ele geralmente é suspenso pelo sistema e todas as operações de tempo de execução são interrompidas.

Enquanto o aplicativo está em segundo plano, ele pode ser direcionado pelo sistema para executar rapidamente uma tarefa específica. Assim, no watchOS 2, o sistema pode ativar temporariamente um aplicativo em segundo plano para fazer coisas como lidar com uma notificação de aparência longa ou atualizar a Complicação do aplicativo. No watchOS 3, há várias novas maneiras de executar um aplicativo em segundo plano.

Enquanto um aplicativo está em segundo plano, o sistema impõe vários limites a ele:

  • São dados apenas alguns segundos para concluir qualquer tarefa. O sistema leva em consideração não apenas a quantidade de tempo passado, mas também quanta energia de CPU o aplicativo está consumindo para derivar esse limite.
  • Qualquer aplicativo que exceda seus limites será eliminado com os seguintes códigos de erro:
    • CPU - 0xc51bad01
    • Tempo - 0xc51bad02
  • O sistema imporá limites diferentes com base no tipo de Tarefa em Segundo Plano que pediu ao aplicativo para executar. Por exemplo, WKApplicationRefreshBackgroundTask e WKURLSessionRefreshBackgroundTask as Tarefas recebem tempos de execução um pouco mais longos em relação a outros tipos de Tarefas em Segundo Plano.

Complicações e atualizações de aplicativos

Além das novas Tarefas em Segundo Plano que a Apple adicionou ao watchOS 3, as Complicações de um aplicativo watchOS podem afetar como e quando o aplicativo recebe atualizações em segundo plano.

As complicações são pequenos elementos visuais que fornecem informações úteis em um piscar de olhos. Dependendo do mostrador selecionado, o usuário tem a capacidade de personalizar um mostrador de relógio com uma ou mais complicações que podem ser fornecidas por um aplicativo de relógio no watchOS 3.

Se o usuário incluir uma das Complicações do aplicativo no mostrador do relógio, ele dará ao aplicativo os seguintes benefícios atualizados:

  • Isso faz com que o sistema mantenha o aplicativo em um estado pronto para iniciar, onde ele tenta iniciar o aplicativo em segundo plano, o mantém na memória e lhe dá tempo extra para atualizar.
  • As complicações são garantidas pelo menos 50 atualizações push por dia.

O desenvolvedor deve sempre se esforçar para criar complicações atraentes para seus aplicativos para atrair o usuário a adicioná-los ao mostrador do relógio pelos motivos listados acima.

No watchOS 2, as complicações eram a principal maneira pela qual um aplicativo recebia tempo de execução em segundo plano. No watchOS 3, um aplicativo de complicação ainda terá a garantia de receber várias atualizações por hora, no entanto, ele pode usar WKExtensions para solicitar mais tempo de execução para atualizar suas complicações.

Dê uma olhada no seguinte código usado para atualizar a complicação do aplicativo do iPhone conectado:

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

Ele usa a RemainingComplicationUserInfoTransfers propriedade do para ver quantas transferências de WCSession alta prioridade o aplicativo deixou para o dia e, em seguida, executa ações com base nesse número. Se o aplicativo começar a ficar com poucas transferências, ele pode adiar o envio de pequenas atualizações e só enviar informações quando houver uma mudança significativa.

Agendamento e o Dock

No watchOS 3, a Apple adicionou o Dock onde os usuários podem fixar seus aplicativos favoritos e acessá-los rapidamente. Quando o usuário pressionar o botão lateral no Apple Watch, uma galeria de instantâneos de aplicativos fixados será exibida. O usuário pode deslizar para a esquerda ou para a direita para encontrar o aplicativo desejado e, em seguida, tocar no aplicativo para iniciá-lo substituindo o instantâneo pela interface do aplicativo em execução.

O Cais

O sistema tira periodicamente instantâneos da interface do usuário do aplicativo e usa esses instantâneos para preencher os Documentos. O watchOS dá ao aplicativo a oportunidade de atualizar seu conteúdo e interface do usuário antes que esse instantâneo seja tirado.

Os aplicativos que foram fixados no dock podem esperar o seguinte:

  • Eles receberão um mínimo de uma atualização por hora. Isso inclui uma Tarefa de Atualização de Aplicativo e uma Tarefa de Instantâneo.
  • O orçamento de atualização é distribuído entre todos os aplicativos no Dock. Portanto, quanto menos aplicativos o usuário fixar, mais atualizações potenciais cada aplicativo receberá.
  • O aplicativo será mantido na memória para que o aplicativo seja retomado rapidamente quando selecionado no Dock.

O último aplicativo executado pelo usuário será considerado o aplicativo usado mais recentemente e ocupará o último slot no Dock. A partir daí, o usuário pode optar por fixá-lo permanentemente no Dock. O mais recentemente usado será tratado como qualquer outro aplicativo favorito que o usuário já fixou no Dock.

Importante

Os aplicativos que foram adicionados apenas à tela inicial não receberão nenhum agendamento regular. Para receber agendamento regular e atualizações em segundo plano, um aplicativo deve ser adicionado ao Dock.

Como dito anteriormente neste documento, os instantâneos são muito importantes no watchOS 3, pois funcionam como imagens de visualização e de inicialização para o aplicativo. Se o usuário se instalar em um aplicativo no Dock, ele será expandido para tela cheia, entrará no primeiro plano e começará a ser executado, portanto, é imperativo que o Snapshot esteja atualizado.

Pode haver momentos em que o sistema decide que precisa de um novo instantâneo da interface do usuário do aplicativo. Nessas situações, a solicitação de instantâneo não contará para o orçamento de tempo de execução do aplicativo. O seguinte acionará uma solicitação de instantâneo do sistema:

  • Uma atualização da linha do tempo de complicação.
  • Interação do usuário com a notificação de um aplicativo.
  • Alternando do estado Primeiro Plano para o estado Plano de Fundo.
  • Após uma hora de estar no estado em segundo plano, para que o aplicativo possa retornar ao estado padrão.
  • Quando o watchOS inicializa pela primeira vez.

Práticas Recomendadas

A Apple sugere as seguintes práticas recomendadas ao trabalhar com tarefas em segundo plano:

  • Agende quantas vezes o aplicativo precisar ser atualizado. Toda vez que o aplicativo é executado, ele deve reavaliar suas necessidades futuras e ajustar esse cronograma conforme necessário.
  • Se o sistema enviar uma Tarefa de Atualização em Segundo Plano e o aplicativo não exigir uma atualização, adie o trabalho até que uma atualização seja realmente necessária.
  • Considere todas as oportunidades de tempo de execução disponíveis para um aplicativo:
    • Ativação de doca e primeiro plano.
    • Notificações.
    • Atualizações de complicação.
    • Atualizações em segundo plano.
  • Use ScheduleBackgroundRefresh para tempo de execução em segundo plano de uso geral, como:
    • Sondagem do sistema para obter informações.
    • Agende o futuro NSURLSessions para solicitar dados em segundo plano.
    • Transições de tempo conhecidas.
    • Disparando atualizações de complicação.

Práticas recomendadas de snapshot

Ao trabalhar com atualizações de instantâneo, a Apple faz as seguintes sugestões:

  • Invalide instantâneos somente quando necessário, por exemplo, quando houver uma alteração significativa de conteúdo.
  • Evite a invalidação de instantâneo de alta frequência. Por exemplo, um aplicativo de timer não deve atualizar o Snapshot a cada segundo, isso só deve ser feito quando o timer terminar.

Fluxo de dados do aplicativo

A Apple sugere o seguinte para trabalhar com fluxo de dados:

Diagrama de fluxo de dados do aplicativo

Um evento externo (como Watch Connectivity) ativa o aplicativo. Isso força o aplicativo a atualizar seu Modelo de Dados (que representa o estado atual do aplicativo). Como resultado da alteração do Modelo de Dados, o aplicativo precisará atualizar suas Complicações, solicitar um novo Instantâneo, possivelmente iniciar um plano de fundo NSURLSession para extrair mais dados e agendar novas atualizações em segundo plano.

O ciclo de vida do aplicativo

Por causa do Dock e da capacidade de fixar aplicativos favoritos nele, a Apple acha que os usuários estarão se movendo entre muito mais aplicativos, com muito mais frequência, do que fizeram com o watchOS 2. Como resultado, o aplicativo deve estar pronto para lidar com essa alteração e mover-se entre os estados de primeiro plano e plano de fundo rapidamente.

A Apple tem as seguintes sugestões:

  • Certifique-se de que o aplicativo conclua qualquer tarefa em segundo plano o mais rápido possível ao entrar na ativação em primeiro plano.
  • Certifique-se de concluir todo o trabalho de primeiro plano antes de entrar em segundo plano chamando NSProcessInfo.PerformExpiringActivity.
  • Ao testar um aplicativo no watchOS Simulator, nenhum dos orçamentos de tarefas será imposto para que um aplicativo possa atualizar o quanto for necessário para testar corretamente um recurso.
  • Sempre teste em hardware real do Apple Watch para garantir que o aplicativo não está sendo executado além de seus orçamentos antes de publicar no iTunes Connect.
  • A Apple sugere manter o Apple Watch no carregador durante os testes e depuração.
  • Certifique-se de que tanto a inicialização a frio quanto a retomada de um aplicativo sejam exaustivamente testadas.
  • Verifique se todas as Tarefas do aplicativo estão sendo concluídas.
  • Varie o número de aplicativos fixados no Dock para testar os melhores e os piores cenários.

Resumo

Este artigo abordou as melhorias que a Apple fez no watchOS e como elas podem ser usadas para manter um aplicativo de relógio atualizado. Primeiro, ele cobriu toda a nova tarefa em segundo plano que a Apple adicionou no watchOS 3. Em seguida, abordou o ciclo de vida da API em segundo plano e como implementar tarefas em segundo plano em um aplicativo watchOS Xamarin. Por fim, abordou como funciona o agendamento e deu algumas práticas recomendadas.