Synchroniser les données

Ce document explique comment synchroniser des données entre un appareil Wear OS et un téléphone. Consultez les conseils généraux pour savoir quand utiliser l'API Data Layer et quand utiliser votre infrastructure.

Envoyer et synchroniser des données directement à partir du réseau

Créez des applications Wear OS pour communiquer directement avec le réseau. Utilisez les mêmes API que pour le développement mobile, mais gardez à l'esprit certaines différences spécifiques à Wear OS.

Synchroniser des données à l'aide de l'API Wear OS Data Layer

Un DataClient expose une API pour que les composants puissent lire ou écrire un DataItem ou un Asset.

Il est possible de définir des éléments de données et des composants sans être connecté à des appareils. Ils sont synchronisés lorsque les appareils établissent une connexion réseau. Ces données sont privées pour votre application et ne sont accessibles qu'à votre application sur d'autres appareils.

  • Un DataItem est synchronisé sur tous les appareils d'un réseau Wear OS. Ils sont généralement de petite taille.

  • Utilisez un Asset pour transférer un objet plus volumineux, tel qu'une image. Le système garde la trace des composants qui ont déjà été transférés et effectue automatiquement la déduplication.

Écouter les événements dans les services

Étendez la classe WearableListenerService. Le système gère le cycle de vie du WearableListenerService de base en l'associant au service lorsqu'il doit envoyer des éléments de données ou des messages et en le dissociant en l'absence de travail.

Écouter les événements dans les activités

Implémentez l'interface OnDataChangedListener. Utilisez cette interface à la place d'un WearableListenerService lorsque vous souhaitez écouter les modifications uniquement lorsque l'utilisateur utilise activement votre application.

description: Transférez des objets binaires volumineux, tels que des images, entre des téléphones Android et des montres Wear OS à l'aide des éléments de l'API Data Layer. keywords_public: Wear OS, API Data Layer, éléments, transfert de données Bluetooth, synchronisation des données, DataMap, PutDataRequest

Synchroniser les données

Pour partager des objets binaires volumineux via le transport Bluetooth, tels qu'un enregistrement vocal depuis un autre appareil, vous pouvez associer un Asset à un élément de données, puis placer l'élément de données dans le data store répliqué. Toutefois, si l'échange est ponctuel entre deux appareils connectés, déterminez si un transfert direct plus simple est plus approprié.

Remarque : L'API Data Layer ne peut envoyer des messages et synchroniser des données qu'avec des téléphones fonctionnant sous Android ou des montres Wear OS. Si un appareil Wear OS est associé à un appareil iOS, l'API Data Layer ne fonctionnera pas.

C'est pourquoi vous ne devez pas utiliser cette API comme moyen de communication principal avec un réseau. Suivez plutôt le même principe dans votre application Wear OS que dans une application mobile, avec quelques différences mineures, comme décrit dans Accès au réseau et synchronisation sur Wear OS.

Les éléments gèrent automatiquement la mise en cache des données pour empêcher la retransmission et préserver la bande passante Bluetooth. Il est courant qu'une application de téléphone télécharge une image, la réduise à une taille appropriée pour l'afficher sur la montre et la partage avec l'application de montre en tant qu'élément. Les exemples suivants illustrent ce schéma.

Transférer un élément

Créez le composant à l'aide de l'une des méthodes create...() de la classe Asset. Convertissez un bitmap en tableau d'octets, puis appelez createFromBytes() pour créer l'élément, comme illustré dans l'exemple suivant.

private fun createAssetFromBitmap(bitmap: Bitmap): Asset =
    ByteArrayOutputStream().let { byteStream ->
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream)
        Asset.createFromBytes(byteStream.toByteArray())
    }

Associez ensuite cet élément à un élément de données avec la méthode putAsset() dans DataMap ou PutDataRequest. Ensuite, placez l'élément de données dans le datastore à l'aide de la méthode putDataItem(), comme indiqué dans les exemples suivants.

L'exemple suivant utilise PutDataRequest :

private fun Context.sendImagePutDataRequest(): Task<DataItem> {

    val asset: Asset = createAssetFromBitmap(BitmapFactory.decodeResource(resources, R.drawable.ic_walk))
    val request: PutDataRequest = PutDataRequest.create("/image").apply {
        putAsset("profileImage", asset)
    }
    val putTask: Task<DataItem> = Wearable.getDataClient(this).putDataItem(request)

    return putTask
}

L'exemple suivant utilise PutDataMapRequest :

private fun Context.sendImagePutDataMapRequest(): Task<DataItem> {

    val asset: Asset = createAssetFromBitmap(BitmapFactory.decodeResource(resources, R.drawable.ic_walk))
    val request: PutDataRequest = PutDataMapRequest.create("/image").run {
        dataMap.putAsset("profileImage", asset)
        asPutDataRequest()
    }
    val putTask: Task<DataItem> = Wearable.getDataClient(this).putDataItem(request)

    return putTask
}

Recevoir les éléments

Une fois que vous avez créé un élément, vous le lisez et l'extrayez généralement de l'autre côté de la connexion. L'exemple suivant montre comment implémenter le rappel pour détecter une modification d'élément et l'extraire :

override fun onDataChanged(dataEvents: DataEventBuffer) {
    dataEvents
        .filter { it.type == DataEvent.TYPE_CHANGED && it.dataItem.uri.path == "/image" }
        .forEach { event ->
            val asset = DataMapItem.fromDataItem(event.dataItem)
                .dataMap.getAsset("profileImage")

            asset?.let { safeAsset ->
                lifecycleScope.launch {
                    val bitmap = loadBitmapFromAsset(safeAsset)
                    // Do something with the bitmap
                }
            }
        }
}

private suspend fun loadBitmapFromAsset(asset: Asset): Bitmap? = withContext(Dispatchers.IO) {
    try {
        val assetResult = Wearable.getDataClient(this@DataLayerActivity2)
            .getFdForAsset(asset)
            .await()

        assetResult?.inputStream?.use { inputStream ->
            BitmapFactory.decodeStream(inputStream)
        }
    } catch (e: Exception) {
        e.printStackTrace()
        null
    }
}

Pour en savoir plus, consultez l'exemple de projet DataLayer sur GitHub.