Flutter で Google Glass Enterprise Edition 2 のアプリを作る際のメモ
Google Glass Enterprise Edition 2(以下「Glass」)の実機を入手したので、サンプルアプリをいろいろ作ってみている。 Android ネイティブで作ってもいいが、先日 Flutter 2 が出たところだし、せっかくなので Flutter で試してみている。 とりあえず、Tips がいくつかあったのでメモしておく。
アプリアイコンを Glass の Launcher に表示させる
Flutter のプロジェクト作成時の初期状態では、apk をビルドしてインストールしても、Glass のホーム画面である Launcher にはアイコンが表示されない。
アイコンを表示させるためには、Project/android/app/src/main/AndroidManifest.xml
に以下の記述を追加する。*1
<manifest ...> <application ...> <intent-filter> <!-- ここから --> <category android:name="com.google.android.glass.category.DIRECTORY" /> <!-- ここまで --> </intent-filter> </application> </manifest>
指での操作を Flutter 側で利用する
Glass にはタップ操作できる画面はないので、本体横の平面をタップやスワイプするのが標準操作となる。
Flutter では常に Android の MainActivity
それらの操作を Flutter 側でハンドリングするために、
1) Project/android/app/src/main/AndroidManifest.xml
に以下の記述を追加する
<manifest ...> <application ...> <!-- ここから --> <meta-data android:name="com.google.android.glass.TouchEnabledApplication" android:value="true" /> <!-- ここまで --> </application> </manifest>
2) ネイティブ側の MainActivity.java でネイティブの GestureDetector
を使ったハンドラを記述する。
package dev.nosu.flutter_slide_viewer.flutter_slide_viewer; import android.os.Handler; import android.os.Bundle; import android.view.MotionEvent; import android.view.GestureDetector; import io.flutter.Log; import io.flutter.embedding.android.FlutterActivity; public class MainActivity extends FlutterActivity implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener { private static final String DEBUG_TAG = "Gestures"; private GestureDetector mDetector; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mDetector = new GestureDetector(this,this); mDetector.setOnDoubleTapListener(this); } @Override public boolean onTouchEvent(MotionEvent event){ if (this.mDetector.onTouchEvent(event)) { return true; } return super.onTouchEvent(event); } @Override public boolean onDown(MotionEvent event) { Log.d(DEBUG_TAG,"onDown: " + event.toString()); return true; } @Override public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { Log.d(DEBUG_TAG, "onFling: " + event1.toString() + event2.toString()); return true; } @Override public void onLongPress(MotionEvent event) { Log.d(DEBUG_TAG, "onLongPress: " + event.toString()); } @Override public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX, float distanceY) { Log.d(DEBUG_TAG, "onScroll: " + event1.toString() + event2.toString()); return true; } @Override public void onShowPress(MotionEvent event) { Log.d(DEBUG_TAG, "onShowPress: " + event.toString()); } @Override public boolean onSingleTapUp(MotionEvent event) { Log.d(DEBUG_TAG, "onSingleTapUp: " + event.toString()); return true; } @Override public boolean onDoubleTap(MotionEvent event) { Log.d(DEBUG_TAG, "onDoubleTap: " + event.toString()); return true; } @Override public boolean onDoubleTapEvent(MotionEvent event) { Log.d(DEBUG_TAG, "onDoubleTapEvent: " + event.toString()); return true; } @Override public boolean onSingleTapConfirmed(MotionEvent event) { Log.d(DEBUG_TAG, "onSingleTapConfirmed: " + event.toString()); return true; } }
あとは、Flutter 側で GestureDetector
を使ってあげれば良い。
下向きのスワイプをアプリ終了に割り当てるには以下のようにする。(Glass では「戻る」または「アプリ終了」操作に割り当てるのが標準になっている)
class GestureContainer extends StatelessWidget { @override Widget build(BuildContext context) { return Container( child: GestureDetector( onVerticalDragEnd: (details) { print("onVerticalDragEnd primaryVelocity:" + details.primaryVelocity.toString()); if(details.primaryVelocity > 0) { SystemNavigator.pop(); } }, child: ChildWidget() ), ); } }
ほかにもいろいろポイントはありそうなので追って追記する予定。