Android
AndroidWear

Android Wear開発まとめ

More than 3 years have passed since last update.

このドキュメントを読んだので超ざっくりまとめる。

基本的に、この機能はこの為にありますとか、こういうデザインにしましょうという話はしない。

デザインのガイドラインがあるので一度目を通しておくといいかも。

あとツールの使い方とか、細かい手順も省略。


通知編

※Androidに以前からあった通知機能については触れないので悪しからず

Handheld(電話とかタブレット)とWearableが接続してると、Handheldの通知が自動でWearableにも共有される(とは言え、Wearable固有の機能性を通知に追加するとUX的にいいよ)。


通知を作る



  • NotificationCompat.Builderで通知を作る(従来の方法と同じ)


  • NotificationCompat.Builder#addActionでアクションボタンを追加できる(従来の方法と同じ)


Wearableだけのアクションボタン



  • NotificationCompat.WearableExtenderというクラスをインスタンス化して使う


  • WearableExtender#addActionに(従来の方法で作った)NotificationCompat.Actionを渡す


  • NotificationCompat.Builder#extendWearableExtenderを渡す

  • 一度でもこの方法でアクションボタンを追加するとNotificationCompat.Builder#addActionで追加されたアクションボタンはWearableの方では表示されなくなる


Big View



  • BigTextStyleまたはInboxStyleのスタイルが適用された通知は、Wearable側でもいい感じに表示される

  • スタイルの設定の仕方は、従来のやり方と同じ


通知にWearable固有の機能を追加する

先に少し触れたけどWearableExtenderというクラスをインスタンス化して使う。これに対して必要なプロパティを設定していく。そしてこのWearableExtenderインスタンスをNotificationCompat.Builder#extendでセットすればOK。


通知を伝える



  • NotificationManagerCompatを使う


  • NotificationManagerだとWearableExtenderで追加した機能が動かないよ


音声入力を受信する


  • メールの返信とかテキストを入力するアクションを含んだ通知では、普通はアクティビティを起動してテキストを入力していく

  • そのような通知がWearableにあるとき、キーボードからの入力じゃなくてユーザにしゃべらせたり事前に定義しといたテキストを選んでもらうことができる

  • そのテキストが付加されたインテントをhandheldのアプリに送信できるよ

  • エミュレータでは音声入力できないのでキーボードで入力する


音声入力の定義



  • RemoteInput.Builderをインスタンス化して使う

  • コンストラクタは文字列を受け取る: 入力されたテキストを取得するために使うKey


  • RemoteInput.Builder#setChoicesCharSequence配列を渡すと、それが事前定義されたテキストとしてユーザは音声入力の代わりに選択できる


通知のアクションとして音声入力を追加する



  • RemoteInputオブジェクトをNotificationCompat.Action.Builder#addRemoteInputに渡すことでアクションに音声入力を追加できる


文字列として音声入力を受け取る


  • アクションのインテントにRemoteInput.getResultsFromIntentを適用して得られるBundleから取得する

  • そのBundleから、RemoteInput.Builderのコンストラクタ呼び出し時に渡したKeyで音声入力を文字列として取得する


通知にページを追加する



  1. NotificationCompat.Builderを使って従来と同じ方法で通知を作る(これがWearable側でのメイン、つまり最初のページになる)


  2. NotificationCompat.Builderを使ってWearable用の追加ページとしてNotificationを作る


  3. WearableExtenderaddPageメソッドやaddPagesメソッドを使って複数ページのあるNotificationを作る


通知をスタックする

通知をスタック内にグルーピングする方法。


通知をグループに追加する



  • NotificationCompat.Builder#setGroupを使って当該の通知をグループに追加する


  • setGroupは引数にGroupKey(String)を取る

  • ビルドした通知は普通にNotificationManagerCompat#notifyで発行する

  • 後ほど同一GroupKeyを持った別の通知が発行された際には、同じスタック内に表示される


Summary Notificationを追加する


  • Summary Notificationは、Wearable側では表示されずHandheld側でのみ表示される


  • NotificationCompat.Builder#setGroupSummarytrueを渡すとそれはSummary Notificationになる

  • グループのSummary(要約)となる通知なので、もちろんsetGroupでGroupKeyを指定すること

  • Summary NotificationはWearableには表示されないけど影響を与える: WearableExtendersetBackgroundaddActionの呼び出しなど(例えばスタック全体の背景を指定したいとき)


Wearable用アプリ編

基本的に普通のアプリと同じ。

だけどデザイン、ユーザビリティ、機能の量で大きく異なるので注意。

↓主な違い


  • アクティビティはずっと表示できない。スリープから復帰したらWearホーム画面が表示される。ずっと表示したいのがあるときは通知でやること。

  • WearableはHandheldと比べるとサイズも機能も小さい。なので操作は極力Handheldで行い、結果をWearableに送る感じで。

  • ユーザはWearableに直接アプリをダウンロードしない。WearableアプリはHandheldアプリにバンドルされてて、Handheldアプリがインストールされるときにシステムが自動でWearableアプリもインストールしてくれる。開発のために直接Wearablにインストールすることはできる。

  • Wearableアプリは標準のAndroid APIの大部分にアクセスできるけど、次に挙げるのはダメ


    • android.webkit

    • android.print

    • android.app.backup

    • android.appwidget

    • android.hardware.usb




Wearableアプリを作って動かす

Android Wearエミュレータ、デバイスのセットアップやプロジェクト作成、インストールについてはこちらを参照。


カスタムレイアウトを作る


Custom Notification


  • カスタムレイアウトをアクティビティに載っけて、それで通知できる(ただしHandheldとの自動同期はない)

  • アクティビティはマニフェストで、android:exported="true" android:allowEmbedded="true" android:taskAffinity=""と設定する必要がある

  • アクティビティのテーマをTheme.DeviceDefault.Lightにするといいよ

  • このアクティビティを起動するPendingIntentを作る


  • WearableExtender#setDisplayIntentでそのPendingIntentを設定する

  • あとは普通に通知をnotifyすればいい


