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 do relógio podem escolher quais provedores de dados desejam usar para obter os dados subjacentes. Isso permite que os mostradores exibam informações além da hora sem precisar de código para obter os dados.

A API Complications também permite que os usuários selecionem os provedores de dados que desejarem. Além disso, o Wear OS by Google fornece 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:

Defina provedores padrão para mostradores do relógio

Mostradores do relógio podem especificar provedores padrão a serem usados até que o usuário selecione um. Defina provedores padrão usando o método =setDefaultComplicationProvider() em WatchFaceService.Engine. Esse método pode ser chamado a qualquer momento, mas não tem 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 deve ser concedida a um mostrador do relógio antes que os dados possam fluir para ele. Entretanto, alguns os provedores de sistema são considerados “seguros”, pois eles apenas fornecem as informações que o mostrador do relógio pode obter 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 utilizar esses provedores como padrão, pois eles podem fornecer os dados imediatamente.

Como alternativa, se um mostrador do relógio tiver parceria com determinado provedor e desejar usá-lo como padrão, ele pode solicitar que o provedor o liste como um mostrador de relógio seguro.

Provedores do sistema

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

A tabela a seguir apresenta detalhes sobre alguns dos provedores de sistema com suporte:

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 aplicativo padrão Agenda.
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 Seu padrão é Londres ou Nova York. Pode ser tocado para alterar o fuso horário.
appsProvider() Sim Sim Mostra um ícone de “aplicativos” inicialmente, que pode ser tocado para selecionar um aplicativo.
nextEventProvider() Não Sim (mas não é um provedor seguro) O provedor padrão de “próximo evento” do sistema. O toque abre o aplicativo padrão Agenda.

Permita que os usuários escolham provedores de dados

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

Quando um mostrador do relógio chama createProviderChooserHelperIntent, o mostrador fornece uma ID de complicação de mostrador e uma lista de tipos suportados. Os tipos devem 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 selecionar um provedor de dados, a configuração será salva automaticamente. O mostrador do relógio não precisa fazer mais nada.

Consulte o Exemplo de aplicativo de mostrador do relógio para obter 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 das entradas de configuração disponíveis na IU.

Abra o seletor de provedores

Um mostrador do relógio deve ter a seguinte permissão para receber dados de complicação no seletor de provedores:

com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA

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

Para facilitar a solicitação da permissão e iniciar o seletor, a classe ComplicationHelperActivity é disponibilizada na biblioteca de suporte para wearables. Essa classe deve ser usada no lugar de ProviderChooserIntent para iniciar o seletor em quase todos os casos.

Solicite 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 obter 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. Em caso negativo, ela faz uma solicitação de permissão em tempo de 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 retornado à Activity que realizou a chamada terá um código de resultado de RESULT_OK se um provedor tiver sido definido com êxito ou um código de resultado de RESULT_CANCELLED se nenhum provedor tiver 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.

Receba 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 essas IDs para identificar slots de forma exclusiva no mostrador onde as complicações podem ser exibidas e as passa 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 do relógio precisam da permissão acima para receber dados de complicação, mas há algumas exceções. Especificamente, um mostrador do relógio só pode receber dados de um provedor se uma das afirmações a seguir for 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 texto curto ou ícone, para fins de conveniência.

Quando um mostrador do relógio recebe dados de TYPE_NO_PERMISSION, ele deve renderizá-los corretamente para que o usuário possa ver 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 aplicativo do mostrador do relógio.

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

Renderize as complicações

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

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

Desenhe as complicações

A classe ComplicationDrawable permite que você renderize uma complicação inteira em um canvas.

Ela oferece suporte para os seis principais tipos de complicação e faz o seguinte para você:

  • 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 aplicativo para o nível de API 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 eles forem fornecidos e o dispositivo os exigir. Para fazer isso, chame o método ComplicationDrawable.setBurnInProtection() quando as propriedades do dispositivo forem recebidas.

Para obter instruções detalhadas e exemplos para desenhar complicações, consulte ComplicationDrawable, que inclui exemplos de XML. Para um exemplo de mostrador do relógio que utiliza essa classe e inclui exemplo de XML, consulte o exemplo de AnalogComplicationWatchFaceService no Exemplo de aplicativo de mostrador de relógio.

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

Renderize o texto

A classe TextRenderer é destinada ao uso em complicações e facilita o desenho de 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ê inicializa o mecanismo do mostrador do relógio, você pode criar um objeto TextRenderer e passar o objeto TextPaint que você deseja que o objeto TextRenderer use. O objeto TextPaint define a fonte, o tamanho do texto, a cor e muito mais. Você deve criar um objeto TextRenderer para cada campo, por exemplo, um para um campo de texto e um para um campo de título.

