Participe do evento ⁠#Android11: apresentação de lançamento da versão Beta no dia 3 de junho.

Adicionar complicações a um mostrador do relógio

A complicação de um mostrador do relógio exibe informações de um provedor de dados. Com a API Complications, mostradores de relógio podem escolher quais provedores de dados usar para receber os dados subjacentes. Isso permite que os mostradores exibam informações além da hora, sem precisar de códigos para conseguir os dados.

A API Complications também permite que os usuários selecionem os provedores de dados que preferirem. Além disso, o Wear OS by Google disponibiliza uma interface de usuário para selecionar a fonte dos dados.

Complicações

Para adicionar complicações a um mostrador do relógio, faça o seguinte:

Definir provedores padrão para mostradores de relógio

Mostradores de relógio podem especificar provedores padrão a serem usados até que o usuário selecione um provedor. Defina provedores padrão usando o método setDefaultComplicationProvider() em WatchFaceService.Engine. Esse método pode ser chamado a qualquer momento, mas não terá efeito se o usuário já tiver escolhido um provedor para a complicação em questão.

Para a maioria dos provedores, a permissão RECEIVE_COMPLICATION_DATA precisa ser concedida a um mostrador do relógio antes que o fluxo de dados comece. Entretanto, alguns provedores de sistema são considerados seguros porque só disponibilizam informações que o mostrador do relógio poderia conseguir por conta própria. Provedores seguros não exigem que o mostrador do relógio tenha permissão para que os dados sejam enviados (consulte Provedores do sistema). É preferível usar esses provedores como padrão, porque eles podem disponibilizar dados imediatamente.

Como alternativa, se um mostrador do relógio tiver parceria com determinado provedor e quiser usá-lo como padrão, ele poderá solicitar ao provedor para ser listado como um mostrador seguro.

Provedores do sistema

O sistema inclui provedores que podem ser usados como padrão. O método setDefaultSystemComplicationProvider(), na classe WatchFaceService.Engine, define um provedor de sistema padrão para uma complicação. Esse método usa um ID (como um número inteiro) que representa um provedor de sistema. Os IDs disponíveis são listados na classe SystemProviders.

A tabela a seguir apresenta detalhes sobre alguns dos provedores de sistema compatíveis:

Nome do método na classe SystemProviders Segurança Pode ser o padrão Observações
dateProvider() Sim Sim O provedor padrão de datas do sistema. O toque abre o app padrão Compromissos.
currentTimeProvider() Sim Sim O provedor padrão de “data e hora” do sistema. Nenhuma ação de toque.
batteryProvider() Sim Sim O provedor padrão de bateria do sistema. Nenhuma ação de toque.
stepCountProvider() Sim Sim Mostra um total diário de passos, conforme reportado por readDailyTotal.
unreadCountProvider() Sim Sim Mostra o número de notificações não lidas no stream.
worldClockProvider() Sim Sim Tem como padrão Londres ou Nova York. Pode ser tocado para alterar o fuso horário.
appsProvider() Sim Sim Mostrará um ícone de "apps" inicialmente, que pode ser tocado para escolher um app.
nextEventProvider() Não Sim (mas não é um provedor seguro) O provedor padrão de "próximo evento" do sistema. O toque abre o app padrão Compromissos.

Permitir que os usuários escolham provedores de dados

O Wear OS oferece uma interface do usuário (por meio de uma atividade) que permite que os usuários escolham os provedores para uma complicação específica. Mostradores de relógio podem chamar o método createProviderChooserHelperIntent para receber um intent que pode ser usado para mostrar a interface do seletor.

Quando um mostrador do relógio chama createProviderChooserHelperIntent, o mostrador fornece um ID de complicação e uma lista de tipos compatíveis. Os tipos precisam ser listados em ordem de preferência, geralmente com os tipos que oferecem mais informações, como um valor de intervalo, com uma preferência mais alta.

Quando o usuário seleciona um provedor de dados, a configuração é salva automaticamente. O mostrador do relógio não precisa fazer mais nada.

