將 Wear OS 資料轉移到新行動裝置

使用者設定 Wear OS 裝置時,會將 Wear OS 裝置連結至特定行動裝置。使用者日後可能會決定取得新的行動裝置,並將現有的 Wear OS 裝置連結至新行動裝置。部分與 Wear OS 裝置相關的資料會儲存在目前連結的行動裝置上。

自 Wear OS 4 起,當使用者連結至新行動裝置時,即可將 Wear OS 資料轉移至新行動裝置。資料轉移完畢後,系統會自動同步處理資料。

當使用者要求轉移資料時,Wearable Data Layer 會將原本儲存在行動裝置的 DataItem 物件傳送至另一部行動裝置。這能讓應用程式使用者享有流暢的使用體驗。

本文件說明如何設定 Wear OS 應用程式和相關的行動應用程式,以便在此情境中運作。

準備

資料移轉程序會根據擁有資料的應用程式,以不同方式處理 DataItem 物件:

Wear OS 應用程式擁有的物件
這些物件會保留在 Wear OS 裝置上。
行動應用程式擁有的物件

這些物件會封存在舊裝置上。接著,系統會將封存的資料封裝到 DataItemBuffer 物件中,並將這些資料傳送至安裝在新行動裝置上的行動應用程式。

傳送封存資料後,Wearable Data Layer 會立即叫用 onNodeMigrated() 事件監聽器,這類似於系統在 Wear OS 裝置寫入資料時通知應用程式的方式。

保留已轉移的資料

應用程式有責任保留轉移的 DataItem 物件。資料傳送到新行動裝置後不久,系統就會刪除舊裝置上的封存資料。

請確認符合下列各項條件:

  1. 轉移作業中的兩部行動裝置都已安裝您的應用程式。
  2. 兩部行動裝置上安裝的行動應用程式都有相符的套件簽名。

如果不符合上述條件,系統不會傳送已封存的 DataItem 物件,而會捨棄物件。

接收舊行動裝置的資料

如要在新行動裝置上接收舊行動裝置的封存資料,行動應用程式必須實作 onNodeMigrated() 回呼,該回呼是 WearableListenerService 類別的一部分。如要這樣做,請完成下列步驟:

  1. 在行動應用程式的建構檔案中,加入 Google Play 服務中最新版穿戴式裝置程式庫的依附元件:

    dependencies {
        ...
        implementation 'com.google.android.gms:play-services-wearable:19.0.0'
    }
  2. 在應用程式的資訊清單檔案中宣告並匯出 WearableListenerService

    <service
        android:name=".snippets.datalayer.MyWearableListenerService"
        android:exported="true"
        tools:ignore="ExportedService">
        <intent-filter>
            <action android:name="com.google.android.gms.wearable.NODE_MIGRATED" />
            <data android:scheme="wear" android:host="*" />
        </intent-filter>
    </service>

  3. 建立擴充 WearableListenerService 並覆寫 onNodeMigrated() 的服務類別。

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