Przenoszenie danych z Wear OS na nowe urządzenie mobilne

Podczas konfigurowania urządzenia z Wear OS użytkownicy łączą je z konkretnym urządzeniem mobilnym. Użytkownik może później kupić nowe urządzenie mobilne i połączyć istniejące urządzenie z Wear OS z nowym urządzeniem mobilnym. Niektóre dane związane z urządzeniem z Wear OS są przechowywane na połączonym obecnie urządzeniu mobilnym.

Od Wear OS 4 użytkownicy, którzy łączą się z nowym urządzeniem mobilnym, mogą przenieść na nie dane z Wear OS. Dane są synchronizowane automatycznie po przeniesieniu.

Gdy użytkownik poprosi o przeniesienie, warstwa danych do noszenia dostarcza na inne urządzenie mobilne obiekty DataItem, które były pierwotnie zapisane na jednym urządzeniu mobilnym. Dzięki temu użytkownicy mogą bez trudu korzystać z Twojej aplikacji.

Z tego dokumentu dowiesz się, jak skonfigurować aplikację na Wear OS i jej towarzyszącą aplikację mobilną pod kątem obsługi takiego scenariusza.

Przygotowanie

Proces przenoszenia danych obsługuje obiekty DataItem w różny sposób, w zależności od tego, która aplikacja jest właścicielem danych:

Obiekty należące do aplikacji na Wear OS
Te obiekty są zachowywane na urządzeniu z Wear OS.
Obiekty należące do aplikacji mobilnej

Te obiekty są zarchiwizowane na starym urządzeniu. System następnie spakuje zarchiwizowane dane do obiektu DataItemBuffer i dostarcza je do aplikacji mobilnej zainstalowanej na nowym urządzeniu.

Bezpośrednio po dostarczeniu archiwum warstwa danych do noszenia wywołuje detektor onDataChanged(), podobnie jak aplikacja jest powiadamiana o zapisaniu danych przez urządzenie z Wear OS.

Zachowaj przeniesione dane

Za zachowanie przeniesionych obiektów DataItem odpowiada Twoja aplikacja. W krótkim czasie po dostarczeniu danych na nowe urządzenie mobilne archiwum jest usuwane ze starego urządzenia.

Upewnij się, że każdy z tych warunków jest spełniony:

  1. Aplikacja jest instalowana na obu urządzeniach mobilnych uwzględnionych w przenoszeniu.
  2. Aplikacje mobilne zainstalowane na poszczególnych urządzeniach mobilnych mają pasujące podpisy pakietów.

W przeciwnym razie zarchiwizowane obiekty DataItem nie są dostarczane i zamiast tego są odrzucane.

Odbieranie danych ze starego urządzenia mobilnego

Aby można było odbierać dane na nowym urządzeniu mobilnym, które zostało zarchiwizowane na starym urządzeniu, Twoja aplikacja musi implementować wywołanie zwrotne onNodeMigrated(), które jest częścią klasy WearableListenerService. Aby to zrobić, wykonaj te czynności:

  1. W pliku kompilacji aplikacji mobilnej dodaj zależność od najnowszej wersji biblioteki do noszenia w Usługach Google Play:

    dependencies {
        ...
        implementation 'com.google.android.gms:play-services-wearable:18.1.0'
    }
    
  2. Zadeklaruj i wyeksportuj WearableListenerService w pliku manifestu aplikacji:

    <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. Utwórz klasę usługi, która rozszerza zakres WearableListenerService i zastępuje 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 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();
        }
    }