Google GlassはNexus 5で十分にプロトタイプできるか?

こんにちは、ATLでウェアラブルデバイスの研究をしている吉村です。ふとしたことからGoogle Glassに触れることになってここ3〜4回ほど記事を書かせていただいていたわけなのですが、このデバイスはなかなか面白いものです。ボイスコマンドで制御され、通知が入れば首を振るだけで視野の右上にぼんやりと画面が投影されて確認でき、終われば勝手に画面が消えている…といった形のUXは、通知→ポケットから取り出して起動→情報を確認→終了する、といったような一般的な携帯電話が提供するものとは全く違い、当然アプリにもこれまでとは全く違うUXが求められます。…この辺りはもう何回も書いているわけなのですが 😉

しかし、これの上で動作するアプリを作ろうにもエミュレータは公式にはなく、実機を用意しようにも入手経路や費用面でいろいろと苦労させられるのが現状です。いろいろ考えた末、Nexus 5を使用してGlasswareを(ギリギリ)プロトタイプできるような感触を得たので、今回はそれについて書かせてもらえたらと思います。ふわふわした話になってしまう可能性がありますが、その辺はなにとぞよろしくお願いいたします m(__)m

最初に断わっておきますが、これはあくまでも私が研究に携わった中で得た一つの知見としてとらえていただければ幸いです!

ここで挙げる方法が常に最善なはずはありませんし、そうでない場合を自分もいくつか経験しています。

Nexus 5?

素のAndroid 4.4(XE16以降がベースにしているバージョン)が動く、比較的手軽なデバイスだからです。今回はAndroidベースとはいえ違うシステムで動作させるものをプロトタイプしようとしているので「素の」というところがかなり重要になります。一方でハードウェアスペック的にはGoogle GlassはどちらかというとNexus Sに似ているので、ひょっとするとCyanogenMod 11をNexus Sで動かした方が適当な場合もあるかもしれません。

ワークフロー

基本的には適当なエミュレーションレイヤーを挟み込み、共通項の多いActivityを中心にモデリングを進め、そして一通り片付いたらGlassへポートする、という段階的なアプローチがある程度有効です。

モデリング

だいたい以下のような感じにGlass固有のAPIをモックするようなレイヤーを挿入します。

LiveCard→Ongoing Notification

GlasswareではServiceLiveCardを組み合わせるケースが一般的ですが、これはServiceNotification、あるいはWidgetRemoteViewsでエミュレートするのが良いのではないかと思います。

だいたいこのように書かれるところ:


これをAndroidのNotificationで動作させるためのエミュレーションレイヤーはこのような感じに:


Mirror API→GCM+Notification?

同様に、Mirror APIGoogle Nowで…としたいのですが、残念ながら今のところGoogle Nowに独自カードを提示させることはできません。そのため、現在のところはGoogle Cloud Messaging (GCM)などを使用してリモートでNotificationを飛ばせるようなサービスをどこかに立て、それを使うことでエミュレートするほかにはなさそうです。

このようなサービスの書き方ですが、とりあえずGoGoogle App Engineを使用してこのような形に書くことができます(注: 最新のGoogle Cloud SDKでは多少変わっているかもしれません。)

まずapp.yamlから。


ありがたいことにGoにもGCM関係をハンドリングしてくれる gcm というライブラリがあり、ここではそれを使用させてもらうことにします。普通に開発環境で動かすにはgoapp経由でインストールするだけで良いのですが、このままだとGoogle App Engineへ展開した際に漏れてしまうので適当に作業ディレクトリへコピーしておきます。


ロジックの実装ですが、reflector/reflector.goとして、以下のように書いておきます。GCM関連の処理はライブラリで行なうので、ここではデバイスの登録を受けつけてDatastoreに書いていたり拡散したいパラメータをライブラリに渡しているくらいなもので実にシンプルなものです。


これを、以下のようにまとめて適当にGoogle App Engineへ展開しておきます。


これでサーバ環境の準備は完了です。これでAndroid端末を http://your-application-id-goes-here.appspot.com/device へregid=…としてPOSTすることで登録ができ、その後適当に http://your-application-id-goes-here.appspot.com/ へmessage=….という形のデータをPOSTすることで外から通知を行なうことができるようになりました。

