Expor dados a complicações

Os apps de provedores de dados expõem informações para complicações do mostrador do relógio, disponibilizando campos que contém texto, strings, imagens e números.

Um serviço de provedor de dados estende ComplicationProviderService para disponibilizar informações úteis diretamente para o mostrador do relógio.

Criar um projeto de provedor de dados

Para criar um projeto no Android Studio para seu app de provedor de dados:

  1. Clique em Studio > New > New project.
  2. Na janela Create Android Project, aceite os valores padrão e clique em Next.
  3. Na janela Target Android Devices, selecione somente a opção Wear e, na lista de versões do SDK, selecione a versão mais recente disponível. Clique em Next.
  4. Na janela Add an Activity to Wear, selecione Add No Activity e clique em Finish.

    O Android Studio criará um projeto com um módulo app para seu provedor de dados. Para ver mais informações sobre projetos no Android Studio, consulte Criar um projeto.

  5. Inicie o app de provedor de dados criando uma nova classe que estenda BroadcastReceiver. O objetivo dessa classe é ouvir solicitações de atualização de complicações do sistema Wear OS. Além disso, crie uma nova classe que estenda ComplicationProviderService para fornecer dados conforme solicitado pelas complicações apropriadas. Para ver mais informações, consulte os seguintes tópicos:

    Observação: a adição de uma atividade ao seu provedor de dados é opcional. Por exemplo, você pode adicionar uma atividade que só é iniciada quando o usuário toca em uma complicação.

Implementar um método para solicitações de atualização

Quando dados de complicação são necessários, o sistema Wear OS envia solicitações de atualização ao seu provedor de dados. As solicitações são recebidas pelo BroadcastReceiver. Para responder às solicitações de atualização, seu provedor de dados precisa implementar o método onComplicationUpdate() da classe ComplicationProviderService. O sistema Wear OS chama esse método quando precisa de dados do seu provedor. Por exemplo, quando uma complicação que usa seu provedor se torna ativa ou quando uma quantidade fixa de tempo se passa. Um objeto ComplicationManager é passado como um parâmetro para o método onComplicationUpdate e pode ser usado para enviar dados ao sistema.

Observação: quando o app de provedor disponibiliza dados, o mostrador do relógio recebe os valores brutos enviados para que o mostrador possa desenhar as informações.

O snippet de código a seguir mostra um exemplo de implementação do método onComplicationUpdate:

Kotlin

    override fun onComplicationUpdate(
        complicationId: Int, dataType: Int, complicationManager: ComplicationManager) {

        Log.d(TAG, "onComplicationUpdate() id: $complicationId")

        // Used to create a unique key to use with SharedPreferences for this complication.
        val thisProvider = ComponentName(this, javaClass)

        // Retrieves your data, in this case, we grab an incrementing number from SharedPrefs.
        val preferences = getSharedPreferences(ComplicationTapBroadcastReceiver.COMPLICATION_PROVIDER_PREFERENCES_FILE_KEY, 0)

        val number = preferences.getInt(
                ComplicationTapBroadcastReceiver.getPreferenceKey(
                        thisProvider, complicationId),
                        0)
        val numberText = String.format(Locale.getDefault(), "%d!", number)

        var complicationData: ComplicationData? = null

        when (dataType) {
            ComplicationData.TYPE_SHORT_TEXT -> complicationData = ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
                    .setShortText(ComplicationText.plainText(numberText))
                    .build()
            else -> if (Log.isLoggable(TAG, Log.WARN)) {
                        Log.w(TAG, "Unexpected complication type $dataType")
                    }
        }

        if (complicationData != null) {
            complicationManager.updateComplicationData(complicationId, complicationData)
        } else {
            // If no data is sent, we still need to inform the ComplicationManager, so
            // the update job can finish and the wake lock isn't held any longer.
            complicationManager.noUpdateRequired(complicationId)
        }
    }
    

Java

    @Override
    public void onComplicationUpdate(
           int complicationId, int dataType, ComplicationManager complicationManager) {

       Log.d(TAG, "onComplicationUpdate() id: " + complicationId);

       // Used to create a unique key to use with SharedPreferences for this complication.
       ComponentName thisProvider = new ComponentName(this, getClass());

       // Retrieves your data, in this case, we grab an incrementing number from SharedPrefs.
       SharedPreferences preferences =
         getSharedPreferences( ComplicationTapBroadcastReceiver.COMPLICATION_PROVIDER_PREFERENCES_FILE_KEY, 0);

       int number =
               preferences.getInt(
                       ComplicationTapBroadcastReceiver.getPreferenceKey(
                               thisProvider, complicationId),
                       0);
       String numberText = String.format(Locale.getDefault(), "%d!", number);

       ComplicationData complicationData = null;

       switch (dataType) {
           case ComplicationData.TYPE_SHORT_TEXT:
               complicationData =
                       new ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
                               .setShortText(ComplicationText.plainText(numberText))
                               .build();
               break;
           default:
               if (Log.isLoggable(TAG, Log.WARN)) {
                   Log.w(TAG, "Unexpected complication type " + dataType);
               }
       }

       if (complicationData != null) {
           complicationManager.updateComplicationData(complicationId, complicationData);

       } else {
           // If no data is sent, we still need to inform the ComplicationManager, so
           // the update job can finish and the wake lock isn't held any longer.
           complicationManager.noUpdateRequired(complicationId);
       }
    }
    

Declarações e permissões do manifesto

Um app de provedor de dados precisa incluir declarações específicas no manifesto para ser tratado como provedor de dados pelo sistema Android. Esta seção explica as configurações necessárias para um app de provedor de dados. No manifesto do app, declare o serviço e adicione um filtro de intent da ação de solicitação de atualização. O manifesto também precisa proteger o serviço, adicionando a permissão BIND_COMPLICATION_PROVIDER para garantir que apenas o sistema Wear OS possa se vincular aos serviços do provedor.

