Wear OS-Daten auf ein neues Mobilgerät übertragen

Wenn Nutzer ein Wear OS-Gerät einrichten, wird es mit einem bestimmten Mobilgerät verbunden. Der Nutzer kann sich später für ein neues Mobilgerät entscheiden und sein vorhandenes Wear OS-Gerät damit verbinden. Einige Daten, die sich auf ein Wear OS-Gerät beziehen, werden auf dem aktuell verbundenen Mobilgerät gespeichert.

Ab Wear OS 4 können Nutzer, die eine Verbindung mit einem neuen Mobilgerät herstellen, Wear OS-Daten auf das neue Mobilgerät übertragen. Die Daten werden bei der Übertragung automatisch synchronisiert.

Wenn der Nutzer eine Übertragung anfordert, sendet die Wearable-Datenschicht DataItem-Objekte, die ursprünglich auf einem Mobilgerät gespeichert waren, an das andere Mobilgerät. Dies ermöglicht eine nahtlose Nutzung Ihrer App.

In diesem Dokument wird beschrieben, wie du deine Wear OS-App und die zugehörige mobile Companion-App für dieses Szenario konfigurieren kannst.

Vorbereitung

Bei der Datenübertragung werden DataItem-Objekte unterschiedlich verarbeitet, je nachdem, zu welcher Anwendung die Daten gehören:

Objekte, die der Wear OS App gehören
Diese Objekte werden auf dem Wear OS-Gerät aufbewahrt.
Objekte, die der mobilen App gehören

Diese Objekte werden auf dem alten Gerät archiviert. Das System verpackt die archivierten Daten in einem DataItemBuffer-Objekt und sendet diese Daten an die mobile App, die auf dem neuen Mobilgerät installiert ist.

Unmittelbar nach der Bereitstellung des Archivs ruft die Wearable-Datenschicht den onDataChanged()-Listener auf, ähnlich wie deine App benachrichtigt wird, wenn Daten vom Wear OS-Gerät geschrieben werden.

Übertragene Daten beibehalten

Deine App ist dafür verantwortlich, die übertragenen DataItem-Objekte beizubehalten. Kurz nach der Übermittlung der Daten an das neue Mobilgerät wird das Archiv auf dem alten Gerät gelöscht.

Achten Sie darauf, dass jede der folgenden Bedingungen erfüllt ist:

  1. Ihre Anwendung ist auf beiden Mobilgeräten installiert, die an der Übertragung beteiligt sind.
  2. Die auf den einzelnen Mobilgeräten installierten mobilen Apps haben passende Paketsignaturen.

Andernfalls werden die archivierten DataItem-Objekte nicht zugestellt, sondern verworfen.

Daten vom alten Mobilgerät empfangen

Um Daten auf dem neuen Mobilgerät zu empfangen, die auf dem alten Mobilgerät archiviert wurden, muss deine mobile App den onNodeMigrated()-Callback implementieren, der Teil der WearableListenerService-Klasse ist. Führen Sie dazu die folgenden Schritte aus:

  1. Füge in die Build-Datei deiner mobilen App eine Abhängigkeit von der neuesten Version der Wearable-Bibliothek in den Google Play-Diensten ein:

    dependencies {
        ...
        implementation 'com.google.android.gms:play-services-wearable:18.2.0'
    }
    
  2. Deklariere WearableListenerService in der Manifestdatei deiner App und exportiere sie:

    <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. Erstellen Sie eine Dienstklasse, die WearableListenerService erweitert und onNodeMigrated() überschreibt.

    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 suspend 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())
                }
            }
    
            CoroutineScope(Job() + Dispatchers.IO).launch {
                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 void 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;
                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());
                }
            }
    
            Thread thread = new Thread(() -> {
                for (DataItem dataItem : dataItemsToHandle) {
                    handleDataItem(nodeId, dataItem);
                }
            });
            thread.start();
        }
    }