Consulte a Amostra de app de mostrador do relógio (em inglês) para ver o código completo recomendado para a interface do usuário das configurações.

Esse código inclui:

  • uma interface padrão para configurações de complicação;
  • acesso fácil a outras configurações.

Um ponto de partida para analisar esse código é a classe AnalogComplicationConfigActivity, que tem um método getDataToPopulateAdapter() que retorna uma lista de entradas de configurações disponíveis na IU.

Abrir o seletor de provedores

Um mostrador de relógio precisa ter a seguinte permissão para receber dados de complicação e abrir o seletor de provedores:

    com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA
    

O mostrador do relógio que não tiver a permissão acima não poderá iniciar o seletor de provedores.

Para facilitar a solicitação de permissão e iniciar o seletor, a classe ComplicationHelperActivity é disponibilizada na Biblioteca de Suporte de Wearables. Essa classe precisa ser usada no lugar de ProviderChooserIntent para iniciar o seletor em quase todos os casos.

Solicitar a permissão necessária

Para usar ComplicationHelperActivity, adicione-a ao mostrador do relógio no arquivo de manifesto:

    <activity android:name="android.support.wearable.complications.ComplicationHelperActivity"/>
    

Para iniciar o seletor de provedores, chame o método ComplicationHelperActivity.createProviderChooserHelperIntent, para receber um intent.

O novo intent pode ser usado com startActivity ou startActivityForResult para iniciar o seletor.

Veja um exemplo de como usar o novo intent com startActivityForResult:

Kotlin

    startActivityForResult(
            ComplicationHelperActivity.createProviderChooserHelperIntent(
                    activity,
                    watchFace,
                    complicationId,
                    ComplicationData.TYPE_LARGE_IMAGE
            ),
            PROVIDER_CHOOSER_REQUEST_CODE
    )
    

Java

    startActivityForResult(
      ComplicationHelperActivity.createProviderChooserHelperIntent(
         getActivity(),
         watchFace,
         complicationId,
         ComplicationData.TYPE_LARGE_IMAGE),
      PROVIDER_CHOOSER_REQUEST_CODE);
    

Quando a atividade auxiliar for iniciada, ela verificará se a permissão foi concedida. Se não foi, ela faz uma solicitação de permissão durante a execução. Se a solicitação de permissão for aceita (ou se não for necessária), o seletor de provedores será mostrado.

Se startActivityForResult for usado com o intent, o resultado devolvido à atividade que realizou a chamada terá um código de resultado igual a RESULT_OK, caso um provedor tenha sido definido, ou igual a RESULT_CANCELLED, caso nenhum provedor tenha sido definido.

Caso um provedor tenha sido definido, a classe ComplicationProviderInfo do provedor escolhido será incluída no intent de dados do resultado, como um extra com a chave ProviderChooserIntent#EXTRA_PROVIDER_INFO.

Receber dados de complicação

Para começar a receber dados de complicação, um mostrador de relógio chama setActiveComplications(), na classe WatchFaceService.Engine, com uma lista de IDs de complicação de mostrador do relógio. Um mostrador do relógio cria esses IDs para identificar slots de forma exclusiva no mostrador em que as complicações podem ser exibidas e as transmite para o método createProviderChooserIntent() para permitir que o usuário decida qual complicação entra em qual slot. Dados de complicação são enviados pelo callback onComplicationDataUpdate().

Em geral, mostradores de relógio precisam da permissão acima para receber dados de complicação, mas há algumas exceções. Especificamente, o mostrador do relógio só pode receber dados de um provedor quando uma das afirmações a seguir é verdadeira:

  • O provedor é um provedor de sistema "seguro".
  • O provedor e o mostrador do relógio são do mesmo aplicativo.
  • O provedor colocou o mostrador do relógio na lista de permissões como um mostrador “seguro”.
  • O mostrador do relógio tem a permissão.

Se nenhuma das afirmações a seguir for verdadeira, no momento em que ComplicationData normalmente seria enviado para um mostrador do relógio, o sistema enviará dados do tipo TYPE_NO_PERMISSION. Esse tipo inclui um ícone (um ponto de exclamação) e um texto curto ("-") para permitir que ele seja renderizado como se fosse do tipo de texto curto ou de ícone, por conveniência.

