Przenoszenie danych z Wear OS na nowe urządzenie mobilne

Podczas konfigurowania urządzenia z Wear OS użytkownik łączy je z konkretne urządzenie mobilne. Użytkownik może później zdecydować się na zakup nowego urządzenia mobilnego i połączyć obecne urządzenie z Wear OS z nowym urządzeniem mobilnym. Niektóre dane powiązane z urządzeniem z Wear OS są przechowywane na obecnie połączonym urządzeniu mobilnym.

Od wersji Wear OS 4 użytkownicy mogą połączyć się z nowym urządzeniem mobilnym przenieść dane z Wear OS na nowe urządzenie mobilne. Dane są synchronizowane automatycznie po przeniesieniu.

Gdy użytkownik poprosi o przeniesienie, warstwa danych do noszenia dostarczy DataItem obiektów zapisanych pierwotnie na jednym urządzeniu mobilnym na drugie; urządzenia mobilnego. Dzięki temu użytkownicy aplikacji będą mogli bez trudu korzystać z niej.

W tym dokumencie opisujemy, jak skonfigurować aplikację na Wear OS aplikacji towarzyszącej na potrzeby tego scenariusza.

Przygotowanie

Proces przenoszenia danych obsługuje obiekty DataItem w różny sposób, w zależności od 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. Następnie system pakuje do obiektu DataItemBuffer i przesyła je do aplikację mobilną zainstalowaną na nowym urządzeniu mobilnym.

Natychmiast po dostarczeniu archiwum wywołuje warstwa danych do noszenia. detektor onDataChanged() – podobnie jak w przypadku powiadomień aplikacji. gdy dane są zapisywane przez urządzenie z Wear OS.

Zachowaj przesłane dane

Obowiązkiem Twojej aplikacji jest zachowanie przeniesionych obiektów DataItem. Wkrótce po dostarczeniu danych na nowe urządzenie mobilne archiwum usunięte 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 i przenieś.
  2. Aplikacje mobilne, zainstalowane na każdym urządzeniu mobilnym, mają pakiet podpisy, które pasują do siebie.

W przeciwnym razie zarchiwizowane obiekty DataItem nie zostaną dostarczone. odrzucono.

Odbieraj dane ze starego urządzenia mobilnego

Aby odbierać dane na nowym urządzeniu mobilnym, które zostały zarchiwizowane na starym urządzeniu mobilnym na swoim urządzeniu, aplikacja mobilna musi zaimplementować wywołanie zwrotne onNodeMigrated(), w ramach zajęć WearableListenerService. W tym celu wykonaj następujące czynności: kroki:

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

    dependencies {
        ...
        implementation 'com.google.android.gms:play-services-wearable:18.2.0'
    }
    
  2. Zadeklaruj i wyeksportuj w swojej aplikacji uprawnienia WearableListenerService plik manifestu:

    <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();
        }
    }