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

Wenn Nutzer ein Wear OS-Gerät einrichten, verbinden sie das Wear OS-Gerät mit einem bestimmten Mobilgerät. Der Nutzer entscheidet sich möglicherweise später für ein neues Mobilgerät und verbindet sein vorhandenes Wear OS-Gerät mit diesem neuen Mobilgerät. 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 Wear OS-Daten auf ein neues Mobilgerät übertragen, wenn sie eine Verbindung zu diesem herstellen. Daten werden bei der Übertragung automatisch synchronisiert.

Wenn der Nutzer eine Übertragung anfordert, stellt die Wearable Data Layer DataItem-Objekte, die ursprünglich auf einem Mobilgerät gespeichert waren, auf dem anderen Mobilgerät bereit. So wird eine nahtlose Nutzung Ihrer App ermöglicht.

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

Vorbereitung

Beim Datenübertragungsprozess werden DataItem-Objekte je nach App, die die Daten enthält, unterschiedlich behandelt:

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

Diese Objekte werden auf dem alten Gerät archiviert. Das System verpackt die archivierten Daten dann in ein DataItemBuffer-Objekt und stellt diese Daten der mobilen App zur Verfügung, die auf dem neuen Mobilgerät installiert ist.

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

Übertragene Daten beibehalten

Es liegt in der Verantwortung Ihrer App, die übertragenen DataItem-Objekte beizubehalten. Kurz nachdem die Daten auf das neue Mobilgerät übertragen wurden, wird das Archiv vom alten Gerät gelöscht.

Achten Sie darauf, dass die folgenden Bedingungen erfüllt sind:

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

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

Daten vom alten Mobilgerät empfangen

Damit Sie Daten auf dem neuen Mobilgerät empfangen können, die auf dem alten Mobilgerät archiviert wurden, muss in Ihrer mobilen App der onNodeMigrated()-Callback implementiert sein, der Teil der WearableListenerService-Klasse ist. Führen Sie dazu folgende Schritte aus:

  1. Fügen Sie in die Build-Datei Ihrer 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:19.0.0'
    }
  2. Deklarieren und exportieren Sie das WearableListenerService in der Manifestdatei Ihrer 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. 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 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.
        }
    }