Questo documento descrive come sincronizzare i dati tra un dispositivo Wear OS e un dispositivo portatile.
Invia e sincronizza i dati direttamente dalla rete
Crea app per Wear OS per comunicare direttamente con la rete. Usa lo stesso API che utilizzi per lo sviluppo mobile, ma che mantengono alcune specifiche per Wear OS le differenze esistenti.
Sincronizzare i dati utilizzando l'API Data Layer di Wear OS
Un DataClient
espone un'API per consentire ai componenti di leggere o scrivere su un DataItem
o
Asset
.
Puoi impostare elementi di dati e asset senza connessione a nessun dispositivo. Vengono sincronizzati quando i dispositivi stabiliscono una connessione di rete. Questi dati è privata per la tua app ed è accessibile all'app soltanto su altri dispositivi.
Viene sincronizzato un
DataItem
su tutti i dispositivi di una rete Wear OS. Di solito sono di dimensioni ridotte.Usa un
Asset
per trasferire un oggetto più grande, ad esempio un'immagine. Il sistema tiene traccia delle risorse già trasferite e delle loro prestazioni la deduplicazione automatica.
Ascolta gli eventi nei servizi
Estendi il corso WearableListenerService
. Il sistema gestisce
ciclo di vita di base WearableListenerService
, associato al servizio quando
deve inviare elementi di dati o messaggi e annullare l'associazione del servizio quando non è
necessaria.
Ascolta gli eventi nelle attività
Implementa l'interfaccia di OnDataChangedListener
. Utilizza questa interfaccia
di WearableListenerService
quando vuoi ascoltare le modifiche solo quando
che l'utente sta utilizzando attivamente la tua app.
Trasferisci dati
Inviare oggetti binari di grandi dimensioni tramite il trasporto Bluetooth, ad esempio una registrazione vocale
da un altro dispositivo, puoi collegare
Asset
a un elemento di dati e quindi inserirlo nel datastore replicato.
Gli asset gestiscono automaticamente la memorizzazione nella cache dei dati per impedire la ritrasmissione e per risparmiare larghezza di banda Bluetooth. Un modello comune è che un'app portatile scarichi un'immagine e la riduca a dimensioni appropriate per la visualizzazione sul dispositivo indossabile e lo trasmette all'app indossabile come risorsa. I seguenti esempi dimostrano questo pattern.
Nota: anche se la dimensione degli elementi di dati è teoricamente limitata a 100 kB, in pratica è possibile utilizzare elementi di dati più grandi. Per più grandi, separa i dati in base a percorsi unici ed evita utilizzando un unico percorso per tutti i dati. Il trasferimento di risorse di grandi dimensioni influisce sull'esperienza utente in molti in altri casi, ti consigliamo di testare le app per assicurarti che funzionino correttamente quando trasferisci risorse di grandi dimensioni.
Trasferire una risorsa
Crea l'asset utilizzando uno dei create...()
metodi nella sezione
Asset
.
Converti una bitmap in un flusso di byte e quindi richiama
createFromBytes()
per creare l'asset, come illustrato nell'esempio seguente.
Kotlin
private fun createAssetFromBitmap(bitmap: Bitmap): Asset = ByteArrayOutputStream().let { byteStream -> bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream) Asset.createFromBytes(byteStream.toByteArray()) }
Java
private static Asset createAssetFromBitmap(Bitmap bitmap) { final ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream); return Asset.createFromBytes(byteStream.toByteArray()); }
Successivamente, collega l'asset a un elemento dati con il metodo putAsset()
DataMap
oppure
PutDataRequest
. Quindi, inserisci l'elemento dati nel datastore utilizzando
putDataItem()
, come mostrato negli esempi riportati di seguito.
Il seguente esempio utilizza PutDataRequest
:
Kotlin
val asset: Asset = BitmapFactory.decodeResource(resources, R.drawable.image).let { bitmap -> createAssetFromBitmap(bitmap) } val request: PutDataRequest = PutDataRequest.create("/image").apply { putAsset("profileImage", asset) } val putTask: Task<DataItem> = Wearable.getDataClient(context).putDataItem(request)
Java
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image); Asset asset = createAssetFromBitmap(bitmap); PutDataRequest request = PutDataRequest.create("/image"); request.putAsset("profileImage", asset); Task<DataItem> putTask = Wearable.getDataClient(context).putDataItem(request);
Il seguente esempio utilizza PutDataMapRequest
:
Kotlin
val asset: Asset = BitmapFactory.decodeResource(resources, R.drawable.image).let { bitmap -> createAssetFromBitmap(bitmap) } val request: PutDataRequest = PutDataMapRequest.create("/image").run { dataMap.putAsset("profileImage", asset) asPutDataRequest() } val putTask: Task<DataItem> = Wearable.getDataClient(context).putDataItem(request)
Java
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image); Asset asset = createAssetFromBitmap(bitmap); PutDataMapRequest dataMap = PutDataMapRequest.create("/image"); dataMap.getDataMap().putAsset("profileImage", asset); PutDataRequest request = dataMap.asPutDataRequest(); Task<DataItem> putTask = Wearable.getDataClient(context).putDataItem(request);
Ricevi asset
Quando viene creato un asset, probabilmente vorrai leggere ed estrarre dall'altro lato della connessione. Di seguito viene riportato un esempio di come implementare per rilevare una modifica apportata all'asset ed estrarlo:
Kotlin
override fun onDataChanged(dataEvents: DataEventBuffer) { dataEvents .filter { it.type == DataEvent.TYPE_CHANGED && it.dataItem.uri.path == "/image" } .forEach { event -> val bitmap: Bitmap? = DataMapItem.fromDataItem(event.dataItem) .dataMap.getAsset("profileImage") .let { asset -> loadBitmapFromAsset(asset) } // Do something with the bitmap } } fun loadBitmapFromAsset(asset: Asset): Bitmap? { // Convert asset into a file descriptor and block until it's ready val assetInputStream: InputStream? = Tasks.await(Wearable.getDataClient(context).getFdForAsset(asset)) ?.inputStream return assetInputStream?.let { inputStream -> // Decode the stream into a bitmap BitmapFactory.decodeStream(inputStream) } ?: run { Log.w(TAG, "Requested an unknown Asset.") null } }
Java
@Override public void onDataChanged(DataEventBuffer dataEvents) { for (DataEvent event : dataEvents) { if (event.getType() == DataEvent.TYPE_CHANGED && event.getDataItem().getUri().getPath().equals("/image")) { DataMapItem dataMapItem = DataMapItem.fromDataItem(event.getDataItem()); Asset profileAsset = dataMapItem.getDataMap().getAsset("profileImage"); Bitmap bitmap = loadBitmapFromAsset(profileAsset); // Do something with the bitmap } } } public Bitmap loadBitmapFromAsset(Asset asset) { if (asset == null) { throw new IllegalArgumentException("Asset must be non-null"); } // Convert asset into a file descriptor and block until it's ready InputStream assetInputStream = Tasks.await(Wearable.getDataClient(context).getFdForAsset(asset)) .getInputStream(); if (assetInputStream == null) { Log.w(TAG, "Requested an unknown Asset."); return null; } // Decode the stream into a bitmap return BitmapFactory.decodeStream(assetInputStream); }
Per maggiori informazioni, consulta la sezione Progetto di esempio Datalayer su GitHub.