Wearable UI Library

Android Studioで使える非公式のUIライブラリがあるらしい。こちらを参照。


音声機能を追加する

WearはSystem-providedとApp-providedの2種類の音声アクションを提供している。


System-provided


  • システム、つまりAndroid Wearプラットフォームが提供する音声アクション

  • ユーザがしたいことを言って、システムがそれを理解してアクティビティを起動する

  • 具体的にはインテントフィルタで音声アクションを拾う感じ

Wearがサポートする音声インテント一覧はこちらを参照。


App-provided


  • 音声アクションによって直接アクティビティを起動できる

  • "Start <アクティビティ名>"みたいに言うと、対象のアクティビティが起動する(日本語の場合はどうなんだろ?)

  • このアクティビティは、Handheld上でランチャーアイコンから起動するやつと同じ

  • <アクティビティ名>はマニフェストでアクティビティに設定したandroid:labelの値


Wearableアプリをパッケージングする


  • WearableアプリはHandheldアプリ内にパッケージする必要がある

  • ユーザはWearableアプリを直接インストールすることはできないから

  • システムが自動的にWearableにWearableアプリをプッシュする

Android Studioを使った、あるいは手作業でのパッケージング手順はこちらを参照。


データの送信、同期編

Google Play Servicesの一部であるWearable Data Layer APIは、Handheld-Wearableアプリ間の通信チャネルを提供する。


Data Itemsを同期する


  • DataItemはHandheld-Wearable間のデータ同期のためのインタフェースを定義する

  • DataItemは一般に、PayloadとPathで構成される

  • Payloadは最大100KBのbyte配列(だから好きなデータを載せられるしオブジェクトのシリアライズ/デシリアライズも可能)

  • Pathはスラッシュから始まるユニークな文字列(例えば"/path/to/data")

普通はDataItemを直接実装することはない。代わりに


  1. アイテムを一意に識別するPathを指定してPutDataRequestオブジェクトを生成する


  2. setDataメソッドでPayloadをセットする


  3. DataApi.putDataItemを呼び出し、Data Itemの生成を要求する

  4. Data Itemsが要求されるとシステムはDataItemインタフェースを適切に実装したオブジェクトを返す

setDataの代わりに次に紹介するData Mapの方が簡単なのでおすすめらしい。


Data Mapで同期する



  • Bundleに似たインタフェースのDataMapクラスを使うといいよ


  • PutDataMapRequestオブジェクトを生成してgetDataMapメソッドでData Mapを取得できる

  • put...メソッド(例えばputString)で必要な値をセットできる


  • PutDataMapRequest.asPutDataRequestPutDataRequestが取得できるのでDataApi.putDataItemに渡してData Itemを生成する


Data Itemイベントをリスンする

後述


Assetの転送


  • 画像のようなBLOBをBluetoothで送るには、AssetをData Itemに付加する

  • Assetは再送を防ぐため、Bluetoothの帯域幅を節約するためにデータのキャッシュを自動的に扱う


Assetを転送する


  • Assetを作るには、Assetクラスのcreate...メソッドを使う(例えばcreateFromBytes)

  • Assetを得たらDataMapとかPutDataRequestputAssetする。


Assetを受信する

サンプルコード


メッセージの送受信


  • メッセージはData Itemと違ってHandheld-Wearable間同期はないよ

  • メッセージは"fire-and-forget"的な片方向通信

  • メッセージを送って、なんかして、メッセージを送り返せばrequest/responseモデルにもできる


メッセージを送信する

接続相手側のアクティビティを起動させるメッセージを送るサンプルコード

このコードは、メッセージが受信されるかタイムアウトするまでブロックするらしい


メッセージを受信する

後述


Data Layerイベントのハンドル


Data Layerの呼び出しのステータスを待つ


  • Data Layer APIはPendingResultを返すことがある(例えばputDataItem)


  • PendingResultを使って同期的にも非同期的にもオペレーションの結果を得られる


  • PendingResult#awaitで同期的に結果を得る


  • PendingResult#setResultCallbackで非同期で結果を得る


Data Layerイベントをリスンする

Data Layerイベントをリスンするには、WearableListenerServiceを継承したサービスを作るか、リスナを実装したアクティビティを作るかの2つの選択肢がある。


WearableListenerService

WearableListenerService固有のメソッド



  • onDataChanged: Data Itemオブジェクトの生成、変更、削除時に呼び出される。接続している片方で起こったイベントは、双方に通知される


  • onMessageReceived: 接続相手が送ったメッセージを受信したときに呼び出される


  • onPeerConnectedonPeerDisconnected: 接続したとき、切断したときに呼び出される。接続している片方で起こったイベントは、双方に通知される

WearableListenerServiceを継承したサービスは、上記のメソッドを必要に応じて実装して、com.google.android.gms.wearable.BIND_LISTENERアクションを拾うようにインテントフィルタを設定する。


Data Layerコールバック内のパーミッション


  • Data Layerコールバック内でパーミッションが必要な操作を行うと失敗する: IPCにより呼び出されるため


  • Binder.clearCallingIdentityメソッドを呼び出せば大丈夫

  • 最後にBinder.restoreCallingIdentityを呼び出して元に戻すこと


リスナアクティビティ

次のリスナを1つ以上実装すればアクティビティでイベントをリスンできる。


  • DataApi.DataListener

  • MessageApi.MessageListener

  • NodeApi.NodeListener

アクティビティのライフサイクルに合わせていろいろやる必要がある(詳細は公式ドキュメントを参照)。