Przenoszenie danych z Wear OS na nowe urządzenie mobilne

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

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

Gdy użytkownik poprosi o przeniesienie, warstwa danych do noszenia dostarcza obiekty DataItem pierwotnie zapisane na jednym urządzeniu mobilnym na drugie. Dzięki temu użytkownicy aplikacji będą mogli bez trudu korzystać z niej.

Z tego dokumentu dowiesz się, jak skonfigurować aplikację na Wear OS i jej towarzyszącą aplikację mobilną, aby spełnić ten scenariusz.

Przygotowanie

Proces przenoszenia danych obsługuje obiekty DataItem w różny sposób, w zależności od tego, do której aplikacji należą dane:

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. Następnie system pakuje zarchiwizowane dane do obiektu DataItemBuffer i dostarcza je do aplikacji mobilnej zainstalowanej na nowym urządzeniu mobilnym.

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

Zachowaj przesłane dane

Obowiązkiem Twojej aplikacji jest zachowanie przeniesionych obiektów DataItem. Krótko 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. Twoja aplikacja jest zainstalowana na obu urządzeniach mobilnych objętych przenoszeniem.
  2. Aplikacje mobilne zainstalowane na każdym urządzeniu mobilnym mają pasujące podpisy pakietów.

W przeciwnym razie zarchiwizowane obiekty DataItem nie zostaną dostarczone i zostaną odrzucone.

Odbieraj dane 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, aplikacja mobilna musi wdrożyć wywołanie zwrotne onNodeMigrated(), które jest częścią klasy WearableListenerService. Aby to zrobić:

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

    dependencies {
        ...
        implementation 'com.google.android.gms:play-services-wearable:18.2.0'
    }
    
  2. Zadeklaruj i wyeksportuj element 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();
        }
    }