Sincronizzare gli elementi di dati con l'API Data Layer

Una DataItem definisce l'interfaccia che il sistema utilizza per sincronizzare i dati tra dispositivi portatili e indossabili. In genere un DataItem è costituito dai seguenti componenti:

  • Payload: un array di byte che puoi impostare con i dati, in modo da poter eseguire la serializzazione e la deserializzazione degli oggetti. La dimensione del payload è limitata a 100 kB.
  • Percorso: una stringa univoca che deve iniziare con una barra, ad esempio "/path/to/data".

Nota: l'API del livello dati può solo inviare messaggi e sincronizzare dati solo con telefoni Android o orologi Wear OS. Se il tuo dispositivo Wear OS è accoppiato con un dispositivo iOS, l'API del livello dati non funziona.

Per questo motivo, non utilizzare l'API del livello dati come metodo principale per comunicare con una rete. Segui invece lo stesso schema di un'app per dispositivi mobili, con alcune piccole differenze.

In genere non implementi DataItem direttamente. Procedi invece nel seguente modo:

  1. Crea un oggetto PutDataRequest, specificando un percorso stringa per identificare in modo univoco l'elemento.
  2. Chiama setData() per impostare il payload.
  3. Se un ritardo nella sincronizzazione potrebbe influire negativamente sull'esperienza utente, chiama setUrgent().
  4. Utilizza il metodo putDataItem della classe DataClient per richiedere al sistema di creare l'elemento di dati.

Quando vengono richiesti elementi di dati, il sistema restituisce gli oggetti che implementano correttamente l'interfaccia DataItem. Tuttavia, invece di lavorare con byte non elaborati utilizzando setData(), ti consigliamo di utilizzare una mappa dati, che espone un elemento di dati con un'interfaccia simile a Bundle.

Per ulteriori informazioni, consulta l'articolo sull'app DataLayer Sample.

Sincronizzare i dati con una mappa di dati

Se possibile, utilizza la classe DataMap. Questo approccio ti consente di lavorare con gli elementi di dati sotto forma di Bundle Android, in modo che il sistema esegua automaticamente la serializzazione e la deserializzazione degli oggetti e tu possa manipolare i dati con coppie chiave-valore.

Per utilizzare una mappa di dati:

  1. Crea un oggetto PutDataMapRequest, impostando il percorso dell'elemento di dati.

    Nota: la stringa di percorso è un identificatore univoco dell'elemento di dati che ti consente di accedervi da entrambi i lati della connessione. Il percorso deve iniziare con una barra. Se nell'app utilizzi dati gerarchici, crea uno schema del percorso che corrisponda alla struttura dei dati.

  2. Chiama PutDataMapRequest.getDataMap() per ottenere una mappa di dati su cui puoi impostare valori.
  3. Imposta i valori per la mappa di dati utilizzando i metodi put...(), come putString().
  4. Se un ritardo nella sincronizzazione potrebbe influire negativamente sull'esperienza utente, chiama setUrgent().
  5. Chiama PutDataMapRequest.asPutDataRequest() per ottenere un oggetto PutDataRequest.
  6. Utilizza il metodo putDataItem della classe DataClient per richiedere al sistema di creare l'elemento di dati.

    Nota: se il telefono e i dispositivi indossabili sono disconnessi, i dati vengono memorizzati nel buffer e sincronizzati quando la connessione viene ristabilita.

Il metodo increaseCounter() nell'esempio seguente mostra come creare una mappa di dati e inserirvi i dati:

Kotlin

private const val COUNT_KEY = "com.example.key.count"

class MainActivity : Activity() {

    private lateinit var dataClient: DataClient
    private var count = 0
    ...
    // Create a data map and put data in it
    private fun increaseCounter() {
        val putDataReq: PutDataRequest = PutDataMapRequest.create("/count").run {
            dataMap.putInt(COUNT_KEY, count++)
            asPutDataRequest()
        }
        val putDataTask: Task<DataItem> = dataClient.putDataItem(putDataReq)
    }
    ...
}

Java

