Premiers pas avec les widgets

Prérequis et configuration

Avant de commencer, assurez-vous que votre environnement répond aux exigences suivantes.

Exigences d'exécution

Les widgets Wear nécessitent la version 1.6.1 ou ultérieure de l'APK com.google.android.wearable.protolayout.renderer sur l'appareil cible.

Pour obtenir une version compatible du moteur de rendu, vous pouvez :

  • Émulateur Wear OS 7 : utilisez l'image de l'émulateur Wear OS 7. Les versions antérieures à la version 7 ne sont pas adaptées. Pour obtenir des instructions de configuration, consultez Configurer l'émulateur Wear OS 7.
  • Appareil physique : utilisez un appareil Wear OS physique qui reçoit des mises à jour automatiques du Google Play Store ou un appareil de développeur connecté au Google Play Store.

Pour vérifier la version installée sur votre appareil, utilisez la commande suivante :

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

Configuration de Gradle

Les bibliothèques de widgets Wear sont disponibles sur Google Maven.

1. Configurer la version du SDK

Assurez-vous que vos compileSdk et targetSdk sont définis sur 37 ou une version ultérieure.

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

2. Ajouter des dépendances

Incluez les dépendances suivantes dans le fichier build.gradle.kts de votre application :

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")
}

Créer un widget Hello World

Un widget Wear se compose d'un service étendant GlanceWearWidgetService et d'une classe de widget étendant GlanceWearWidget. Vous définissez l'interface utilisateur à l'aide de fonctions @RemoteComposable.

Définir le service

Le service est le point d'entrée auquel le système se lie.

Pour définir votre widget, créez un service qui étend GlanceWearWidgetService et annotez-le avec @AssociateWithGlanceWearWidget pour associer le service à la classe GlanceWearWidget appropriée.

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

Définir le widget

La classe du widget fournit les données et la mise en page du widget.

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

Définir le contenu

Le contenu est créé à l'aide de composants Remote Compose.

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

Prévisualiser votre widget dans Android Studio

Vous pouvez prévisualiser les mises en page de vos widgets directement dans le panneau Design d'Android Studio à l'aide de androidx.glance.wear:wear-tooling-preview.

Suites d'aperçu prédéfinies

La bibliothèque wear-tooling-preview fournit des suites PreviewParameterProvider prédéfinies pour tester vos mises en page sur différentes formes de conteneurs et configurations d'appareils :

  • Squircle Suite (SquircleAllWidgetPreviewParams) : conteneurs rectangulaires arrondis.
  • Round Suite (RoundAllWidgetPreviewParams) : conteneurs en forme de pilule.
  • Suite rectangulaire (RectangularAllWidgetPreviewParams) : conteneurs rectangulaires non recadrés avec marge intérieure de sécurité. Les images générées avec cette configuration d'aperçu peuvent être utilisées comme images d'aperçu intégrées à l'APK utilisées par le sélecteur de widgets (voir Générer des composants d'image d'aperçu).

Pour prévisualiser votre widget dans Android Studio, utilisez @WearWidgetPreview :

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

Créer le fichier XML de configuration du widget

Créez un fichier res/xml/hello_widget_info.xml pour définir les propriétés et les tailles acceptées du widget. Pour obtenir une documentation de référence complète sur les attributs XML compatibles dans la balise <wearwidget-provider>, consultez la documentation sur 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>

Générer des composants Image d'aperçu

L'attribut previewImage de l'élément <container> fait référence à un élément drawable affiché dans le sélecteur de widgets du système. Pour générer des assets de prévisualisation avec les limites et la densité appropriées, utilisez les aperçus Android Studio avec RectangularAllWidgetPreviewParams (qui génère des variantes d'aperçu pour les petits et grands conteneurs) et spécifiez une densité d'affichage de montre connectée de 320 PPP :

@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,
    )
}

Pour extraire les images d'aperçu affichées, procédez comme suit :

  1. Dans Android Studio, ouvrez la surface Design pour l'aperçu du composable.
  2. Dans la fenêtre d'aperçu, effectuez un clic droit sur l'aperçu affiché ou utilisez la barre d'outils d'aperçu pour sélectionner Copier l'image ou enregistrer l'image. Vous pouvez également utiliser des outils de CLI ou des scripts automatisés pour extraire les aperçus Compose.
  3. Enregistrez les fichiers image de petite et grande taille dans le répertoire res/drawable-nodpi/ de votre application, par exemple res/drawable-nodpi/widget_preview_small.png et res/drawable-nodpi/widget_preview_large.png.

Enregistrer dans AndroidManifest.xml

Enregistrez le service dans votre AndroidManifest.xml avec les filtres d'intent et les métadonnées requis.

<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>

Compiler et déployer

Après avoir défini votre service et votre widget, vous pouvez compiler votre projet et le déployer sur un appareil ou un émulateur.

Compiler et installer

Créez le projet et installez l'APK de débogage sur votre appareil connecté ou émulateur :

./gradlew :app:installDebug

Ajouter et prévisualiser votre widget

Une fois l'application installée, utilisez adb pour ajouter de manière programmatique le widget au carrousel et l'afficher à l'écran.

Remarque : Les widgets Wear utilisent l'infrastructure de tuile sous-jacente à des fins de débogage. Par conséquent, les commandes adb nécessitent les opérations add-tile et show-tile.

1. Ajoutez le widget au carrousel :

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

2. Afficher le widget :

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

Mettre à jour le contenu du widget de manière programmatique

Lorsque les données sous-jacentes de votre application changent (par exemple, lors de la réception d'une synchronisation de données, d'une notification push ou d'une action de l'utilisateur), demandez au système d'actualiser le contenu du widget.

Pour demander une mise à jour de toutes les instances actives de votre widget, appelez triggerUpdateAll sur votre classe de widget :

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

Pour mettre à jour une instance de widget spécifique sans actualiser toutes les instances actives, appelez triggerUpdate avec l'ID de l'instance cible.