Como criar um mostrador de relógio

Este guia explica como implementar um serviço de mostrador de relógio personalizado para Android Wear 1.0. Instruções passo a passo são fornecidas para a criação de um serviço de mostrador de relógio digital despojado, seguido de mais código para criar um mostrador de relógio de estilo analógico.

Visão geral

Neste passo a passo, um serviço básico de mostrador de relógio é criado para ilustrar os fundamentos da criação de um mostrador de relógio Android Wear 1.0 personalizado. O serviço de mostrador inicial exibe um relógio digital simples que exibe a hora atual em horas e minutos:

A captura de tela mostra o mostrador inicial do relógio digital.

Depois que este mostrador de relógio digital é desenvolvido e testado, mais código é adicionado para atualizá-lo para um mostrador de relógio analógico mais sofisticado com três mãos:

A captura de tela mostra o mostrador analógico final do relógio.

Os serviços de face do relógio são agrupados e instalados como parte de um aplicativo Wear 1.0. Nos exemplos a seguir, MainActivity contém nada mais do que o código do modelo de aplicativo Wear 1.0 para que o serviço de mostrador do relógio possa ser empacotado e implantado no relógio inteligente como parte do aplicativo. Na verdade, este aplicativo servirá puramente como um veículo para obter o serviço de mostrador do relógio carregado no dispositivo Wear 1.0 (ou emulador) para depuração e teste.

Requisitos

Para implementar um serviço de mostrador de relógio, é necessário o seguinte:

  • Android 5.0 (API nível 21) ou superior no dispositivo ou emulador Wear.

  • As bibliotecas de suporte do Xamarin Android Wear devem ser adicionadas ao projeto Xamarin.Android.

Embora o Android 5.0 seja o nível mínimo de API para implementar um serviço de mostrador de relógio, o Android 5.1 ou posterior é recomendado. Os dispositivos Android Wear com Android 5.1 (API 22) ou superior permitem que os aplicativos Wear controlem o que é exibido na tela enquanto o dispositivo está no modo ambiente de baixo consumo de energia. Quando o dispositivo sai do modo ambiente de baixo consumo de energia, ele está no modo interativo. Para obter mais informações sobre esses modos, consulte Mantendo seu aplicativo visível.

Iniciar um projeto de aplicativo

Crie um novo projeto Android Wear 1.0 chamado WatchFace (para obter mais informações sobre como criar novos projetos Xamarin.Android, consulte Olá, Android):

Defina o nome do pacote como com.xamarin.watchface:

Além disso, role para baixo e habilite as permissões INTERNET e WAKE_LOCK :

Permissões necessárias

Em seguida, baixe preview.png – isso será adicionado à pasta drawables mais adiante neste passo a passo.

Adicionar o pacote Xamarin.Android Wear

Inicie o Gerenciador de Pacotes NuGet (no Visual Studio, clique com o botão direito do mouse em Referências no Gerenciador de Soluções e selecione Gerenciar Pacotes NuGet...). Atualize o projeto para a versão estável mais recente do Xamarin.Android.Wear:

Gerenciador de Pacotes NuGet adicionar

Em seguida, se Xamarin.Android.Support.v13 estiver instalado, desinstale-o:

Gerenciador de Pacotes NuGet remover

Crie e execute o aplicativo em um dispositivo ou emulador Wear (para obter mais informações sobre como fazer isso, consulte o Guia de Introdução ). Você deve ver a seguinte tela do aplicativo no dispositivo Wear:

Captura de tela do aplicativo

Neste ponto, o aplicativo Wear básico não tem a funcionalidade de mostrador de relógio porque ainda não fornece uma implementação de serviço de mostrador de relógio. Este serviço será adicionado em seguida.

CanvasWatchFaceService

O Android Wear implementa mostradores de relógio através da CanvasWatchFaceService classe. CanvasWatchFaceServiceé derivado de , que é derivado de WatchFaceServiceWallpaperService como mostrado no diagrama a seguir:

Diagrama de herança

CanvasWatchFaceService inclui um aninhado CanvasWatchFaceService.Engine; ele instancia um CanvasWatchFaceService.Engine objeto que faz o trabalho real de desenhar o mostrador do relógio. CanvasWatchFaceService.Engine é derivado de WallpaperService.Engine como mostrado no diagrama acima.

Não mostrado neste diagrama é um Canvas que CanvasWatchFaceService usa para desenhar o mostrador do relógio - isso Canvas é passado através do OnDraw método como descrito abaixo.

