Expor dados para complicações

As fontes de dados de complementos expõem informações aos complementos do mostrador do relógio , fornecendo texto, imagens e números que o mostrador pode renderizar.

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 dependência abaixo 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 complemento são necessários, o sistema Wear OS envia solicitações de atualização à fonte de dados. Para responder às solicitações de atualização, a fonte de dados precisa implementar o onComplicationRequest() método da SuspendingComplicationDataSourceService classe.

O sistema Wear OS chama onComplicationRequest() quando precisa de dados da sua fonte. Por exemplo, quando um complemento que usa a fonte de dados é ativado ou quando um período fixo de tempo passa.

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 uma implementação de exemplo:

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 uma fonte 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 complementos.

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, for example: "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, specify a configuration activity, where the user can configure your complication. -->
    <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 complemento que a fonte de dados oferece suporte.
  • android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS": especifica com que frequência o sistema deve verificar se há atualizações nos dados.

Quando a fonte de dados de complemento está ativa, UPDATE_PERIOD_SECONDS especifica com que frequência você quer que o sistema verifique se há atualizações nos dados. Caso não seja necessário atualizar as informações mostradas no complemento 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 seleciona essa fonte de dados específica no seletor de complementos. 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 meta-data elemento com a PROVIDER_CONFIG_ACTION chave. 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 complementos que está configurando na intent dentro do onCreate() método 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

Como alternativa à especificação de um intervalo de atualização no manifesto do app, você pode usar uma instância de ComplicationDataSourceUpdateRequester para iniciar atualizações dinamicamente. 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 classes a seguir permitem criar esses valores que dependem do horário:

Dados da Linha do Tempo

Para fontes de dados de complemento 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, a fonte de dados pode fornecer uma linha do tempo de eventos uma vez e, em seguida, 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 horário 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 está dentro de nenhuma entrada na linha do tempo, o valor padrão é usado. Por exemplo, no app de agenda, isso pode ser "Nenhum evento".
  • Se o horário atual estiver dentro de vários eventos, o evento 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 com base em valores que estão disponíveis diretamente para a plataforma. Para oferecer essa capacidade nas suas complicações, use ComplicationData campos que aceitam valores dinâmicos. A plataforma avalia e atualiza esses valores com frequência, sem exigir que o provedor de complemento esteja em execução.

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

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