Para obter um exemplo de código, incluindo a especificação de limites para o texto que você deseja renderizar, consulte TextRenderer.

Toque nas complicações

Use o método ComplicationDrawable.onTap() para permitir que o mostrador do relógio passe 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 passar 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 é chamado, você receberá um valor de retorno true se um ComplicationDrawable iniciou 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 usar 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 do relógio interativos para saber como criar mostradores do 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 está disponível 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 curto.

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 oferecer suporte aos tipos RANGED_VALUE e SHORT_TEXT, enquanto um provedor de “próximo encontro” pode oferecer suporte aos tipos SHORT_TEXT e LONG_TEXT. O provedor de dados também escolhe quais campos opcionais desses tipos incluir.
  • Um provedor de mostradores do relógio escolhe quantos tipos de complicação suportar. Por exemplo, uma complicação redonda em um mostrador de relógio pode oferecer suporte aos tipos SHORT_TEXT, ICON e RANGED_VALUE, enquanto um medidor no mostrador do relógio pode oferecer suporte apenas ao 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 de seu campo obrigatório.

Um tipo pode incluir diferentes conjuntos de campos. Por exemplo, SHORT_TEXT pode ser apenas uma unidade de texto ou um ícone e um texto. Uma complicação que oferece suporte a um determinado tipo deve 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 texto curto do tipo RANGED_VALUE não é obrigatório de forma que, por exemplo, medidores podem ser mostrados sem incluir texto.

Exemplos 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 do 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/texto curto deve ser mostrados se uma ou ambas essas 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ínimo
Valor máximo
Í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 fornecido.
SMALL_IMAGE Imagem pequena Uma pequena imagem 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 não adequada 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, pois isso é seguro. Caso contrário, como o mostrador do relógio tem dificuldade para determinar a adequabilidade, uma imagem não deve 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 não adequada para exibição no modo ambiente em dispositivos com proteção de pixels ou com o modo ambiente com poucos bits. Como é difícil para um mostrador do relógio determinar a adequabilidade para exibição, ele não deve exibir uma imagem em modo ambiente se a proteção de pixels ou o ambiente de poucos bits estiver ativado.

Os tipos na tabela abaixo destinam-se 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 suportados. Esses tipos permitem que mostradores de relógio diferenciem os seguintes três casos:

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

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

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 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 tiverem dados reais para enviar.

Use 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 contagem de passos pode ter um valor de campo de "2,543" com um valor de campo de título de "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). Mostradores do relógio devem poder renderizar qualquer string de sete caracteres. Strings variam em largura, dependendo dos caracteres usados. Um mostrador do relógio deve ajustar o tamanho do texto para que ele comporte a 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. Deve ser possível colorir. 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, mostradores do relógio que utilizam a proteção de pixels não devem exibir blocos sólidos 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 deve ser fornecido por provedores se o ícone padrão não for adequado para proteção de pixels. Um mostrador do relógio renderizando 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 de o 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, mostradores do relógio que utilizam a proteção de pixels não devem exibir blocos sólidos 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 deve conter blocos sólidos de pixels. O campo Burn-in protection small image deve ser fornecido por provedores se a imagem pequena padrão não for adequada para proteção de pixels. Um mostrador do relógio renderizando no modo ambiente de um dispositivo com a proteção de pixels ativada deve usar o campo Burn-in protection small image, se disponível, em vez de 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). Mostradores do relógio devem poder renderizar qualquer string de sete caracteres. Strings variam em largura, dependendo dos caracteres usados. Um mostrador do relógio deve ajustar o tamanho do texto para que ele comporte a 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 Long text.
Valor Uma representação numérica (flutuante) dos dados. Deve ser renderizada em relação aos limites dos campos Min value e Max value (mas não é obrigatório estar dentro desses limites).
Valor mínimo Limite inferior para o intervalo dentro de onde Value deve ser renderizado. Significativo somente em combinação com Value e Max value.
Valor máximo Limite superior para o intervalo dentro de onde value deve ser renderizado. Significativo somente em combinação com Value e Min value.
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.

Teste os tipos de complicação

Cada tipo de complicação tem campos, como texto e ícones. Se o mostrador do relógio oferecer suporte para um tipo de complicação, você deve oferecer suporte a todas as combinações de campos válidas.

Você pode testar como os dados de complicação são exibidos em um mostrador do relógio. Mais especificamente, um pacote de teste permite que você teste a exibição de tipos de complicação. Portanto, não é preciso gravar 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 exemplo, 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 principal ícone de 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 em sua complicação para visualizar 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 oferecer suporte a texto curto, toque nela para ver todas as principais combinações de campos para esse tipo.