Expor dados para complicações

As fontes de dados de complementos expõem informações para complicações do mostrador do relógio, fornecendo texto, imagens e números que podem ser renderizados.

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

Primeiros passos

Adicione a seguinte dependência ao módulo do app:

dependencies {
  implementiation("androidx.wear.watchface:watchface-complications-data-source-ktx:1.2.1")
}

Criar o serviço de fonte de dados

Quando dados de complicação são necessários, o sistema Wear OS envia solicitações de atualização à sua fonte de dados. Para responder às solicitações de atualização, sua fonte de dados precisa implementar o método onComplicationRequest() da classe SuspendingComplicationDataSourceService.

O sistema Wear OS chama onComplicationRequest() quando precisa de dados da sua fonte. Por exemplo, quando uma complicação que usa sua fonte de dados se torna ativa ou depois de passar uma quantidade fixa de tempo.

Observação:quando a fonte de dados disponibiliza dados, o mostrador do relógio recebe os valores brutos. O mostrador do relógio é responsável por formatar os dados para exibição.

O snippet de código a seguir mostra um exemplo de implementação:

class MyComplicationDataSourceService : SuspendingComplicationDataSourceService() {
    override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData? {
        // Retrieve the latest info for inclusion in the data.
        val text = getLatestData()
        return shortTextComplicationData(text)
    }

    override fun getPreviewData(type: ComplicationType): ComplicationData? {
        return shortTextComplicationData("Event 1")
    }

    private fun shortTextComplicationData(text: String) =
        ShortTextComplicationData.Builder(
            text = PlainComplicationText.Builder(text).build(),
            contentDescription = PlainComplicationText.Builder(text).build()
        )
            // Add further optional details here such as icon, tap action, and title.
            .build()

    // ...
}

Declarações e permissões do manifesto

As fontes de dados precisam incluir declarações específicas no manifesto do app para serem tratadas como fontes de dados pelo sistema Android. Esta seção explica as configurações necessárias para fontes 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 se vincule aos serviços do provedor.

Além disso, inclua um atributo android:icon no elemento service que forneça um ícone branco. Recomendamos drawables vetoriais para os ícones. O ícone representa a fonte de dados e é mostrado no seletor de complicações.

Veja um exemplo:

<service
    android:name=".snippets.complication.MyComplicationDataSourceService"
    android:exported="true"
    android:label="@string/my_complication_service_label"
    android:icon="@drawable/complication_icon"
    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>

    <!-- Supported types should be comma-separated e.g. SHORT_TEXT,SMALL_IMAGE -->
    <meta-data
        android:name="android.support.wearable.complications.SUPPORTED_TYPES"
        android:value="SHORT_TEXT" />
    <meta-data
        android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS"
        android:value="300" />

    <!--
        Optionally, the complication can be configured by the user by specifying a
        configuration activity.
    -->
    <meta-data
        android:name="android.support.wearable.complications.PROVIDER_CONFIG_ACTION"
        android:value="MY_CONFIG_ACTION" />

</service>

Elementos de metadados

No arquivo de manifesto, observe os seguintes elementos de metadados:

  • android:name="android.support.wearable.complications.SUPPORTED_TYPES": Especifica os tipos de dados de complicação compatíveis com a fonte de dados.
  • android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS": Especifica a frequência com que o sistema deve verificar atualizações nos dados.

Quando a fonte de dados de complicação está ativa, UPDATE_PERIOD_SECONDS especifica a frequência com que você quer que o sistema verifique se há atualizações para os dados. Caso não seja necessário atualizar as informações mostradas na complicação regularmente, como ao usar atualizações push, defina esse valor como 0.

Se você não definir UPDATE_PERIOD_SECONDS 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 ocorrem com menos frequência quando o dispositivo está no modo ambiente ou não está sendo usado.

Adicionar uma atividade de configuração

Se necessário, uma fonte de dados pode incluir uma atividade de configuração que é mostrada quando o usuário escolhe essa fonte de dados específica no seletor de complicações. Por exemplo, uma fonte de dados de relógio mundial pode ter uma atividade de configuração que permite ao usuário escolher a cidade ou o fuso horário a ser exibido.

O manifesto de exemplo inclui um elemento meta-data com a chave PROVIDER_CONFIG_ACTION. O valor desse elemento é a ação usada para iniciar a atividade de configuração.

Crie a atividade de configuração e adicione um filtro de intent que corresponda à ação dela no arquivo de manifesto.

<intent-filter>
    <action android:name="MY_CONFIG_ACTION" />
    <category android:name="android.support.wearable.complications.category.PROVIDER_CONFIG" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

