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. Utilizza le stesse API che usi per lo sviluppo mobile, ma tieni presenti alcune differenze specifiche di Wear OS.
Sincronizzare i dati utilizzando l'API Data Layer di Wear OS
Un DataClient
espone un'API per consentire ai componenti di leggere o scrivere in 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 sono privati per la tua app e sono accessibili 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 degli asset già trasferiti ed esegue automaticamente la deduplicazione.
Ascolta gli eventi nei servizi
Estendi il corso WearableListenerService
. Il sistema gestisce il ciclo di vita dell'elemento WearableListenerService
di base, associandolo al servizio quando deve inviare elementi di dati o messaggi e slegando il servizio quando non sono necessari interventi.
Ascolta gli eventi nelle attività
Implementa l'interfaccia di OnDataChangedListener
. Utilizza questa interfaccia anziché
WearableListenerService
quando vuoi ascoltare le modifiche solo quando
l'utente utilizza attivamente la tua app.
Trasferire dati
Per inviare oggetti binari di grandi dimensioni tramite il trasporto Bluetooth, ad esempio una registrazione vocale da un altro dispositivo, puoi collegare un elemento
Asset
a un elemento di dati e quindi inserire quest'ultimo nel datastore replicato.
Gli asset gestiscono automaticamente la memorizzazione nella cache dei dati per impedire la ritrasmissione e risparmiare larghezza di banda Bluetooth. Un modello comune prevede che un'app portatile scarichi un'immagine, la riduca a dimensioni appropriate per la visualizzazione sul dispositivo indossabile e la trasmetta all'app indossabile come asset. 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. Nel caso di elementi di dati più grandi, separa i dati in base a percorsi univoci ed evita di utilizzare un unico percorso per tutti i dati. Il trasferimento di asset di grandi dimensioni influisce sull'esperienza utente in molti casi, quindi testa le tue app per assicurarti che funzionino correttamente quando trasferisci risorse di grandi dimensioni.
Trasferire una risorsa
Crea l'asset utilizzando uno dei metodi create...()
nella classe
Asset
.
Converti una bitmap in uno stream di byte, quindi chiama
createFromBytes()
per creare l'asset, come mostrato 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()
in
DataMap
o
PutDataRequest
. Quindi, inserisci l'elemento di dati nel datastore utilizzando il metodo
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 leggerlo ed estrarlo dall'altro lato della connessione. Ecco un esempio di come implementare il callback per rilevare una modifica 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.