Quando um mostrador de relógio recebe dados de TYPE_NO_PERMISSION, ele precisa renderizá-los corretamente para que o usuário veja que é necessário realizar uma ação para que a complicação funcione. Se possível, um toque na complicação nesse estado deve iniciar uma solicitação de permissão. Isso pode ser feito usando ComplicationHelperActivity.createPermissionRequestHelperIntent(), se a atividade auxiliar foi adicionada ao app do mostrador do relógio.

Se um usuário aceitar a solicitação de permissão criada pela atividade auxiliar, as atualizações serão automaticamente solicitadas para todas as complicações ativas no mostrador do relógio, permitindo que os dados de TYPE_NO_PERMISSION sejam substituídos por dados reais.

Renderizar complicações

O mostrador do relógio pode renderizar os dados como pretendido, desde que os campos esperados sejam representados. Os campos obrigatórios precisam ser sempre incluídos. Dependendo do tipo, alguns dos campos opcionais também devem ser incluídos (consulte a coluna "Observações" na tabela abaixo).

Disponibilizamos diretrizes de design para nosso estilo, como uma sugestão para complicações padrão. No entanto, os desenvolvedores podem usar os próprios estilos ou incorporar os dados no mostrador do relógio de formas diferentes.

Desenhar complicações

Com a classe ComplicationDrawable, você pode renderizar uma complicação inteira em uma tela.

Ela oferece compatibilidade com os seis principais tipos de complicação e faz o seguinte:

  • Lida com todos os aspectos do layout e estilo para as complicações.
  • Desenha planos de fundo, ícones, texto etc. dentro dos limites.
  • Permite que você defina muitas opções. Elas incluem, entre outras, opções para: cor do plano de fundo, formato e raio dos cantos, bordas (ou ausência de bordas), cor do texto e fonte.
  • Decodifica e armazena imagens em cache.

Se você direcionar seu app para a API de nível 24, um objeto ComplicationDrawable poderá ser definido em XML como um recurso. Como alternativa, você pode criar um objeto ComplicationDrawable de forma programática. Use o método draw() para desenhar uma complicação e definir opções de estilo para os modos interativo e ambiente.

ComplicationDrawable usará ícones e imagens com proteção de pixels se tiverem sido fornecidos e o dispositivo os exigir. Para fazer isso, chame o método ComplicationDrawable.setBurnInProtection() quando as propriedades do dispositivo forem recebidas.

Para instruções detalhadas e exemplos de desenho de complicações, consulte ComplicationDrawable, que inclui uma amostra de XML. Para ver uma amostra de mostrador do relógio que utiliza essa classe e inclui uma amostra de XML, consulte a amostra de AnalogComplicationWatchFaceService em Amostra de app de mostrador de relógio.

Se você não usar um objeto ComplicationDrawable, utilize TextRenderer para o texto de uma complicação.

Renderizar texto

A classe TextRenderer foi feita para ser usada em complicações e facilita o desenho do texto em uma tela. A classe inclui os seguintes recursos:

  • Se sete caracteres (o máximo para um campo de texto curto) não couberem nos limites no tamanho de texto solicitado, a classe reduzirá o texto até que ele caiba.
  • O texto pode fluir para um número especificado de linhas.
  • Se o texto não couber, ele poderá ser cortado.
  • A renderização é ajustada para uma tela sempre ativa (modo ambiente).

Quando você inicializar o mecanismo do mostrador do relógio, você poderá criar um objeto TextRenderer e transmitir o objeto TextPaint que você quer que o objeto TextRenderer use. O objeto TextPaint define a fonte, o tamanho do texto, a cor e muito mais. Crie um objeto TextRenderer para cada campo, por exemplo, um para um campo de texto e um para um campo de título.

Para ver uma amostra de código, incluindo a especificação de limites para o texto que você quer renderizar, consulte TextRenderer.

Tocar nas complicações

Use o método ComplicationDrawable.onTap() para permitir que o mostrador do relógio transmita eventos de toque para complicações. Esse método é baseado na funcionalidade na qual um toque no mostrador do relógio aciona o método WatchFaceService.Engine.onTapCommand().

Você pode transmitir coordenadas para um ComplicationDrawable com uma chamada para onTap. Isso iniciará a ação associada ao ComplicationDrawable que contém as coordenadas de toque. Quando o método for chamado, você receberá um valor de retorno true se um ComplicationDrawable tiver iniciado a ação associada.

Use o método setHighlightDuration() para definir a duração pela qual uma complicação permanecerá em destaque após o método onTap ser chamado.

Se você não estiver usando ComplicationDrawable para uma complicação, será necessário detectar toques e acionar a ação de toque PendingIntent por conta própria. Consulte Criar mostradores de relógios interativos para saber como criar mostradores de relógio que respondem a toques do usuário.

Tipos de complicação

Os tipos de complicação determinam os tipos de dados mostrados em uma complicação. Por exemplo, o tipo SHORT_TEXT é disponibilizado quando os dados principais são uma string curta. No exemplo do tipo SHORT_TEXT, os dados opcionais são um ícone e um título abreviado.

Provedores de dados usam esses tipos de complicação de forma diferente dos provedores de mostradores do relógio:

  • Um provedor de dados escolhe os tipos de dados de complicação a serem fornecidos. Por exemplo, um provedor de contagem de passos pode ser compatível com os tipos RANGED_VALUE e SHORT_TEXT, enquanto um provedor de “próxima reunião” pode ser compatível com os tipos SHORT_TEXT e LONG_TEXT. O provedor de dados também escolhe quais campos opcionais desses tipos incluir.
  • Um provedor de mostradores de relógio escolhe quantos tipos de complicação serão compatíveis. Por exemplo, uma complicação redonda em um mostrador do relógio pode ser compatível com os tipos SHORT_TEXT, ICON e RANGED_VALUE, enquanto um medidor no mostrador do relógio pode ser compatível somente com o tipo RANGED_VALUE.

Um objeto ComplicationData sempre terá um só tipo de complicação. Cada tipo de complicação tem campos obrigatórios e opcionais. Geralmente, um campo obrigatório representa os dados principais. A maioria dos tipos adota o nome do campo obrigatório.

Um tipo pode incluir diferentes conjuntos de campos. Por exemplo, SHORT_TEXT pode ser só uma única parte do texto, um título e texto ou um ícone e texto. Uma complicação compatível com um determinado tipo precisa poder exibir todas as variantes esperadas. Entretanto, alguns campos opcionais não precisam ser exibidos (consulte a coluna Observações da tabela abaixo). Por exemplo, o campo de título curto do tipo RANGED_VALUE não é indispensável para que medidores sejam exibidos sem a inclusão de texto.

Exemplos de tipos de complicação

Veja a seguir exemplos de tipos de complicação:

Tipos de complicação

Tipos e campos

A tabela a seguir descreve os tipos e campos do objeto ComplicationData. Se um mostrador de relógio solicitar um campo inválido para um tipo de complicação, um valor padrão para esse campo será retornado. Por exemplo, se o mostrador do relógio tentar acessar o campo Long text em um tipo SHORT_TEXT, o valor padrão para o campo Long text (null) será retornado.

