Comienza a usar widgets

Requisitos previos y configuración

Antes de comenzar, asegúrate de que tu entorno cumpla con los siguientes requisitos.

Requisitos del entorno de ejecución

Los widgets de Wear requieren la versión 1.6.1 o posterior del APK de com.google.android.wearable.protolayout.renderer en el dispositivo de destino.

Obtén una versión compatible del renderizador de una de las siguientes maneras:

  • Emulador de Wear OS 7: Usa la imagen del emulador de Wear OS 7. Las versiones anteriores a la 7 no son adecuadas. Para obtener instrucciones de configuración, consulta Cómo configurar el emulador de Wear OS 7.
  • Dispositivo físico: Usa un dispositivo Wear OS físico que reciba actualizaciones automáticas de Google Play Store o un dispositivo para desarrolladores que haya accedido a Google Play Store.

Para verificar qué versión tienes instalada en tu dispositivo, usa el siguiente comando:

adb shell dumpsys package com.google.android.wearable.protolayout.renderer | \
  grep -m 1 versionName | \
  awk -F= '{print $2}'

Configuración de Gradle

Las bibliotecas de widgets de Wear están disponibles en Google Maven.

1. Configura la versión del SDK

Asegúrate de que compileSdk y targetSdk estén configurados en 37 o un valor superior.

android {
    compileSdk = 37
    // ...
    defaultConfig {
        targetSdk = 37
        // ...
    }
}

2. Agrega dependencias

Incluye las siguientes dependencias en el archivo build.gradle.kts de tu app:

Groovy

dependencies {
    // Core Wear Widget and Remote Compose libraries
    implementation "androidx.compose.remote:remote-creation-compose:1.0.0-alpha21"
    implementation "androidx.compose.remote:remote-core:1.0.0-alpha21"
    implementation "androidx.glance.wear:wear:1.0.0-alpha20"
    implementation "androidx.glance.wear:wear-core:1.0.0-alpha20"
    implementation "androidx.wear.compose.remote:remote-material3:1.0.0-alpha13"

    // Tooling for previews (optional, but recommended)
    implementation "androidx.compose.remote:remote-tooling-preview:1.0.0-alpha21"
    implementation "androidx.wear.compose:compose-ui-tooling:1.7.1"
    implementation "androidx.wear.tiles:tiles-tooling-preview:1.6.2"
    debugImplementation "androidx.wear.tiles:tiles-renderer:1.6.2"
}

Kotlin

dependencies {
    // Core Wear Widget and Remote Compose libraries
    implementation("androidx.compose.remote:remote-creation-compose:1.0.0-alpha21")
    implementation("androidx.compose.remote:remote-core:1.0.0-alpha21")
    implementation("androidx.glance.wear:wear:1.0.0-alpha20")
    implementation("androidx.glance.wear:wear-core:1.0.0-alpha20")
    implementation("androidx.wear.compose.remote:remote-material3:1.0.0-alpha13")

    // Tooling for previews (optional, but recommended)
    implementation("androidx.compose.remote:remote-tooling-preview:1.0.0-alpha21")
    implementation("androidx.wear.compose:compose-ui-tooling:1.7.1")
    implementation("androidx.wear.tiles:tiles-tooling-preview:1.6.2")
    debugImplementation("androidx.wear.tiles:tiles-renderer:1.6.2")
}

Cómo compilar un widget de Hello World

Un widget de Wear consiste en un servicio que extiende GlanceWearWidgetService y una clase de widget que extiende GlanceWearWidget. La IU se define con funciones @RemoteComposable.

Define el Service

El servicio es el punto de entrada al que se vincula el sistema.

Para definir tu widget, crea un servicio que extienda GlanceWearWidgetService y anótalo con @AssociateWithGlanceWearWidget para asociar el servicio con la clase GlanceWearWidget adecuada.

@AssociateWithGlanceWearWidget(HelloWidget::class)
class HelloWidgetService : GlanceWearWidgetService() {
    override val widget: GlanceWearWidget = HelloWidget()
}

Define el widget

La clase de widget proporciona los datos y el diseño del widget.

class HelloWidget : GlanceWearWidget() {
    override suspend fun provideWidgetData(
        context: Context,
        params: WearWidgetParams,
    ): WearWidgetData {
        return WearWidgetDocument(
            background = WearWidgetBrush.color(Color.Blue.rc),
        ) {
            HelloWidgetContent()
        }
    }
}

Define el contenido

El contenido se compila con componentes de Remote Compose.

@RemoteComposable
@Composable
fun HelloWidgetContent() {
    RemoteBox(
        modifier = RemoteModifier.fillMaxSize(),
        contentAlignment = RemoteAlignment.Center,
    ) {
        RemoteText(
            text = "Hello World".rs,
            color = Color.White.rc,
        )
    }
}

Obtén una vista previa de tu widget en Android Studio

Puedes obtener una vista previa de los diseños de tus widgets directamente en el panel Design de Android Studio con androidx.glance.wear:wear-tooling-preview.

Conjuntos de vistas previas predefinidos

