ユーザーが 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
オブジェクトは、アプリ側で保持してください。データが新しいモバイル デバイスに送られるとすぐに、以前のデバイスからアーカイブが削除されます。
次の各条件を満たしていることを確認してください。
- 転送に関与するどちらのモバイル デバイスにもアプリがインストールされていること。
- それぞれのモバイル デバイスにインストールされているモバイルアプリのパッケージ署名が一致すること。
上記の条件を満たさないと、アーカイブされた DataItem
オブジェクトは送信されず、破棄されます。
以前のモバイル デバイスからデータを受信する
以前のモバイル デバイスにアーカイブされたデータを新しいモバイル デバイスで受信するには、モバイルアプリで、WearableListenerService
クラスの onNodeMigrated()
コールバックを実装する必要があります。そのための手順は次のとおりです。
モバイルアプリのビルドファイルに、Google Play 開発者サービスのウェアラブル ライブラリの最新バージョンへの依存関係を追加します。
dependencies { ... implementation 'com.google.android.gms:play-services-wearable:18.2.0' }
アプリのマニフェスト ファイルで
WearableListenerService
を宣言してエクスポートします。<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>
WearableListenerService
を拡張して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 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
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. } }
あなたへのおすすめ
- 注: JavaScript がオフになっている場合はリンクテキストが表示されます
- Wear OS モジュールを統合する
- 電力とバッテリーを節約