Nas seções a seguir, um serviço de mostrador de relógio personalizado será criado seguindo estas etapas:

  1. Defina uma classe chamada MyWatchFaceService que é derivada de CanvasWatchFaceService.

  2. Dentro MyWatchFaceServicedo , crie uma classe aninhada chamada MyWatchFaceEngine que é derivada de CanvasWatchFaceService.Engine.

  3. No MyWatchFaceService, implemente um CreateEngine método que instancia MyWatchFaceEngine e o retorna.

  4. No MyWatchFaceEngine, implemente o OnCreate método para criar o estilo do mostrador do relógio e executar quaisquer outras tarefas de inicialização.

  5. Implemente o OnDraw método de MyWatchFaceEngine. Esse método é chamado sempre que o mostrador do relógio precisa ser redesenhado (ou seja, invalidado). OnDraw é o método que desenha (e redefine) elementos do mostrador do relógio, como hora, minuto e segundos ponteiros.

  6. Implemente o OnTimeTick método de MyWatchFaceEngine. OnTimeTick é chamado pelo menos uma vez por minuto (nos modos ambiente e interativo) ou quando a data/hora foi alterada.

Para obter mais informações sobre CanvasWatchFaceServiceo , consulte a documentação da API do Android CanvasWatchFaceService . Da mesma forma, CanvasWatchFaceService.Engine explica a implementação real do mostrador do relógio.

Adicionar o CanvasWatchFaceService

Adicione um novo arquivo chamado MyWatchFaceService.cs (no Visual Studio, clique com o botão direito do mouse em WatchFace no Gerenciador de Soluções, clique em Adicionar > Novo Item..., e selecione Classe).

Substitua o conteúdo deste arquivo com o seguinte código:

using System;
using Android.Views;
using Android.Support.Wearable.Watchface;
using Android.Service.Wallpaper;
using Android.Graphics;

namespace WatchFace
{
    class MyWatchFaceService : CanvasWatchFaceService
    {
        public override WallpaperService.Engine OnCreateEngine()
        {
            return new MyWatchFaceEngine(this);
        }

        public class MyWatchFaceEngine : CanvasWatchFaceService.Engine
        {
            CanvasWatchFaceService owner;
            public MyWatchFaceEngine (CanvasWatchFaceService owner) : base(owner)
            {
                this.owner = owner;
            }
        }
    }
}

MyWatchFaceService (derivado de CanvasWatchFaceService) é o "programa principal" do mostrador do relógio. MyWatchFaceService implementa apenas um método, OnCreateEngine, que instancia e retorna um MyWatchFaceEngine objeto (MyWatchFaceEngine é derivado de CanvasWatchFaceService.Engine). O objeto instanciado MyWatchFaceEngine deve ser retornado como um WallpaperService.Enginearquivo . O objeto de encapsulamento MyWatchFaceService é passado para o construtor.

MyWatchFaceEngine é a implementação real do mostrador do relógio – ele contém o código que desenha o mostrador do relógio. Ele também lida com eventos do sistema, como mudanças de tela (modos ambiente/interativo, desligamento da tela, etc.).

Implementar o método Engine OnCreate

O OnCreate método inicializa o mostrador do relógio. Adicione o seguinte campo a MyWatchFaceEngine:

Paint hoursPaint;

Este Paint objeto será usado para desenhar a hora atual no mostrador do relógio. Em seguida, adicione o seguinte método a MyWatchFaceEngine:

public override void OnCreate(ISurfaceHolder holder)
{
    base.OnCreate (holder);

    SetWatchFaceStyle (new WatchFaceStyle.Builder(owner)
        .SetCardPeekMode (WatchFaceStyle.PeekModeShort)
        .SetBackgroundVisibility (WatchFaceStyle.BackgroundVisibilityInterruptive)
        .SetShowSystemUiTime (false)
        .Build ());

    hoursPaint = new Paint();
    hoursPaint.Color = Color.White;
    hoursPaint.TextSize = 48f;
}

OnCreate é chamado logo após MyWatchFaceEngine é iniciado. Ele configura o WatchFaceStyle (que controla como o dispositivo Wear interage com o usuário) e instancia o Paint objeto que será usado para exibir a hora.

A chamada para SetWatchFaceStyle faz o seguinte:

  1. Define o modo de visualização como PeekModeShort, o que faz com que as notificações apareçam como pequenos cartões de "espiar" na tela.

  2. Define a visibilidade em segundo plano como Interruptive, o que faz com que o plano de fundo de um cartão de visualização seja mostrado apenas brevemente se ele representar uma notificação interruptiva.

  3. Desativa a hora padrão da interface do usuário do sistema de ser desenhada no mostrador do relógio para que o mostrador do relógio personalizado possa exibir a hora.