La biblioteca wear-tooling-preview proporciona conjuntos de PreviewParameterProvider predefinidos para probar tus diseños en diferentes formas de contenedores y configuraciones de dispositivos:

  • Squircle Suite (SquircleAllWidgetPreviewParams): Contenedores de rectángulos redondeados.
  • Round Suite (RoundAllWidgetPreviewParams): Contenedores con forma de píldora.
  • Rectangular Suite (RectangularAllWidgetPreviewParams): Contenedores rectangulares sin recortar con relleno seguro. Las imágenes generadas con esta configuración de vista previa son adecuadas para usarse como imágenes de vista previa incorporadas en el APK que usa el selector de widgets (consulta Genera recursos de imagen de vista previa).

Para obtener una vista previa de tu widget en Android Studio, usa @WearWidgetPreview:

@Preview
@Composable
fun HelloWidgetPreview(
    @PreviewParameter(SquircleAllWidgetPreviewParams::class) params: WearWidgetParams,
) {
    WearWidgetPreview(
        widget = HelloWidget(),
        params = params,
    )
}

Crea el archivo XML de configuración del widget

Crea un archivo res/xml/hello_widget_info.xml nuevo para definir las propiedades y los tamaños admitidos del widget. Para obtener una referencia completa de los atributos XML admitidos en la etiqueta <wearwidget-provider>, consulta la documentación de WearWidgetProviderInfo.

<wearwidget-provider
    description="@string/hello_widget_description"
    icon="@mipmap/ic_launcher"
    label="@string/hello_widget_label"
    preferredType="SMALL">

    <container
        type="SMALL"
        previewImage="@drawable/widget_preview_small" />
    <container
        type="LARGE"
        previewImage="@drawable/widget_preview_large" />
</wearwidget-provider>

Genera recursos de imagen de vista previa

El atributo previewImage del elemento <container> hace referencia a un recurso de elemento de diseño que se muestra en el selector de widgets del sistema. Para generar recursos de vista previa con los límites y la densidad correctos, usa las vistas previas de Android Studio con RectangularAllWidgetPreviewParams (que genera variantes de vista previa para contenedores pequeños y grandes) y especifica una densidad de pantalla de reloj inteligente de 320 DPI:

@Preview(
    name = "Widget Preview Asset",
    device = "spec:width=1000dp,height=1000dp,dpi=320",
)
@Composable
fun HelloWidgetCatalogPreview(
    @PreviewParameter(RectangularAllWidgetPreviewParams::class) params: WearWidgetParams,
) {
    WearWidgetPreview(
        widget = HelloWidget(),
        params = params,
    )
}

Para extraer las imágenes de vista previa renderizadas, completa los siguientes pasos:

  1. En Android Studio, abre la superficie Design de la vista previa de la función de componibilidad.
  2. En la ventana de vista previa, haz clic con el botón derecho en la vista previa renderizada o usa la barra de herramientas de vista previa para seleccionar Copy Image o guardar la imagen. Como alternativa, usa herramientas de la CLI o secuencias de comandos automatizadas para extraer vistas previas de Compose.
  3. Guarda los archivos de imagen pequeños y grandes en el directorio res/drawable-nodpi/ de tu app, como res/drawable-nodpi/widget_preview_small.png y res/drawable-nodpi/widget_preview_large.png.

Registra en AndroidManifest.xml

Registra el servicio en tu AndroidManifest.xml con los filtros de intents y los metadatos necesarios.

<service
    android:name=".snippets.widget.HelloWidgetService"
    android:exported="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/hello_widget_label"
    android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER">

    <intent-filter>
        <action android:name="androidx.glance.wear.action.BIND_WIDGET_PROVIDER" />
        <!-- If you already have a Tile, omit the following line. -->
        <action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" />
    </intent-filter>

    <meta-data
        android:name="androidx.glance.wear.widget.provider"
        android:resource="@xml/hello_widget_info" />

    <meta-data
        android:name="androidx.wear.tiles.PREVIEW"
        android:resource="@drawable/tile_preview" />
</service>

Compile e implemente

Después de definir el servicio y el widget, puedes compilar el proyecto y, luego, implementarlo en un dispositivo o emulador.

Compila e instala

Compila el proyecto e instala el APK de depuración en tu dispositivo conectado o emulador:

./gradlew :app:installDebug

Agrega tu widget y obtén una vista previa de él

Después de instalar la app, usa adb para agregar el widget de forma programática al carrusel y mostrarlo en la pantalla.

Nota: Los widgets de Wear usan la infraestructura de tarjetas subyacente para la depuración. Como resultado, los comandos adb requieren las operaciones add-tile y show-tile.

1. Agrega el widget al carrusel:

adb shell am broadcast \
  -a com.google.android.wearable.app.DEBUG_SURFACE \
  --es operation add-tile \
  --ecn component <your_package_name>/.HelloWidgetService

2. Muestra el widget:

adb shell am broadcast \
  -a com.google.android.wearable.app.DEBUG_SYSUI \
  --es operation show-tile \
  --ei index 0

Actualiza el contenido del widget de forma programática

Cuando cambien los datos subyacentes de tu app (por ejemplo, cuando se reciba una sincronización de datos, una notificación push o una acción del usuario), notifica al sistema para que actualice el contenido del widget.

Para solicitar una actualización de todas las instancias activas de tu widget, llama a triggerUpdateAll en la clase del widget:

// Request a content update for all active HelloWidget instances
HelloWidget().triggerUpdateAll(context)

Para actualizar una instancia de widget específica sin actualizar todas las instancias activas, llama a triggerUpdate con el ID de la instancia de destino.