あとはこれを端末で適当に受けてNotificationなど出すことで、外部からnon-obtrusiveな通知を送るためにMirror APIを使用しているような場合についてはかなり手荒ながらエミュレートができたかな、と思います。

この例では通知対象を限定すらしていないので通知すると全端末に飛んでしまいます。とはいえテスト用途でとりわけ小規模な使い方をしている限りあまり問題にならないかと思いますが…

GestureDetector→エミュレート

次です。さて、GestureDetectorはAndroid SDKにもあるのですが、Glasswareの場合GDK特有のGestureDetectorを使用する必要があります(さもないと検出できない)。次のようなコードがあったとします。

Glass:


上のコードをAndroidで動作させるために必要なエミュレーションレイヤーはだいたい次のような形になります。実質的な検出ロジックにおいては実装を割愛していますが、こちらはAndroid SDKで普通に検出する場合とほぼ同等の実装になるのではないかと思います:


GDKのGestureクラスは単なるenumであり、こちらも当然Android SDKとは互換性がないのでこちらも定義しておきます。


最後にActivityレイヤーですべてのMotionEventを解析するようにします。


これで最初に挙げたGoogle Glass用のコードが動作するはずです。

GCM→Standalone GCM

GlassはGoogle Play Servicesを持っていないので、GCMを使用する場合にはStandalone版を使用することになります。Standalone版はAndroidでも特に問題なく使えるので、こちらを使用しておけばそのままGlassで動作させることができます。

Card→LayoutInflater

Cardはパラメータを受けとってGlass標準のレイアウトを作成するヘルパー的な役目をしていますので、簡単なものであればLayoutInflaterを使用して適当なカスタムレイアウトをロードさせるようにするのが適当でしょう。

Glass:


このようなコードがある場合、Androidでは以下のようにエミュレーションを行なうことになるでしょう。この例ではaddImageなどのメソッドは定義していませんが、もっと複雑な例では必要に応じて追加することになると思います。


メニュー

無理にカスタム設計するよりも、透明ActivityOption Menuによるシステム標準のエミュレーション機構に頼るのが最善です。ただ、これをそのままAndroidで動かすと見かけがかなり違ってきてしまいますが…

Glass:


メニューを起動するための透明Activityについては以下のようになります。


VoiceTrigger関連

メタデータはそのままでOKですが、クラス参照は次のような形でスタブ化しておく必要があります。


当然これだけではボイスコマンドを聞いてくれませんので、ボイスコマンドに対応するServiceをandroid.intent.action.MAIN/android.intent.category.LAUNCHERから別に起動できるようにするようにしておきます。

また、Tasker/AutoVoiceなどを併用することでボイスコマンドを使用して起動させることが可能になります。

※詳細な方法はlifehackerの記事によくまとまっているのでそちらをご参照ください 🙂

ポーティング

エミュレーションレイヤーを外して、非互換性があるようなら適当に直します。この際、アプリ自体が単純だったりレイヤーの設計がうまく行っていれば特にそれほど問題になることはないのですが、実際のポーティングでは以下のようなところが問題になりやすい感じがします。

OpenGL ES 2.0

Glassが搭載しているGPUはNexus Sと同じSGX540なので、Nexus 5とはかなり違います。このためシェーダーのコンパイルに失敗したりすることがあるので、このような場合はNexus S+CyanogenMod 11あたりで動作を確認するのが良いでしょう。

発熱

GlassのCPU自体はNexus Sと同等なのですが、フォームファクタが違いすぎるので無理をさせてしまうとすぐに高温になります。高温な状態になると”ok, glass”と交互に”Glass must cool down to run smoothly.”というメッセージが表示されてくるので注意しましょう。

image-0

まとめ

Google GlassとAndroid携帯端末はとても良く似ています。基本的にフロント面から遠くなればなるだけ共通項が増えてくるようなイメージを少しでも伝えられたでしょうか。ここに挙げた差分は自分で研究に参加している時にたまたま当たったものだけでありますが、大まかなところではこのくらいではないかと思います。懸念通りふわふわしたエントリになってしまいましたが、もしGoogle Glassで開発をしたくなったときこれが開発効率向上の役に立つことを祈ります。