Para obter mais informações sobre essas e outras opções de estilo de mostrador de relógio, consulte a documentação da API WatchFaceStyle.Builder do Android.

Após SetWatchFaceStyle a conclusão, OnCreate instancia o Paint objeto () e define sua cor comohoursPaint branco e seu tamanho de texto como 48 pixels (TextSize deve ser especificado em pixels).

Implementar o método Engine OnDraw

O OnDraw método é talvez o mais importante CanvasWatchFaceService.Engine – é o método que realmente desenha elementos do mostrador do relógio, como dígitos e ponteiros do mostrador do relógio. No exemplo a seguir, ele desenha uma cadeia de caracteres de tempo no mostrador do relógio. Adicione o seguinte método a MyWatchFaceEngine:

public override void OnDraw (Canvas canvas, Rect frame)
{
    var str = DateTime.Now.ToString ("h:mm tt");
    canvas.DrawText (str,
        (float)(frame.Left + 70),
        (float)(frame.Top  + 80), hoursPaint);
}

Quando o Android chama OnDraw, ele passa em uma Canvas instância e os limites em que o rosto pode ser desenhado. No exemplo de código acima, DateTime é usado para calcular a hora atual em horas e minutos (no formato de 12 horas). A sequência de tempo resultante é desenhada na tela usando o Canvas.DrawText método. A cadeia de caracteres aparecerá 70 pixels acima da borda esquerda e 80 pixels abaixo da borda superior.

Para obter mais informações sobre o OnDraw método, consulte a documentação da API do Android onDraw .

Implementar o método Engine OnTimeTick

O Android chama periodicamente o OnTimeTick método para atualizar a hora mostrada pelo mostrador do relógio. Ele é chamado pelo menos uma vez por minuto (nos modos ambiente e interativo), ou quando a data/hora ou o fuso horário foram alterados. Adicione o seguinte método a MyWatchFaceEngine:

public override void OnTimeTick()
{
    Invalidate();
}

Essa implementação de OnTimeTick chamadas simples.Invalidate O Invalidate método agenda OnDraw para redesenhar o mostrador do relógio.

Para obter mais informações sobre o OnTimeTick método, consulte a documentação da API onTimeTick do Android.

Registrar o CanvasWatchFaceService

MyWatchFaceService deve ser registrado no AndroidManifest.xml do aplicativo Wear associado. Para fazer isso, adicione o seguinte XML à <application> seção :

<service
    android:name="watchface.MyWatchFaceService"
    android:label="Xamarin Sample"
    android:allowEmbedded="true"
    android:taskAffinity=""
    android:permission="android.permission.BIND_WALLPAPER">
    <meta-data
        android:name="android.service.wallpaper"
        android:resource="@xml/watch_face" />
    <meta-data
        android:name="com.google.android.wearable.watchface.preview"
        android:resource="@drawable/preview" />
    <intent-filter>
        <action android:name="android.service.wallpaper.WallpaperService" />
        <category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" />
    </intent-filter>
</service>

Esse XML faz o seguinte:

  1. Define a android.permission.BIND_WALLPAPER permissão. Essa permissão dá ao serviço do mostrador do relógio permissão para alterar o papel de parede do sistema no dispositivo. Observe que essa permissão deve ser definida na <service> seção e não na seção externa <application> .

  2. Define um watch_face recurso. Esse recurso é um arquivo XML curto que declara um wallpaper recurso (esse arquivo será criado na próxima seção).

  3. Declara uma imagem desenhável chamada preview que será exibida pela tela de seleção do seletor de relógio.

  4. Inclui um intent-filter para que o Android saiba que MyWatchFaceService exibirá um mostrador do relógio.

Isso completa o código para o exemplo básico WatchFace . O próximo passo é adicionar os recursos necessários.

Adicionar arquivos de recursos

Antes de executar o serviço de observação, você deve adicionar o recurso watch_face e a imagem de visualização. Primeiro, crie um novo arquivo XML em Resources/xml/watch_face.xml e substitua seu conteúdo pelo seguinte XML:

<?xml version="1.0" encoding="UTF-8"?>
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android" />

Defina a ação de compilação deste arquivo como AndroidResource:

Esse arquivo de recurso define um elemento simples wallpaper que será usado para o mostrador do relógio.