Além disso, um atributo android:icon precisa ser incluído dentro do elemento de serviço. O ícone disponibilizado deve ser um ícone branco sólido. Drawables de vetor são recomendados para os ícones. Um ícone serve para representar o provedor e será mostrado no seletor de provedores.

Veja um exemplo:

    <service
        android:name=".provider.IncrementingNumberComplicationProviderService"
        android:icon="@drawable/icn_complications"
        android:label="@string/complications_provider_incrementing_number"
        android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER">
        <intent-filter>
            <action
             android:name="android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST"/>
        </intent-filter>
    </service>
    

Especificar os elementos de metadados

No arquivo de manifesto, inclua metadados para especificar os tipos compatíveis, o período de atualização e a ação de configuração, conforme mostrado no exemplo a seguir:

    <meta-data
        android:name="android.support.wearable.complications.SUPPORTED_TYPES"
        android:value="RANGED_VALUE,SHORT_TEXT,LONG_TEXT" />

    <meta-data
        android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS"
        android:value="300" />
    

Quando seu provedor de dados de complicação está ativo, UPDATE_PERIOD_SECONDS especifica a frequência com que você quer que o sistema verifique se há atualizações para os dados. Se as informações mostradas na complicação não precisarem ser atualizadas regularmente, como quando você estiver usando atualizações push, defina esse valor como 0.

Se UPDATE_PERIOD_SECONDS não for definido como 0, será necessário usar um valor de pelo menos 300 (cinco minutos), que é o período mínimo de atualização que o sistema impõe para preservar a duração da bateria do dispositivo. Além disso, as solicitações de atualização podem ocorrer com menos frequência quando o dispositivo está no modo ambiente ou não está sendo usado.

Para ver mais detalhes sobre o envio de atualizações, consulte as chaves listadas para a classe ComplicationProviderService na Referência de API do Wear.

Adicionar uma atividade de configuração

Se necessário, um provedor pode incluir uma atividade de configuração, que é exibida para o usuário quando ele seleciona um provedor de dados. Para incluir a atividade de configuração, adicione um item de metadados na declaração do serviço de provedor no manifesto com uma chave contendo o seguinte:

    <meta-data
        android:name="android.support.wearable.complications.PROVIDER_CONFIG_ACTION"
        android:value="PROVIDER_CONFIG_ACTION"/>
    

O valor pode ser uma ação da sua escolha.

Em seguida, crie a atividade de configuração com um filtro de intent para essa ação. A atividade de configuração precisa residir no mesmo pacote que o provedor. A atividade de configuração precisa retornar RESULT_OK ou RESULT_CANCELED para informar ao sistema se o provedor será definido.

Mostradores de relógio seguros especificados pelo provedor

Os provedores podem especificar certos mostradores do relógio como "seguros" para receber os dados deles. Essa função deverá ser usada somente quando um mostrador de relógio tentar usar o provedor como um padrão (veja abaixo) e o provedor confiar no app do mostrador do relógio.

Para declarar mostradores do relógio como seguros, o provedor adiciona metadados com uma chave de android.support.wearable.complications.SAFE_WATCH_FACES. O valor dos metadados deve ser uma lista separada por vírgulas (o espaço em branco é ignorado). Entradas da lista podem ser nomes de componentes (de WatchFaceServices, se ComponentName.flattenToString() tiver sido chamado) ou nomes de pacotes (de apps e, nesse caso, todos os mostradores do relógio em um app especificado são considerados seguros). Por exemplo:

    <meta-data
           android:name="android.support.wearable.complications.SAFE_WATCH_FACES"
           android:value="
              com.app.watchface/com.app.watchface.MyWatchFaceService,
              com.anotherapp.anotherwatchface/com.something.WatchFaceService,
              com.something.text"/>
    

Usar imagens com proteção de pixels

Em telas suscetíveis à proteção de pixels, blocos sólidos de cor devem ser evitados no modo ambiente. Se seus ícones ou imagens incluírem blocos sólidos de cor, ofereça também uma versão com proteção de pixels.

Ao disponibilizar um ícone usando ComplicationData.Builder#setIcon, inclua uma versão com proteção de pixels usando ComplicationData.Builder#setBurnInProtectionIcon.

Ao disponibilizar uma imagem usando ComplicationData.Builder#setSmallImage, inclua uma versão com proteção de pixels usando ComplicationData.Builder#setBurnInProtectionSmallImage.

Usar atualizações push

Em vez de especificar um intervalo de atualizações diferente de zero e constante para uma complicação no manifesto do app, você pode usar uma instância de ProviderUpdateRequester para solicitar atualizações de forma dinâmica. Para solicitar uma atualização do conteúdo visível ao usuário da complicação, chame onComplicationUpdate().

Cuidado: para preservar a duração da bateria do dispositivo, sua instância de ProviderUpdateRequester não deve chamar onComplicationUpdate() com uma frequência maior do que, em média, a cada cinco minutos.

Usar valores que dependem do horário

Algumas complicações precisam exibir um valor relacionado ao horário atual. Os exemplos incluem a data atual, o tempo restante até a próxima reunião ou a hora em outro fuso horário.

Não atualize uma complicação a cada segundo ou minuto para manter esses valores atualizados. Uma complicação nunca precisa ser atualizada com tanta frequência. Em vez disso, especifique os valores como relativos à data ou ao horário atual usando texto dependente de horário. Você pode usar builders na classe ComplicationText para criar esses valores que dependem do horário.