Trasferire i dati di Wear OS su un nuovo dispositivo mobile

Quando gli utenti configurano un dispositivo Wear OS, lo connettono a un dispositivo mobile specifico. L'utente potrebbe decidere in un secondo momento di acquistare un nuovo dispositivo mobile e connettere il dispositivo Wear OS esistente a questo nuovo dispositivo mobile. Alcuni dati relativi a un dispositivo Wear OS vengono memorizzati sul dispositivo mobile attualmente connesso.

A partire da Wear OS 4, quando gli utenti si connettono a un nuovo dispositivo mobile, possono trasferire i dati di Wear OS al nuovo dispositivo mobile. I dati vengono sincronizzati automaticamente durante il trasferimento.

Quando l'utente richiede un trasferimento, il livello di dati indossabili invia DataItem oggetti, originariamente memorizzati su un dispositivo mobile, all'altro dispositivo mobile. Ciò consente un'esperienza ottimale per gli utenti della tua app.

Questo documento descrive come configurare l'app Wear OS e la relativa app mobile complementare per supportare questo scenario.

Preparazione

La procedura di trasferimento dei dati gestisce gli oggetti DataItem in modo diverso, a seconda dell'app proprietaria dei dati:

Oggetti di proprietà dell'app Wear OS
Questi oggetti vengono conservati sul dispositivo Wear OS.
Oggetti di proprietà dell'app mobile

Questi oggetti vengono archiviati sul vecchio dispositivo. Il sistema comprime i dati archiviati in un oggetto DataItemBuffer e li invia all'app mobile installata sul nuovo dispositivo mobile.

Subito dopo la consegna dell'archivio, il livello dati indossabile richiama il listener onNodeMigrated(), in modo simile a come la tua app viene avvisata quando i dati vengono scritti dal dispositivo Wear OS.

Conservare i dati trasferiti

È responsabilità della tua app conservare gli oggetti DataItem trasferiti. Poco dopo il trasferimento dei dati sul nuovo dispositivo mobile, l'archivio viene eliminato dal vecchio dispositivo.

Assicurati che siano soddisfatte le seguenti condizioni:

  1. L'app è installata su entrambi i dispositivi mobili coinvolti nel trasferimento.
  2. Le app mobile, installate su ogni dispositivo mobile, hanno firme del pacchetto corrispondenti.

In caso contrario, gli oggetti DataItem archiviati non vengono pubblicati e vengono eliminati.

Ricevere i dati dal vecchio dispositivo mobile

Per ricevere sul nuovo dispositivo mobile i dati archiviati sul vecchio dispositivo mobile, la tua app mobile deve implementare il callback onNodeMigrated(), che fa parte della classe WearableListenerService. Per farlo, completa i seguenti passaggi:

  1. Nel file di build dell'app mobile, includi una dipendenza dall'ultima versione della libreria per indossabili in Google Play Services:

    dependencies {
        ...
        implementation 'com.google.android.gms:play-services-wearable:19.0.0'
    }
  2. Dichiara ed esporta WearableListenerService nel file manifest dell'app:

    <service
    android:name=".MyWearableListenerService"
    android:exported="true">
    <intent-filter>
        ...
        <action android:name="com.google.android.gms.wearable.NODE_MIGRATED" />
        <data android:scheme="wear" />
    </intent-filter>
    </service>
    
  3. Crea una classe di servizio che estenda WearableListenerService ed esegua l'override di onNodeMigrated().

    Kotlin

    class MyWearableListenerService : WearableListenerService() {
        val dataClient: DataClient = Wearable.getDataClient(this)
    
        private fun shouldHandleDataItem(nodeId: String,
                                        dataItem: DataItem): Boolean {
            // Your logic here
            return dataItem.uri.path?.startsWith("/my_feature_path/") == true
        }
    
        private fun handleDataItem(nodeId: String, dataItem: DataItem) {
            val data = dataItem.data ?: return
            val path = dataItem.uri.path ?: return
            // Your logic here
            if (data.toString().startsWith("Please restore")) {
                dataClient.putDataItem(
                    PutDataRequest.create(path).setData(data)
                )
            }
        }
    
        override fun onNodeMigrated(nodeId: String, archive: DataItemBuffer) {
            val dataItemsToHandle = mutableListOf<DataItem>()
    
            for (dataItem in archive) {
                if (shouldHandleDataItem(nodeId, dataItem)) {
                    dataItemsToHandle.add(dataItem.freeze())
                }
            }
    
            // Callback stops automatically after 20 seconds of data processing.
            // If you think you need more time, delegate to a coroutine or thread.
            runBlocking {
                for (dataItem in dataItemsToHandle) {
                    handleDataItem(nodeId, dataItem)
                }
            }
        }
    }

    Java

    public class MyWearableListenerService extends WearableListenerService {
        private final DataClient dataClient = Wearable.getDataClient(this);
    
        private boolean shouldHandleDataItem(String nodeId, DataItem dataItem) {
            // Your logic here
            return Objects.requireNonNull(dataItem.getUri().getPath())
                    .startsWith("/my_feature_path/");
        }
    
        private Task<DataItem> handleDataItem(String nodeId, DataItem dataItem) {
            byte[] data = dataItem.getData();
            String path = dataItem.getUri().getPath();
            // Your logic here
            if (data != null && path != null && Arrays.toString(data)
                    .startsWith("Please restore")) {
                assert path != null;
                return dataClient.putDataItem(
                            PutDataRequest.create(path).setData(data));
        }
    
        @Override
        public void onNodeMigrated(@NonNull String nodeId, DataItemBuffer archive) {
            List<DataItem> dataItemsToHandle = new ArrayList<>();
    
            for (DataItem dataItem : archive) {
                if (shouldHandleDataItem(nodeId, dataItem)) {
                    dataItemsToHandle.add(dataItem.freeze());
                }
            }
    
            for (dataItem in dataItemsToHandle) {
                handleDataItem(nodeId, dataItem);
            }
    
            // Callback stops automatically after 20 seconds of data processing.
            // If you think you need more time, delegate to another thread.
        }
    }