public class MainActivity extends Activity {
    private static final String COUNT_KEY = "com.example.key.count";
    private DataClient dataClient;
    private int count = 0;
    ...
    // Create a data map and put data in it
    private void increaseCounter() {
        PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/count");
        putDataMapReq.getDataMap().putInt(COUNT_KEY, count++);
        PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
        Task<DataItem> putDataTask = dataClient.putDataItem(putDataReq);
    }
  ...
}

Per ulteriori informazioni sulla gestione di Tasks, consulta la documentazione di riferimento.

Imposta priorità DataItem

L'API DataClient consente richieste urgenti per la sincronizzazione degli oggetti DataItem. Solitamente, il sistema ritarda la consegna degli elementi di dati alla rete Wear OS per migliorare la durata della batteria dei dispositivi degli utenti, ma se un ritardo nella sincronizzazione degli elementi di dati influisce negativamente sull'esperienza utente, puoi contrassegnarli come urgenti. Ad esempio, in un'app di controllo remoto in cui l'utente si aspetta che le sue azioni si riflettano immediatamente, puoi fare in modo che il sistema sincronizzi immediatamente gli elementi di dati chiamando setUrgent().

Se non chiami setUrgent(), il sistema potrebbe ritardare fino a 30 minuti prima della sincronizzazione di elementi di dati non urgenti, anche se in genere il ritardo potrebbe essere di pochi minuti. L'urgenza predefinita non è urgente, quindi devi utilizzare setUrgent() se devi mantenere il comportamento della sincronizzazione immediata delle versioni precedenti dell'API Wear OS.

Ascolta gli eventi degli elementi di dati

Se un lato della connessione del livello dati modifica un elemento dati, informa l'utente di eventuali modifiche sull'altro lato della connessione. Puoi farlo implementando un listener per gli eventi degli elementi di dati.

Lo snippet di codice nell'esempio seguente invia una notifica all'app quando il valore del contatore definito nell'esempio precedente cambia:

Kotlin

private const val COUNT_KEY = "com.example.key.count"

class MainActivity : Activity(), DataClient.OnDataChangedListener {

    private var count = 0

    override fun onResume() {
        super.onResume()
        Wearable.getDataClient(this).addListener(this)
    }

    override fun onPause() {
        super.onPause()
        Wearable.getDataClient(this).removeListener(this)
    }

    override fun onDataChanged(dataEvents: DataEventBuffer) {
        dataEvents.forEach { event ->
            // DataItem changed
            if (event.type == DataEvent.TYPE_CHANGED) {
                event.dataItem.also { item ->
                    if (item.uri.path.compareTo("/count") == 0) {
                        DataMapItem.fromDataItem(item).dataMap.apply {
                            updateCount(getInt(COUNT_KEY))
                        }
                    }
                }
            } else if (event.type == DataEvent.TYPE_DELETED) {
                // DataItem deleted
            }
        }
    }

    // Method to update the count
    private fun updateCount(int: Int) { ... }
    ...
}

Java

public class MainActivity extends Activity implements DataClient.OnDataChangedListener {
    private static final String COUNT_KEY = "com.example.key.count";
    private int count = 0;

    @Override
    protected void onResume() {
        super.onResume();
        Wearable.getDataClient(this).addListener(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        Wearable.getDataClient(this).removeListener(this);
    }

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        for (DataEvent event : dataEvents) {
            if (event.getType() == DataEvent.TYPE_CHANGED) {
                // DataItem changed
                DataItem item = event.getDataItem();
                if (item.getUri().getPath().compareTo("/count") == 0) {
                    DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
                    updateCount(dataMap.getInt(COUNT_KEY));
                }
            } else if (event.getType() == DataEvent.TYPE_DELETED) {
                // DataItem deleted
            }
        }
    }

    // Method to update the count
    private void updateCount(int c) { ... }
    ...
}

Questa attività implementa l'interfaccia DataClient.OnDataChangedListener. L'attività si aggiunge come listener per gli eventi degli elementi di dati all'interno del metodo onResume() e rimuove il listener nel metodo onPause(). Per visualizzare un'implementazione utilizzando immagini, modelli di visualizzazione e servizi, vedi l'app Esempio di strato dati.

Puoi anche implementare il listener as a Service. Per ulteriori informazioni, consulta la pagina relativa all'ascolto degli eventi del livello dati.