A atividade pode receber detalhes do slot de complicação que está configurando no intent dentro do método onCreate() da atividade:

// Keys defined on ComplicationDataSourceService
val id = intent.getIntExtra(EXTRA_CONFIG_COMPLICATION_ID, -1)
val type = intent.getIntExtra(EXTRA_CONFIG_COMPLICATION_TYPE, -1)
val source = intent.getStringExtra(EXTRA_CONFIG_DATA_SOURCE_COMPONENT)

A atividade de configuração precisa ficar no mesmo pacote que o provedor. A atividade de configuração precisa retornar RESULT_OK ou RESULT_CANCELED para informar ao sistema se a fonte de dados será definida:

setResult(RESULT_OK) // Or RESULT_CANCELED to cancel configuration
finish()

Usar atualizações push

Em vez de especificar um intervalo de atualizações no manifesto do app, você pode usar uma instância de ComplicationDataSourceUpdateRequester para iniciar atualizações de forma dinâmica. Para solicitar uma atualização, chame requestUpdate().

Cuidado: para preservar a duração da bateria do dispositivo, não chame o método requestUpdate() da instância do ComplicationDataSourceUpdateRequester com frequência maior do que a cada cinco minutos, em média.

Fornecer valores que dependem do horário

Algumas complicações precisam exibir um valor que é associado ao horário atual. Alguns exemplos são a data atual, o tempo restante até a próxima reunião ou a hora em um fuso horário diferente.

Não atualize uma complicação a cada segundo ou minuto. Em vez disso, especifique os valores como relativos à data ou ao horário, usando um texto dependente de horário. As seguintes classes permitem criar esses valores que dependem do horário:

Dados da Linha do Tempo

Para fontes de dados de complementos que fornecem uma sequência de valores em horários predefinidos, use SuspendingTimelineComplicationDataSourceService.

Um exemplo disso seria uma fonte de dados de "próximo evento" de um app de agenda: em vez de o sistema precisar consultar a fonte de dados regularmente para o próximo evento, ela pode fornecer uma linha do tempo de eventos uma vez, e depois iniciar atualizações se a agenda mudar. Isso minimiza a carga no sistema e permite que a complicação mostre o evento correto de maneira oportuna:

class MyTimelineComplicationDataSourceService : SuspendingTimelineComplicationDataSourceService() {
    override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationDataTimeline? {
        if (request.complicationType != ComplicationType.SHORT_TEXT) {
            return ComplicationDataTimeline(
                defaultComplicationData = NoDataComplicationData(),
                timelineEntries = emptyList()
            )
        }
        // Retrieve list of events from your own datasource / database.
        val events = getCalendarEvents()
        return ComplicationDataTimeline(
            defaultComplicationData = shortTextComplicationData("No event"),
            timelineEntries = events.map {
                TimelineEntry(
                    validity = TimeInterval(it.start, it.end),
                    complicationData = shortTextComplicationData(it.name)
                )
            }
        )
    }

    override fun getPreviewData(type: ComplicationType): ComplicationData? {
        return shortTextComplicationData("Event 1")
    }

    private fun shortTextComplicationData(text: String) =
        ShortTextComplicationData.Builder(
            text = PlainComplicationText.Builder(text).build(),
            contentDescription = PlainComplicationText.Builder(text).build()
        )
            // Add further optional details here such as icon, tap action, title etc
            .build()

    // ...
}

O comportamento do SuspendingTimelineComplicationDataSourceService é o seguinte:

  • Quando o horário atual está dentro do período de início e término de uma entrada na linha do tempo, o mostrador do relógio usa esse valor.
  • Quando o horário atual não se enquadra em nenhuma entrada na linha do tempo, o valor padrão é usado. Por exemplo, no app Agenda, isso pode ser "Nenhum evento".
  • Se o horário atual estiver dentro de vários eventos, o mais curto será usado.

Fornecer valores dinâmicos

A partir do Wear OS 4, algumas complicações podem mostrar valores que são atualizados com mais frequência de acordo com os valores disponibilizados diretamente para a plataforma. Para oferecer essa capacidade nas complicações, use campos ComplicationData que aceitam valores dinâmicos. A plataforma avalia e atualiza esses valores com frequência, sem exigir que o provedor de complementos esteja em execução.

Exemplos de campos incluem o campo de valor dinâmico de GoalProgressComplicationData e DynamicComplicationText, que pode ser usado em qualquer campo ComplicationText. Esses valores dinâmicos são baseados na biblioteca androidx.wear.protolayout.expression.

Em algumas situações, a plataforma não consegue avaliar valores dinâmicos: