ドレッドヘアのエンジニアが教えるAndroid Wear Watch Faceのつくりかた

tech.kayac.com Advent Calendar 2015 12日目担当の @ryusukefuda です。

今年はAndroid Wear Watch Faceをいくつか仕事でつくったのとドレッドヘアにしたので、 どちらも同時に紹介したいと思います。

Article.png

この記事を読んで欲しい人

  • 普段Android開発をやっているけど、Android Wearアプリはつくったことない人。
  • 普段パーマあててるけどドレッドヘアにはしたことない人。

まずはじめに

Watch Faceとは?

Android Wear(Androidの時計)では文字盤を好きに変更できます。
その文字盤のことをWatch Faceと呼び、開発者は好きに開発しGooglePlayで配布することができます。

ドレッドヘアとは?

人間は自分の髪型を好きに変更できます。
その髪型のひとつで、複数の髪の毛どうしが絡み合いロープのような束状になっています。

特徴を知りましょう

WatchFaceにできないこと

  • WatchFace単体でのHTTP通信 ※Android本体と接続し行います
  • タップ以外のインタラクション ※スワイプ、長押しはOSの機能につかわれる為

ドレッドヘアにできないこと

  • リンスー
  • 以前被っていた帽子を被る ※頭のサイズが2段階くらいあがります

よくある間違い

"iPhoneでつかえないじゃん。"

実は使えます。今年の9月にAndroid WearがiOS対応され、iPhoneの通知や着信をAndroid Wearで受けることができるようになりました。
Apple Watchを値段が高くて諦めていた方、Android Wearは安いものだと1万円台で買えるのでオススメです。

"髪型変えたんだー、すごいねそのコーンロウ。"

はい、違います。
コーンロウは三つ編みを頭に這わせてラインをつくっていく髪型でドレッドとは全く別の髪型です。
ダンサーの人が発表会などで気合をいれて数日だけやるのがコーンロウです。

完成までの時間

WatchFaceの学習コスト

普段Androidを開発している人であれば、開発からリリースまで1週間程でできます。
(アニメーションや機能を凝ると膨らみますが。)

ドレッドのコスト

ストレートな髪からドレッドになるまで10時間かかります。※3万円でした。

保守性

端末対応

タグホイヤーが16万5000円のAndroid Wearを発売したり各メーカーが様々なものを出していますが今のところ円形と四角形のみ(Moto360だけ円形で下が少し切れていますが)なのでAndroid開発で悩ましい端末対応もさほど考えなくて大丈夫です。 今後不思議な形をしたAndroid Wearが発売されたらそれにあわせてアップデートする必要があるかもしれませんね。

メンテナンス

ドレッドヘアは月に1回3時間程かけて根本と全体のメンテナンスをします。
一見雑そうに見えるドレッドの人ですが、綺麗に保っている人は実はマメな人です。

コードのお話

すべてはCanvas

Androidではレイアウトはxmlに記述しViewにButtonやImageViewなど配置しデザインを組んでいきますが、
WatchFaceはViewはひとつで、すべてそのViewにCanvasでゴリゴリかきます。

@Override
public void onDraw(Canvas canvas, Rect bounds) {
  //ここが毎フレーム呼ばれるのですべてここで描画
}

設定したタイミングで毎回このonDrawが呼ばれるので、そこで、針の動きや時計の表示文字等をセットします。
すべての描画はonDrawにかきます。

アンビエントモード

アンビエントモードはスリープモードの様なもので一定時間何もしないと自動的にアンビエントモードになります。

@Override
public void onAmbientModeChanged(boolean inAmbientMode) {
   super.onAmbientModeChanged(inAmbientMode);
     if (mAmbient != inAmbientMode) {
        mAmbient = inAmbientMode;
        if (mLowBitAmbient) {
            mHandPaint.setAntiAlias(!inAmbientMode);
        }
        invalidate();
    }
    updateTimer();
}

メンバ変数で状態を管理し、 これまたonDraw()のなかで分岐をつくり処理をかきます。
※ ちなみにアンビエントモードはメモリ消費を抑える為、白、黒、グレイのみを使用することがGoogleのポリシーで推奨されています。

タップ検知

@Override
 public void onCreate(SurfaceHolder holder) {
     super.onCreate(holder);

     setWatchFaceStyle(new WatchFaceStyle.Builder(WatchFace.this)
              .setCardPeekMode(WatchFaceStyle.PEEK_MODE_SHORT)
              .setBackgroundVisibility(WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE)
              .setShowSystemUiTime(false)
              .setAcceptsTapEvents(true) //タップイベントを使えるように1行追加
              .build());

~~~~~~~~~~~~~~~~~~~~~~~~~

@Override
public void onTapCommand(int tapType, int x, int y, long eventTime) {
      super.onTapCommand(tapType, x, y, eventTime);
      mTapX = x;
      mTapY = y;
      mIsTap = true;
      invalidate();
}

今年の夏にandroid wearのAPIが追加で公開され、インタラクションが少しですが可能になりました。
Overrideメソッドがあり、Watch Face上の座標が返ってきます。
この座標を使ってタップした場所に文字や画像を浮かび上がらせたりとアイディアが広がりますね。
invalidate();onDraw()を呼びます。

ステータスバー, OK Google の位置指定

Android WearのOS側が出している電池残量や"OK Google" の表示を消すことはできないですが位置を指定することは可能です。

@Override
 public void onCreate(SurfaceHolder holder) {
     super.onCreate(holder);

     setWatchFaceStyle(new WatchFaceStyle.Builder(WatchFace.this)
              .setCardPeekMode(WatchFaceStyle.PEEK_MODE_SHORT)
              .setBackgroundVisibility(WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE)
              .setShowSystemUiTime(false)
              .setAcceptsTapEvents(true)
              .setHotwordIndicatorGravity(Gravity.BOTTOM | Gravity.CENTER) // "OK Google"の位置
              .setStatusBarGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL) // ステータスアイコンの位置
              .build());

デザインの邪魔にならない場所に配置しましょう。

アニメーション

アニメーションをさせたい場合はcanvasでかくか、
コマアニメーションさせる画像を一枚一枚用意し対応する方法があります。
Viewを分けることができないので、複数の場所で別々なアニメーションをさせようとすると結構大変です。

事例紹介

参考資料

おわりに

いかがでしたか? Watch Faceとドレッドを同時に知ることができましたね。
社会人になってドレッドを諦めている方、カヤックでは自由な髪型で働くことができます。
是非カヤックで一緒に働きましょう。

明日は最近VJもやる演出イケメン@seiya_vwさんがおしゃれな記事を書いてくれます。