Google glassでタッチジェスチャ操作時に生起するイベント

##Google glassにおける操作の検出

Google glassは、右フレームを指でなぞったりカメラボタンを押すことによって、androidのタッチパッドに相当する操作を行うことができます。おおまかな操作方法はgoogle glassの[サポートページ](https://support.google.com/glass/answer/3064184)に記載されています。

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の[ドキュメント](http://developer.android.com/reference/android/view/KeyEvent.html)を参照してください。
* **MotionEvent**。通常のandroidではマウス、ペン、指、トラックパッドなどの操作に相当するイベントです。Google glassでは右フレームをトラックパッドのように使用します。*ACTION_DOWN*、*ACTION_MOVE*、*ACTION_UP*などにより、複数の指の動きを検出し処理することができます。ゲームなどで指の細かい動きを処理する場合は、*MotionEvent*のイベントを利用します。詳細はandroidの[ドキュメント](http://developer.android.com/reference/android/view/MotionEvent.html)を参照してください。
* **GestureDetector**。*GestureDetector*はGlass Development Kit (GDK)が用意している高次のリスナーです。複数の*KeyEvent*や*MotionEvent*をまとめて、タップ、スワイプ、スクロールなど標準的な操作(タッチジェスチャ)
のListenerを用意しているので、タッチジェスチャに対する処理を容易に実装することができます。詳細はGDKの[ドキュメント](https://developers.google.com/glass/develop/gdk/reference/com/google/android/glass/touchpad/GestureDetector)を参照してください。

##タッチジェスチャの種類

*GestureDetector*が用意している標準的なタッチジェスチャには以下のものがあります。これらは、[com.google.android.glass.touchpad.Gesture](https://developers.google.com/glass/develop/gdk/reference/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](https://github.com/blackaplysia/gestures)に置いてあります。

###TAP

タップは*BaseListener*で*TAP*ジェスチャを検出します。また、*KEYCODE_DPAD_CENTER*ボタンの*ACTION_DOWN*および*ACTION_UP*という2種類のイベントも事後に発生しています。*GenericMotionEvent*と*FingerListener*は途中の詳細な指の動きを捕捉しています。

```text
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*イベントは、細かい指の動き捕捉しているものです。

```text
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*がすべての指が離れたことを検出したときに、それまでもっとも多く検出した指の数から結果を導いているようです。

```text
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*の後)に生起するのではなく、一定時間継続して押されると指を離さなくても生起するようです。

```text
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*が生起します。

```text
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*が生起します。

```text
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*で指の動きの詳細(場所、移動距離、速度等)を把握することができます。

```text
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*となるようです。なお、このリスナーは上下方向のスワイプでは呼び出されることがありません。

```text
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*イベントが発生しています。

```text
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*は非常にシンプルです。
ただし、実際に操作してみるとわかりますが、グラスフレームでの上方へのスワイプは、操作自体が非常に難しいです。この操作に意味を持たせるかどうかは慎重に検討したほうがいいでしょう。

```text
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*で詳細な動きを検知することもできます。

```text
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

```text
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本の指のときと同様、操作自体が難しいのですが、検出はうまくできました。

```text
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*ボタンのイベントが発生します。

```text
I/gestures( 2123): KeyDown: KEYCODE_CAMERA, ACTION_DOWN
I/gestures( 2123): KeyUp: KEYCODE_CAMERA, ACTION_UP
```

###Google glassを外す

Google glassの入力中(右フレームを長押ししている状態など)にグラスを外すと、*ACTION_UP*のかわりに*ACTION_CANCEL*のイベントが発生します。

```text
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サイト](https://github.com/thorikawa/EyeGestureLib)では、非公開の*com.google.android.glass.eyeパッケージ*を使用してウィンクを検出する方法が紹介されていますので、ご参照ください。ただし、製品版では提供のされかたが変更される可能性があります。また、[XE10以前の方法](https://github.com/kaze0/winky)を紹介したサイトもありますが、現在は使用できません。

###頭を起こす動作

頭を起こす動作(on-head gesture detection)についても、XE18では検出する機能が提供されていません。[Head Gesture Detectorというgithubリポジトリ](https://github.com/thorikawa/glass-head-gesture-detector)には、ジャイロスコープセンサーを用いてこの動作を検出するリスナーを実現するコードが公開されているようです。

##まとめ

Google GlassにはAndroid標準の操作のほかにさまざまなジェスチャがありますが、アプリケーションが自由に使えるものはまだ限定的です。また、ジェスチャのすべて実用的というわけでもありません。今後もGoogle Glassが正式版のプロダクトとなるまでに機能の追加、削除、変更が行われる可能性がありますので、デベロッパとしては継続的に注視しておく必要がありそうです。