Google glassにおける操作の検出
Google glassは、右フレームを指でなぞったりカメラボタンを押すことによって、androidのタッチパッドに相当する操作を行うことができます。おおまかな操作方法はgoogle glassのサポートページに記載されています。
Immersionのactivityでは、各種のイベントをフックするメソッドをオーバーライドしたり、より高次のタッチジェスチャを検出すインタフェースを実装することで、ユーザによる操作に独自の処理を割り付けることができます。一方、periodic notification (static cardによる通知)やongoing task (live cardによる逐次更新タスク)では、タイムライン上の特定の処理に操作が固定されており、オーバーライドすることはできません。
今回は、immersionのactivityでさまざまな操作を行うときに、どのようなイベントをフックできるのか調査しました。
3種類のイベント: KeyEvent, MotionEvent, GestureDetector
タッチパッドに関するイベントは大きく3つに分類されます。これらのうち、3番目のリスナーのみがGoogle Glass特有の機能として提供されています。
- KeyEvent。通常のandroid端末ではキーやボタンに対応するイベントです。右フレームをタップする操作(KEYCODE_DPAD_CENTER)、右フレーム上部のカメラボタンを押す操作(KEYCODE_CAMERA)、右フレームを上から下にスワイプする操作(KEYCODE_BACK)があります。詳細はandroidのドキュメントを参照してください。
- MotionEvent。通常のandroidではマウス、ペン、指、トラックパッドなどの操作に相当するイベントです。Google glassでは右フレームをトラックパッドのように使用します。ACTION_DOWN、ACTION_MOVE、ACTION_UPなどにより、複数の指の動きを検出し処理することができます。ゲームなどで指の細かい動きを処理する場合は、MotionEventのイベントを利用します。詳細はandroidのドキュメントを参照してください。
-
GestureDetector。GestureDetectorはGlass Development Kit (GDK)が用意している高次のリスナーです。複数のKeyEventやMotionEventをまとめて、タップ、スワイプ、スクロールなど標準的な操作(タッチジェスチャ)
のListenerを用意しているので、タッチジェスチャに対する処理を容易に実装することができます。詳細はGDKのドキュメントを参照してください。
タッチジェスチャの種類
GestureDetectorが用意している標準的なタッチジェスチャには以下のものがあります。これらは、com.google.android.glass.touchpad.Gestureに定義されています。
- TAP: 1本の指でタップする
- TWO_TAP: 同時に2本の指でタップする
- THREE_TAP: 同時に3本の指でタップする
- LONG_PRESS: 1本の指で暫く押さえる
- TWO_LONG_PRESS: 同時に2本の指で暫く押さえる
- THREE_LONG_PRESS: 同時に3本の指で暫く押さえる
- SWIPE_LEFT: 後方に向かってスワイプする
- SWIPE_RIGHT: 前方に向かってスワイプする
- SWIPE_DOWN: 下方に向かってスワイプする
- SWIPE_UP: 上方に向かってスワイプする
- TWO_SWIPE_LEFT: 同時に2本の指で後方に向かってスワイプする
- TWO_SWIPE_RIGHT: 同時に2本の指で前方に向かってスワイプする
- TWO_SWIPE_DOWN: 同時に2本の指で下方に向かってスワイプする
- TWO_SWIPE_UP: 同時に2本の指で上方に向かってスワイプする
それぞれのタッチジェスチャで生起するイベント
それでは、それぞれのタッチジェスチャで生起するイベントを調査します。ただし、この記事ではイベントの種類だけをlogcatに出力しています。実際にはイベントによって時間、速度や方向などを検出することができます。
なお、この調査を行ったプログラムのソースはgithubに置いてあります。
TAP
タップはBaseListenerでTAPジェスチャを検出します。また、KEYCODE_DPAD_CENTERボタンのACTION_DOWNおよびACTION_UPという2種類のイベントも事後に発生しています。GenericMotionEventとFingerListenerは途中の詳細な指の動きを捕捉しています。
I/gestures( 2123): GenericMotionEvent: ACTION_DOWN, pointer-count=1
I/gestures( 2123): FingerListener: 0 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_UP, pointer-count=1
I/gestures( 2123): BaseListener: TAP
I/gestures( 2123): FingerListener: 1 -> 0
I/gestures( 2123): KeyDown: KEYCODE_DPAD_CENTER, ACTION_DOWN
I/gestures( 2123): KeyUp: KEYCODE_DPAD_CENTER, ACTION_UP
TWO_TAP
2本の指によるタップは、BaseListenerでTWO_TAPジェスチャを検出します。指が増えるごとにGenericMotionEventおよび対応するFingerListenerが生起しています。また、途中で多数発生しているACTION_MOVEイベントは、細かい指の動き捕捉しているものです。
I/gestures( 2123): GenericMotionEvent: ACTION_DOWN, pointer-count=1
I/gestures( 2123): FingerListener: 0 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_DOWN(0), pointer-count=2
I/gestures( 2123): FingerListener: 1 -> 2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_UP(0), pointer-count=2
I/gestures( 2123): FingerListener: 2 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_UP, pointer-count=1
I/gestures( 2123): BaseListener: TWO_TAP
I/gestures( 2123): FingerListener: 1 -> 0
THREE_TAP
3本の指によるタップは、BaseListenerでTHREE_TAPジェスチャを検出します。途中で検出中の指が2本になったり3本になったりしていますが、ユーザの意識としてはとくに途中で指を離したりはしていません。GenericMotionEventやその結果生起するFingerListenerは感度が高く複数本の指の検出には使わない方がよさそうです。BaseListenerも、最終的にFingerListenerがすべての指が離れたことを検出したときに、それまでもっとも多く検出した指の数から結果を導いているようです。
I/gestures( 2123): GenericMotionEvent: ACTION_DOWN, pointer-count=1
I/gestures( 2123): FingerListener: 0 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_DOWN(0), pointer-count=2
I/gestures( 2123): FingerListener: 1 -> 2
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_DOWN(0), pointer-count=3
I/gestures( 2123): FingerListener: 2 -> 3
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_UP(0), pointer-count=3
I/gestures( 2123): FingerListener: 3 -> 2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_DOWN(0), pointer-count=3
I/gestures( 2123): FingerListener: 2 -> 3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_UP(0), pointer-count=3
I/gestures( 2123): FingerListener: 3 -> 2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_DOWN(0), pointer-count=3
I/gestures( 2123): FingerListener: 2 -> 3
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_UP(0), pointer-count=3
I/gestures( 2123): FingerListener: 3 -> 2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_DOWN(0), pointer-count=3
I/gestures( 2123): FingerListener: 2 -> 3
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_UP(0), pointer-count=3
I/gestures( 2123): FingerListener: 3 -> 2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_DOWN(0), pointer-count=3
I/gestures( 2123): FingerListener: 2 -> 3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_UP(0), pointer-count=3
I/gestures( 2123): FingerListener: 3 -> 2
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_UP(0), pointer-count=2
I/gestures( 2123): FingerListener: 2 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_UP, pointer-count=1
I/gestures( 2123): BaseListener: THREE_TAP
I/gestures( 2123): FingerListener: 1 -> 0
LONG_PRESS
右フレームで指を暫く押しつづけると、BaseListenerでLONG_PRESSジェスチャを受け取ることができます。このジェスチャ以外に生起するイベントはTAPと同じです。指の細かい動きを検知しているため多数のACTION_MOVEが発生しています。また、LONG_PRESSは指を離したとき(ACTION_UPの後)に生起するのではなく、一定時間継続して押されると指を離さなくても生起するようです。
I/gestures( 2123): GenericMotionEvent: ACTION_DOWN, pointer-count=1
I/gestures( 2123): FingerListener: 0 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): BaseListener: LONG_PRESS
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_UP, pointer-count=1
I/gestures( 2123): FingerListener: 1 -> 0
TWO_LONG_PRESS
同様に、2本の指で暫く押しつづけると、TWO_LONG_PRESSが生起します。
I/gestures( 2123): GenericMotionEvent: ACTION_DOWN, pointer-count=1
I/gestures( 2123): FingerListener: 0 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_DOWN(0), pointer-count=2
I/gestures( 2123): FingerListener: 1 -> 2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): BaseListener: TWO_LONG_PRESS
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_UP(0), pointer-count=2
I/gestures( 2123): FingerListener: 2 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_UP, pointer-count=1
I/gestures( 2123): FingerListener: 1 -> 0
THREE_LONG_PRESS
さらに、3本の指の場合も同様、THREE_LONG_PRESSが生起します。
I/gestures( 2123): GenericMotionEvent: ACTION_DOWN, pointer-count=1
I/gestures( 2123): FingerListener: 0 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_DOWN(0), pointer-count=2
I/gestures( 2123): FingerListener: 1 -> 2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_DOWN(0), pointer-count=3
I/gestures( 2123): FingerListener: 2 -> 3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): BaseListener: THREE_LONG_PRESS
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=3
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_UP(0), pointer-count=3
I/gestures( 2123): FingerListener: 3 -> 2
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_UP(0), pointer-count=2
I/gestures( 2123): FingerListener: 2 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_UP, pointer-count=1
I/gestures( 2123): FingerListener: 1 -> 0
SWIPE_LEFT
ここまでタップ、長押しで生起するイベントを確認してきましたが、ここからはスワイプ系の操作を実施します。まずは、左右方向のスワイプを発生させてみます。
SWIPE_LEFTは、LEFTとはいうものの実際には右フレームを前方から後方にスワイプします。ここでは詳細をログに出していませんが、GenericMotionEventまたはより高次のScrollListenerで指の動きの詳細(場所、移動距離、速度等)を把握することができます。
I/gestures( 2123): GenericMotionEvent: ACTION_DOWN, pointer-count=1
I/gestures( 2123): FingerListener: 0 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): ScrollListener: disp=-158.0, delta=-158.0, v=-3.2050996
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): ScrollListener: disp=-519.0, delta=-361.0, v=-6.346878
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): ScrollListener: disp=-759.0, delta=-240.0, v=-8.334586
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): ScrollListener: disp=-1057.0, delta=-298.0, v=-8.13843
I/gestures( 2123): GenericMotionEvent: ACTION_UP, pointer-count=1
I/gestures( 2123): BaseListener: SWIPE_LEFT
I/gestures( 2123): FingerListener: 1 -> 0
SWIPE_RIGHT
スワイプの方向はScrollListenerでいえばdisposition (本記事のログでは*"disp")が正の場合がSWIPE_RIGHT*となるようです。なお、このリスナーは上下方向のスワイプでは呼び出されることがありません。
I/gestures( 2123): GenericMotionEvent: ACTION_DOWN, pointer-count=1
I/gestures( 2123): FingerListener: 0 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): ScrollListener: disp=636.0, delta=636.0, v=7.0749564
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): ScrollListener: disp=864.0, delta=228.0, v=12.20116
I/gestures( 2123): GenericMotionEvent: ACTION_UP, pointer-count=1
I/gestures( 2123): BaseListener: SWIPE_RIGHT
I/gestures( 2123): FingerListener: 1 -> 0
SWIPE_DOWN
次に上下方向のスワイプですが、こちらは非常にシンプルで、タップと同様のイベントシーケンスになります。ただし、SWIPE_DOWNは「Back」ボタンも兼ねていますので、最後にKeyDownイベントとKeyUpイベントが発生しています。
I/gestures( 2123): GenericMotionEvent: ACTION_DOWN, pointer-count=1
I/gestures( 2123): FingerListener: 0 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_UP, pointer-count=1
I/gestures( 2123): BaseListener: SWIPE_DOWN
I/gestures( 2123): FingerListener: 1 -> 0
I/gestures( 2123): KeyDown: KEYCODE_BACK, ACTION_DOWN
I/gestures( 2123): KeyUp: KEYCODE_BACK, ACTION_UP
SWIPE_UP
SWIPE_UPは非常にシンプルです。
ただし、実際に操作してみるとわかりますが、グラスフレームでの上方へのスワイプは、操作自体が非常に難しいです。この操作に意味を持たせるかどうかは慎重に検討したほうがいいでしょう。
I/gestures( 2123): GenericMotionEvent: ACTION_DOWN, pointer-count=1
I/gestures( 2123): FingerListener: 0 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_UP, pointer-count=1
I/gestures( 2123): BaseListener: SWIPE_UP
I/gestures( 2123): FingerListener: 1 -> 0
TWO_SWIPE_LEFT
スワイプは2本の指までをBaseListenerで処理することができます。左右方向の場合はTwoFingerScrollListenerで詳細な動きを検知することもできます。
I/gestures( 2123): GenericMotionEvent: ACTION_DOWN, pointer-count=1
I/gestures( 2123): FingerListener: 0 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_DOWN(0), pointer-count=2
I/gestures( 2123): FingerListener: 1 -> 2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): TwoFingerScrollListener: disp=-208.0, delta=-208.0, v=-5.836789
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_UP(0), pointer-count=2
I/gestures( 2123): FingerListener: 2 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_UP, pointer-count=1
I/gestures( 2123): BaseListener: TWO_SWIPE_LEFT
I/gestures( 2123): FingerListener: 1 -> 0
TWO_SWIPE_RIGHT
I/gestures( 2123): GenericMotionEvent: ACTION_DOWN, pointer-count=1
I/gestures( 2123): FingerListener: 0 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_DOWN(0), pointer-count=2
I/gestures( 2123): FingerListener: 1 -> 2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): TwoFingerScrollListener: disp=305.0, delta=305.0, v=5.515733
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): TwoFingerScrollListener: disp=486.5, delta=181.5, v=9.646457
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_UP(0), pointer-count=2
I/gestures( 2123): FingerListener: 2 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_UP, pointer-count=1
I/gestures( 2123): BaseListener: TWO_SWIPE_RIGHT
I/gestures( 2123): FingerListener: 1 -> 0
TWO_SWIPE_DOWN
2本の指での上下方向のスワイプについて、下方へのスワイプを何度か試しましたが、SWIPE_DOWNになってしまい、うまく検出されませんでした。本記事アップ後にもまた試してみて、うまくいけば記事を更新する予定です。
TWO_SWIPE_UP
2本の指による上方へのスワイプは、1本の指のときと同様、操作自体が難しいのですが、検出はうまくできました。
I/gestures( 2123): GenericMotionEvent: ACTION_DOWN, pointer-count=1
I/gestures( 2123): FingerListener: 0 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_DOWN(0), pointer-count=2
I/gestures( 2123): FingerListener: 1 -> 2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=2
I/gestures( 2123): GenericMotionEvent: ACTION_POINTER_UP(0), pointer-count=2
I/gestures( 2123): FingerListener: 2 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_UP, pointer-count=1
I/gestures( 2123): BaseListener: TWO_SWIPE_UP
I/gestures( 2123): FingerListener: 1 -> 0
その他の操作
4本の指によるタップ
4本の指によるタップを試みましたが、GenericMotionEventやFingerListenerでは3本の指しか検出されず、したがって、結果としてBaseListenerもTHREE_TAPとして処理されるようでした。
カメラボタン
カメラボタンをおすと、KEYCODE_CAMERAボタンのイベントが発生します。
I/gestures( 2123): KeyDown: KEYCODE_CAMERA, ACTION_DOWN
I/gestures( 2123): KeyUp: KEYCODE_CAMERA, ACTION_UP
Google glassを外す
Google glassの入力中(右フレームを長押ししている状態など)にグラスを外すと、ACTION_UPのかわりにACTION_CANCELのイベントが発生します。
I/gestures( 2123): GenericMotionEvent: ACTION_DOWN, pointer-count=1
I/gestures( 2123): FingerListener: 0 -> 1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
(中略)
I/gestures( 2123): GenericMotionEvent: ACTION_MOVE, pointer-count=1
I/gestures( 2123): GenericMotionEvent: ACTION_CANCEL, pointer-count=1
I/gestures( 2123): FingerListener: 1 -> 0
ウィンク
ウィンク(eye detection)は本記事で紹介している一連のしくみでは検出することができません。2014年7月(XE18)現在、アプリケーションがウィンクを検出する標準的な方法は提供されていません。GlassEyeGestureDemoサイトでは、非公開のcom.google.android.glass.eyeパッケージを使用してウィンクを検出する方法が紹介されていますので、ご参照ください。ただし、製品版では提供のされかたが変更される可能性があります。また、XE10以前の方法を紹介したサイトもありますが、現在は使用できません。
頭を起こす動作
頭を起こす動作(on-head gesture detection)についても、XE18では検出する機能が提供されていません。Head Gesture Detectorというgithubリポジトリには、ジャイロスコープセンサーを用いてこの動作を検出するリスナーを実現するコードが公開されているようです。
まとめ
Google GlassにはAndroid標準の操作のほかにさまざまなジェスチャがありますが、アプリケーションが自由に使えるものはまだ限定的です。また、ジェスチャのすべて実用的というわけでもありません。今後もGoogle Glassが正式版のプロダクトとなるまでに機能の追加、削除、変更が行われる可能性がありますので、デベロッパとしては継続的に注視しておく必要がありそうです。