When users [set up a Wear OS device](https://support.google.com/wearos/answer/6056630), they connect the Wear OS device to a
particular mobile device. The user might later decide to get a new mobile device
and connect their existing Wear OS device to this new mobile device. Some data
related to a Wear OS device is stored on the currently-connected mobile device.

Starting in Wear OS 4, when users connect to a new mobile device, they can
transfer Wear OS data to the new mobile device. Data is synced automatically
when it's transferred.
| **Note:** This process of transferring data to a new mobile device is different from [cloud backup and restore](https://developer.android.com/training/wearables/data/cloud-backup-restore), where the user restores data to a new Wear OS device.

When the user requests a transfer, the [Wearable Data Layer](https://developer.android.com/training/wearables/data/data-layer) delivers
[`DataItem`](https://developers.google.com/android/reference/com/google/android/gms/wearable/DataItem) objects, originally stored on one mobile device, to the other
mobile device. This allows a seamless experience for users of your app.

This document describes how you can configure your Wear OS app, and its
companion mobile app, to support this scenario.

## Preparation

The data transfer process handles `DataItem` objects differently, depending on
which app owns the data:

Objects owned by the Wear OS app
:   These objects are preserved on the Wear OS device.

Objects owned by the mobile app

:   These objects are archived on the old device. The system then packages the
    archived data into a [`DataItemBuffer`](https://developers.google.com/android/reference/com/google/android/gms/wearable/DataItemBuffer) object and delivers this data to the
    mobile app that's installed on the new mobile device.

    Immediately after the archive is delivered, the Wearable Data Layer invokes
    the [`onNodeMigrated()`](https://developers.google.com/android/reference/com/google/android/gms/wearable/WearableListenerService#onNodeMigrated(java.lang.String,%20com.google.android.gms.wearable.DataItemBuffer)) listener, similarly to how your app is notified
    when data is written by the Wear OS device.
    | **Note:** Data is transferred only if it's stored in the Wearable Data Layer.

## Preserve transferred data

| **Warning:** To avoid losing data, follow the guidance in this section.

It's your app's responsibility to preserve the transferred `DataItem` objects.
Shortly after the data is delivered to the new mobile device, the archive is
deleted off of the old device.

Make sure each of the following conditions is true:

1. Your app is installed on both mobile devices that are involved in the transfer.
2. The mobile apps, installed on each mobile device, have package signatures that match.

Otherwise, the archived `DataItem` objects aren't delivered and are instead
discarded.

## Receive data from the old mobile device

To receive data on the new mobile device that was archived on the old mobile
device, your mobile app must implement the [`onNodeMigrated()`](https://developers.google.com/android/reference/com/google/android/gms/wearable/WearableListenerService#onNodeMigrated(java.lang.String,%20com.google.android.gms.wearable.DataItemBuffer)) callback,
part of the `WearableListenerService` class. To do so, complete the following
steps:

1. In your mobile app's build file, include a dependency on the latest version
   of the wearable library in Google Play services:

   ```groovy
   dependencies {
       ...
       implementation 'com.google.android.gms:play-services-wearable:19.0.0'
   }
   ```
2. Declare and export the `WearableListenerService` in your app's
   manifest file:

       <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. Create a service class which extends `WearableListenerService` and overrides
   `onNodeMigrated()`.

   **Caution:** To preserve system resources such as battery life, and to prevent ANRs, don't execute any power-demanding or time-consuming tasks in the `onNodeMigrated()` handler.  

   ### Kotlin

   ```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

   ```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.
       }
   }
   ```

## Recommended for you

- Note: link text is displayed when JavaScript is off
- [Integrate a Wear OS module](https://developer.android.com/health-and-fitness/guides/basic-fitness-app/integrate-wear-os)
- [Conserve power and battery](https://developer.android.com/training/wearables/apps/power)