Android Wearでwearとスマホ間でデータをやりとりする話

2019/05/18追記: この記事の情報は古いので公式ドキュメントを参照してください。


データのやりとりはWearable.DataApiを使うことでやりとりできます。Wearable.MessageApiを使うことでもできます。

両者の違いはこんな感じ。

DataApi

  • 接続が切れていても送信できる
  • データはonDataChangedで受け取る
  • 送れるデータは100KBまでだが、Assetを使うことで大きいデータも送れる
  • データを送信するというより、DataItemを更新して、その更新を通知するイメージ

MessageApi

  • 現在接続中のノードに対してデータを送信することができる
  • データはonMessageReceivedで受け取る
  • データを送る際にはノードを指定する必要がある

ノードIDについて

当たり前ですが、ノードIDはAndroid Wear端末とスマホで異なります。

WatchFaceを作成して、その設定画面を用意している場合、WearのノードIDはスマホ側では簡単に取得できます。

mobile側の設定画面となるActivityでgetIntent().getStringExtra(WatchFaceCompanion.EXTRA_PEER_ID)とするとWearのノードIDが取得できます。これは設定画面の起動がAndroid Wearアプリ経由で行われるためです。

一方Wearから、もしくはmobileからでもAndroid Wearアプリを経由しない起動の仕方をするアプリの場合はこの方法では取得できません。

その場合はNodeApi.getConnectedNodesを使うことで、接続されている端末のノードリストを取得することができます。現状スマホとAndroid Wearは1:1でペアリングされるはずなので、これで相手方のノードIDを取得できるでしょう。(将来的に複数ペアリングできるようになったらどうやればいいんでしょうね?)

DataApiを使ったデータ送信の注意点

[DataApi – Android Developers]のConcurrencyにありますが、DataApiを使ったからといってmobileとwearでDataItemが全く同じになるわけではありません。

onDataChanged()内であれば正しいデータが参照できます。これは変更があったDataItemが通知されてきているからです。

しかしAndroid Wear端末を再起動した後に、DataApiを使って送信された設定データを読み込もうとした時に問題が生じます。

wear側からDataItemを識別するUriでデータを取りに行っても、mobile側の設定と齟齬が生じている可能性があります。

その理由はDataItemが以下のように識別されているからです。

wear://ノードID/パス

mobileで作ったDataItemはmobileのノードIDで識別されます。同じパス文字列で識別しているからといって、勝手にwearのノードIDのものが変更されるわけではありません。

これはWatchFaceのサンプルコード(com.example.android.wearable.watchface)を見ると何となく分かると思います。サンプルコードでは、mobileからのDataItemの変更を受け取ると、wear側で同じデータを上書きする処理を行っています。

サンプルのようにmobileからもwearからもデータを送り合うようなアプリの場合、どちらのノードのDataItemも常に同じ状態にするように配慮しないと齟齬が生じて困ることになると思います。

片側からしか送らないというのであれば、ノードIDを指定してDataItemを取りに行くのもありかもしれません。

Amazonのほしいものリストを公開しています。仕事で欲しいもの、単なる趣味としてほしいもの、リフレッシュのために欲しいものなどを登録しています。 寄贈いただけると泣いて喜びます。大したお礼はできませんが、よりよい情報発信へのモチベーションに繋がりますので、ご検討いただければ幸いです。