Tipo Campos obrigatórios Campos opcionais Observações
SHORT_TEXT Texto curto Ícone
Ícone de proteção de pixels
Título curto
Exatamente um ícone/título curto deverá ser mostrado se uma ou ambas as opções forem fornecidas.
ICON Ícone Ícone de proteção de pixels Usado quando texto não é necessário. O ícone deve ter uma só cor e ser colorido pelo mostrador do relógio.
RANGED_VALUE Valor
Valor mín
Valor máx
Ícone
Ícone de proteção de pixels
Texto curto
Título curto
Não há garantias de que os campos opcionais serão exibidos. Se quiser desenhar sua própria barra de progresso, use o método setRangedValueProgressHidden() para ocultar a barra de progresso fornecida pela classe ComplicationDrawable.
LONG_TEXT Texto longo Título longo
Ícone
Ícone de proteção de pixels
Imagem pequena
O título deve ser exibido se disponível.
SMALL_IMAGE Imagem pequena Uma imagem pequena tem um de dois estilos: estilo de foto ou estilo de ícone. O estilo de foto significa que ela deve preencher o espaço e pode ser cortada. O estilo de ícone significa que ela não deve ser cortada e pode ser emoldurada. A variabilidade de imagens pode resultar em uma imagem inadequada para exibição no modo ambiente em dispositivos com proteção de pixels ou com o modo ambiente com poucos bits. Quando a proteção de pixels ou o modo ambiente de poucos bits está ativado, o mostrador do relógio pode usar Burn-in protection small image, porque isso é seguro. Caso contrário, como o mostrador do relógio tem dificuldade para determinar a adequabilidade, nenhuma imagem deverá ser exibida.
LARGE_IMAGE Imagem grande Essa imagem deve ser grande o bastante para preencher o mostrador do relógio. A variabilidade de imagens pode resultar em uma imagem inadequada para exibição no modo ambiente em dispositivos com proteção de pixels ou com o modo ambiente com poucos bits. Como o mostrador do relógio tem dificuldade para determinar a adequabilidade, ele não deverá exibir uma imagem no modo ambiente se a proteção de pixels ou o ambiente de poucos bits estiver ativado.

Os tipos na tabela abaixo se destinam a dados vazios e podem ser enviados para qualquer slot de complicação. Esses tipos não têm campos e não precisam ser incluídos em uma lista de tipos compatíveis. Esses tipos permitem que mostradores de relógio façam a distinção entre estes três casos:

  • Nenhum provedor foi escolhido
  • O usuário selecionou "empty" para um slot
  • O provedor não tem dados para enviar

Os provedores não enviarão TYPE_EMPTY em resposta a solicitações de atualização. Em vez disso, eles enviarão TYPE_NO_DATA.

Os detalhes sobre os tipos de complicação para dados "empty" são apresentados na tabela a seguir:

Tipo de complicação Descrição
TYPE_NOT_CONFIGURED Enviada pelo sistema quando uma complicação é ativada, mas o usuário não selecionou um provedor e nenhum padrão foi definido.

Não pode ser enviada por provedores.

TYPE_EMPTY Enviada pelo sistema quando uma complicação é ativada e o usuário escolheu "empty" em vez de um provedor ou quando o mostrador do relógio não escolheu um provedor e esse tipo é o padrão.

Não pode ser enviada por provedores.

TYPE_NO_DATA Enviada pelo sistema quando uma complicação (que tem um provedor) é ativada, para limpar a complicação antes que dados reais sejam recebidos do provedor.

Deve ser enviada por provedores se eles não têm dados reais para enviar.

Usar campos para dados de complicação

Os campos de um objeto ComplicationData têm diferentes funções. Por exemplo, um campo de texto contém os dados principais, enquanto um campo de título é descritivo. Uma complicação de contagem de passos pode ter um campo de texto com o valor "2.543" e um campo de título com o valor "steps".

A tabela a seguir contém descrições dos campos em um objeto ComplicationData. Os campos podem ou não estar preenchidos, dependendo do tipo de complicação.

