Controle de versões dos Blocos

Em dispositivos Wear OS, os blocos são renderizados por dois componentes principais com versão independente. Para garantir que os blocos de apps funcionem corretamente em todos os dispositivos, é importante entender essa arquitetura.

  • Bibliotecas relacionadas a blocos do Jetpack: essas bibliotecas (incluindo os blocos do Wear e o Wear ProtoLayout) são incorporadas ao app, e você, como desenvolvedor, controla as versões delas. O app usa essas bibliotecas para construir um objeto TileBuilder.Tile (a estrutura de dados que representa seu Bloco) em resposta à chamada onTileRequest() do sistema.
  • ProtoLayout Renderer:esse componente do sistema é responsável por renderizar o objeto Tile na tela e processar as interações do usuário. A versão do renderizador não é controlada pelo desenvolvedor do app e pode variar entre dispositivos, mesmo aqueles com hardware idêntico.

A aparência ou o comportamento de um Bloco pode variar com base nas versões da biblioteca Jetpack Tiles do app e na versão do ProtoLayout Renderer no dispositivo do usuário. Por exemplo, um dispositivo pode oferecer suporte à rotação ou à exibição de dados de frequência cardíaca, enquanto outro não.

Este documento explica como garantir que seu app seja compatível com diferentes versões da biblioteca Tiles e do ProtoLayout Renderer e como migrar para versões mais recentes da biblioteca do Jetpack.

Considere a compatibilidade

Para criar um Bloco que funcione corretamente em vários dispositivos, considere o seguinte:

Detectar a versão do renderizador

  • Use o método getRendererSchemaVersion() do objeto DeviceParameters transmitido para o método onTileRequest(). Esse método retorna os números de versão principal e secundária do renderizador ProtoLayout no dispositivo.
  • Em seguida, use a lógica condicional na implementação de onTileRequest() para adaptar o design ou o comportamento do Bloco com base na versão do renderizador detectada.
    • Por exemplo, se uma animação específica não tiver suporte, você poderá mostrar uma imagem estática.

A anotação @RequiresSchemaVersion

  • A anotação @RequiresSchemaVersion em métodos ProtoLayout indica a versão mínima do esquema do renderizador necessária para que esse método se comporte como documentado (exemplo).
    • Chamar um método que exige uma versão mais recente do renderizador do que está disponível no dispositivo não faz com que o app falhe, mas pode fazer com que o conteúdo não seja exibido ou o recurso seja ignorado.

Exemplo

override fun onTileRequest(
    requestParams: TileService.TileRequest
): ListenableFuture<Tile> {
    val rendererVersion =
        requestParams.deviceConfiguration.rendererSchemaVersion
    val tile = Tile.Builder()

    if (
        rendererVersion.major > 1 ||
            (rendererVersion.major == 1 && rendererVersion.minor >= 300)
    ) {
        // Use a feature supported in renderer version 1.300 or later
        tile.setTileTimeline(/* ... */ )
    } else {
        // Provide fallback content for older renderers
        tile.setTileTimeline(/* ... */ )
    }

    return Futures.immediateFuture(tile.build())
}

Testar com diferentes versões do renderizador

Para testar os Blocos em diferentes versões do renderizador, implante-os em diferentes versões do emulador do Wear OS. Em dispositivos físicos, as atualizações do ProtoLayout Renderer são enviadas pela Play Store ou pelo sistema. Não é possível forçar a instalação de uma versão específica do renderizador.

O recurso de visualização de blocos do Android Studio usa um renderizador incorporado na biblioteca Jetpack ProtoLayout da qual seu código depende. Portanto, outra abordagem é depender de diferentes versões da biblioteca do Jetpack ao testar blocos.

Fazer upgrade das bibliotecas do Jetpack

Atualize as bibliotecas de blocos do Jetpack para aproveitar os aprimoramentos mais recentes, incluindo mudanças na interface para integrar os blocos perfeitamente ao sistema.

Migrar para Tiles 1.2 / ProtoLayout 1.0

Na versão 1.2 e mais recentes, a maioria das APIs de layout de blocos está no namespace androidx.wear.protolayout. Para usar as APIs mais recentes, siga as etapas de migração abaixo no seu código.

Atualizar dependências

No arquivo de build do módulo do app, faça estas mudanças:

Groovy

  // Remove
  implementation 'androidx.wear.tiles:tiles-material:version'

  // Include additional dependencies
  implementation "androidx.wear.protolayout:protolayout:1.2.1"
  implementation "androidx.wear.protolayout:protolayout-material:1.2.1"
  implementation "androidx.wear.protolayout:protolayout-expression:1.2.1"

  // Update
  implementation "androidx.wear.tiles:tiles:1.4.1"

Kotlin

  // Remove
  implementation("androidx.wear.tiles:tiles-material:version")

  // Include additional dependencies
  implementation("androidx.wear.protolayout:protolayout:1.2.1")
  implementation("androidx.wear.protolayout:protolayout-material:1.2.1")
  implementation("androidx.wear.protolayout:protolayout-expression:1.2.1")

  // Update
  implementation("androidx.wear.tiles:tiles:1.4.1")

Atualizar namespaces

Nos arquivos de código com base em Kotlin e Java do seu app, faça estas mudanças. Como alternativa, execute este script de renomeação de namespace (link em inglês).

  1. Substitua todas as importações androidx.wear.tiles.material.* por androidx.wear.protolayout.material.*. Conclua essa etapa para a biblioteca androidx.wear.tiles.material.layouts também.
  2. Substitua a maioria das outras importações androidx.wear.tiles.* por androidx.wear.protolayout.*.

    As importações para androidx.wear.tiles.EventBuilders, androidx.wear.tiles.RequestBuilders, androidx.wear.tiles.TileBuilders e androidx.wear.tiles.TileService precisam ser as mesmas.

  3. Renomeie alguns métodos descontinuados das classes TileService e TileBuilder:

    1. TileBuilders: getTimeline() para getTileTimeline() e setTimeline() para setTileTimeline()
    2. TileService: onResourcesRequest() para onTileResourcesRequest()
    3. RequestBuilders.TileRequest: getDeviceParameters() para getDeviceConfiguration(), setDeviceParameters() para setDeviceConfiguration(), getState() para getCurrentState() e setState() para setCurrentState()