Se você ainda não fez isso, baixe preview.png. Instale-o em Resources/drawable/preview.png. Certifique-se de adicionar esse arquivo ao WatchFace projeto. Esta imagem de pré-visualização é apresentada ao utilizador no seletor de mostradores do relógio no dispositivo Wear. Para criar uma imagem de pré-visualização para o mostrador do relógio, pode tirar uma captura de ecrã do mostrador do relógio enquanto este está em execução. (Para obter mais informações sobre como obter capturas de tela de dispositivos Wear, consulte Tirar screenshots).

Experimente!

Crie e implante o aplicativo no dispositivo Wear. Você deve ver a tela do aplicativo Wear aparecer como antes. Faça o seguinte para ativar o novo mostrador do relógio:

  1. Deslize para a direita até ver o plano de fundo da tela do relógio.

  2. Toque e segure em qualquer lugar no plano de fundo da tela por dois segundos.

  3. Deslize da esquerda para a direita para navegar pelos vários mostradores do relógio.

  4. Selecione o mostrador do relógio Xamarin Sample (mostrado à direita):

    Seletor de Watchface

  5. Toque no mostrador do relógio Xamarin Sample para selecioná-lo.

Isso altera a face do relógio do dispositivo Wear para usar o serviço de mostrador de relógio personalizado implementado até agora:

A captura de ecrã mostra um relógio digital personalizado a correr no dispositivo Wear.

Este é um mostrador de relógio relativamente bruto porque a implementação do aplicativo é muito mínima (por exemplo, ele não inclui um plano de fundo do mostrador do relógio e não chama Paint métodos de suavização de serrilhado para melhorar a aparência). No entanto, ele implementa a funcionalidade básica necessária para criar um mostrador de relógio personalizado.

Na próxima seção, este mostrador do relógio será atualizado para uma implementação mais sofisticada.

Atualizando o mostrador do relógio

No restante deste passo a passo, MyWatchFaceService é atualizado para exibir um mostrador de relógio de estilo analógico e é estendido para oferecer suporte a mais recursos. Os seguintes recursos serão adicionados para criar o mostrador de relógio atualizado:

  1. Indica o tempo com ponteiros analógicos de hora, minuto e segundo.

  2. Reage a mudanças na visibilidade.

  3. Responde a alterações entre o modo ambiente e o modo interativo.

  4. Lê as propriedades do dispositivo Wear subjacente.

  5. Atualiza automaticamente a hora em que ocorre uma alteração de fuso horário.

Antes de implementar as alterações de código abaixo, baixe drawable.zip, descompacte-o e mova os arquivos .png descompactados para Recursos/desenhável (substitua o preview.png anterior). Adicione os novos arquivos .png ao WatchFace projeto.

Recursos do mecanismo de atualização

A próxima etapa é atualizar MyWatchFaceService.cs para uma implementação que desenha um mostrador de relógio analógico e oferece suporte a novos recursos. Substitua o conteúdo do MyWatchFaceService.cs pela versão analógica do código do mostrador do relógio em MyWatchFaceService.cs (você pode recortar e colar essa fonte no MyWatchFaceService.cs existente).

Esta versão do MyWatchFaceService.cs adiciona mais código aos métodos existentes e inclui métodos substituídos adicionais para adicionar mais funcionalidade. As seções a seguir fornecem uma visita guiada ao código-fonte.

OnCreate

O método OnCreate atualizado configura o estilo do mostrador do relógio como antes, mas inclui algumas etapas adicionais:

  1. Define a imagem de plano de fundo para o recurso xamarin_background que reside em Resources/drawable-hdpi/xamarin_background.png.

  2. Inicializa Paint objetos para desenhar o ponteiro das horas, o ponteiro dos minutos e o segundo manual.

  3. Inicializa um Paint objeto para desenhar os tiques de hora ao redor da borda do mostrador do relógio.

  4. Cria um temporizador que chama o Invalidate método (redesenhar) para que a segunda mão seja redesenhada a cada segundo. Observe que esse temporizador é necessário porque OnTimeTick as chamadas Invalidate são feitas apenas uma vez a cada minuto.

Este exemplo inclui apenas uma imagem xamarin_background.png , no entanto, convém criar uma imagem de plano de fundo diferente para cada densidade de tela que seu mostrador de relógio personalizado suportará.

OnDraw

O método OnDraw atualizado desenha um mostrador de relógio de estilo analógico usando as seguintes etapas:

  1. Obtém a hora atual, que agora é mantida em um time objeto.

  2. Determina os limites da superfície de desenho e seu centro.

  3. Desenha o plano de fundo, dimensionado para caber no dispositivo quando o plano de fundo é desenhado.

  4. Desenha doze tiques ao redor da face do relógio (correspondendo às horas no mostrador do relógio).

  5. Calcula o ângulo, a rotação e o comprimento de cada ponteiro do relógio.

  6. Desenha cada mão na superfície do relógio. Observe que o segundo ponteiro não é desenhado se o relógio estiver no modo ambiente.

OnPropertiesChanged

Esse método é chamado para informar MyWatchFaceEngine sobre as propriedades do dispositivo de desgaste (como modo ambiente de baixo bit e proteção contra burn-in). No MyWatchFaceEngine, esse método verifica apenas o modo de ambiente de bits baixos (no modo de ambiente de bits baixos, a tela suporta menos bits para cada cor).

Para obter mais informações sobre esse método, consulte a documentação da API Android onPropertiesChanged .

OnAmbientModeAlterado

Esse método é chamado quando o dispositivo de desgaste entra ou sai do modo ambiente. Na implementação, o MyWatchFaceEngine mostrador do relógio desativa a suavização de borda quando está no modo ambiente.

Para obter mais informações sobre esse método, consulte a documentação da API Android onAmbientModeChanged .

OnVisibilityAlterado

Esse método é chamado sempre que o relógio se torna visível ou oculto. No MyWatchFaceEngine, esse método registra/cancela o registro do receptor de fuso horário (descrito abaixo) de acordo com o estado de visibilidade.

Para obter mais informações sobre esse método, consulte a documentação da API Android onVisibilityChanged .

Recurso de fuso horário

O novo MyWatchFaceService.cs também inclui funcionalidade para atualizar a hora atual sempre que o fuso horário muda (como ao viajar entre fusos horários). Perto do final de MyWatchFaceService.cs, é definida uma alteração BroadcastReceiver de fuso horário que manipula objetos Intent alterados por fuso horário:

public class TimeZoneReceiver: BroadcastReceiver
{
    public Action<Intent> Receive { get; set; }
    public override void OnReceive (Context context, Intent intent)
    {
        if (Receive != null)
            Receive (intent);
    }
}

Os RegisterTimezoneReceiver métodos e UnregisterTimezoneReceiver são chamados pelo OnVisibilityChanged método. UnregisterTimezoneReceiver é chamado quando o estado de visibilidade do mostrador do relógio é alterado para oculto. Quando o mostrador do relógio estiver visível novamente, RegisterTimezoneReceiver é chamado (consulte o OnVisibilityChanged método).

O método engine RegisterTimezoneReceiver declara um manipulador para o evento desse receptor de Receive fuso horário, esse manipulador atualiza o time objeto com a nova hora sempre que um fuso horário é cruzado:

timeZoneReceiver = new TimeZoneReceiver ();
timeZoneReceiver.Receive = (intent) => {
    time.Clear (intent.GetStringExtra ("time-zone"));
    time.SetToNow ();
};

Um filtro de intenção é criado e registrado para o receptor de fuso horário:

IntentFilter filter = new IntentFilter(Intent.ActionTimezoneChanged);
Application.Context.RegisterReceiver (timeZoneReceiver, filter);

O UnregisterTimezoneReceiver método cancela o registro do receptor de fuso horário:

Application.Context.UnregisterReceiver (timeZoneReceiver);

Execute o mostrador do relógio melhorado

Crie e implante o aplicativo no dispositivo Wear novamente. Selecione o mostrador do relógio no seletor do mostrador do relógio como antes. A visualização no seletor de relógios é mostrada à esquerda e o novo mostrador do relógio é mostrado à direita:

A captura de tela mostra uma face analógica aprimorada no seletor e no dispositivo.

Nesta captura de tela, a segunda mão está se movendo uma vez por segundo. Quando você executa esse código em um dispositivo Wear, o segundo ponteiro desaparece quando o relógio entra no modo ambiente.

Resumo

Neste passo a passo, um watchface personalizado do Android Wear 1.0 foi implementado e testado. As CanvasWatchFaceService classes e CanvasWatchFaceService.Engine foram introduzidas, e os métodos essenciais da classe de motores foram implementados para criar um mostrador de relógio digital simples. Essa implementação foi atualizada com mais funcionalidade para criar um mostrador de relógio analógico, e métodos adicionais foram implementados para lidar com alterações na visibilidade, modo ambiente e diferenças nas propriedades do dispositivo. Finalmente, um receptor de transmissão de fuso horário foi implementado para que o relógio atualize automaticamente a hora em que um fuso horário é ultrapassado.