Campo Descrição
Texto curto Campo de texto principal para pequenas complicações. O tamanho máximo desse campo não deve exceder sete caracteres (incluindo qualquer texto dependente de horário). Os mostradores de relógio devem poder renderizar qualquer string de sete caracteres. Strings variam em largura, dependendo dos caracteres usados. O mostrador do relógio deve ajustar o tamanho do texto para que ele caiba na complicação. Se o texto exceder sete caracteres, ele poderá ficar truncado.
Ícone Uma imagem monocromática que representa os dados ou a fonte dos dados. Essa imagem precisa poder ser colorida. Drawables vetoriais são recomendados para esse campo.
Ícone de proteção de pixels Campo para ativar um ícone a ser exibido no modo ambiente em dispositivos que usam a proteção de pixels. No modo ambiente, blocos sólidos de pixels não serão exibidos em mostradores de relógio de dispositivos que usam a proteção de pixels. O campo Burn-in protection icon é opcional para qualquer tipo de complicação que inclua o campo icon. O campo Burn-in protection icon não deve conter blocos sólidos de pixels. O campo Burn-in protection icon precisa ser fornecido por provedores se o ícone padrão não for adequado para proteção de pixels. Um mostrador do relógio renderizado no modo ambiente de um dispositivo com a proteção de pixels ativada deve usar o campo Burn-in protection icon, se disponível, em vez do campo icon.
Imagem pequena com proteção de pixels Campo para ativar uma imagem a ser exibida no modo ambiente em dispositivos que usam a proteção de pixels. No modo ambiente, blocos sólidos de pixels não serão exibidos em mostradores de relógio de dispositivos que usam a proteção de pixels. O campo Burn-in protection small image é opcional para qualquer tipo de complicação que inclua um campo small image. O campo Burn-in protection small image não pode conter blocos sólidos de pixels. O campo Burn-in protection small image será fornecido por provedores se a imagem pequena padrão não for adequada para proteção de pixels. Um mostrador do relógio renderizado no modo ambiente de um dispositivo com a proteção de pixels ativada usará o campo Burn-in protection small image, se disponível, e não o campo small image.
Título curto Campo descritivo para pequenas complicações. Pode ser significativo somente em combinação com o campo Short text. O tamanho máximo desse campo não deve exceder sete caracteres (incluindo qualquer texto dependente de horário). Os mostradores de relógio devem poder renderizar qualquer string de sete caracteres. Strings variam em largura, dependendo dos caracteres usados. O mostrador do relógio deve ajustar o tamanho do texto para que ele caiba na complicação. Se o texto exceder sete caracteres, ele poderá ficar truncado.
Texto longo Campo de dados principal para grandes complicações baseadas em texto.
Título longo Campo descritivo para grandes complicações baseadas em texto. Pode ser significativo somente em combinação com Texto longo.
Valor Uma representação numérica (flutuante) dos dados. Deve ser renderizada em relação aos limites dos campos Valor mínimo e Valor máximo (mas não é obrigatório estar dentro desses limites).
Valor mínimo Limite inferior para o intervalo em que Valor deve ser renderizado. Significativo somente em combinação com Valor e Valor máximo.
Valor máximo Limite superior para o intervalo em que Valor deve ser renderizado. Significativo somente em combinação com Valor e Valor mínimo.
Imagem pequena Uma pequena imagem para representar os dados ou a fonte de dados. Pode ser colorida. Não precisa preencher o mostrador do relógio inteiro.
Imagem grande Uma imagem com resolução suficiente para preencher o mostrador do relógio. Pode ser colorida.

Testar tipos de complicação

Cada tipo de complicação tem campos, como texto e ícones. Se o mostrador do relógio for compatível com um tipo de complicação, será necessário oferecer compatibilidade com todas as combinações de campos válidas.

Você pode testar como os dados da complicação são exibidos em um mostrador do relógio. Mais especificamente, um pacote de teste (em inglês) permite testar a exibição de tipos de complicação. Portanto, não é preciso escrever código para testar as combinações de campos válidas para um objeto ComplicationData.

O pacote de teste é um provedor de dados, disponível como amostra (em inglês), que alterna entre as combinações de campos válidas para determinado tipo de complicação.

Para usar o pacote de teste:

  1. Instale o APK do pacote de teste em um dispositivo ou emulador.
  2. Acesse o mostrador do relógio e toque no ícone principal das configurações.
  3. Use a IU de configurações para escolher o pacote de teste: WearComplication-ProviderTestSuite
  4. Escolha um tipo de dados de complicação para testar.
  5. Toque na complicação para ver as variações do tipo de dados.
  6. Toque na complicação várias vezes para verificar se todas as combinações de campos relevantes são exibidas corretamente.

Por exemplo, se uma complicação for compatível com texto curto, toque nela para ver todas as principais combinações de campos para texto curto.