(この記事は ChatWork Advent Calendar 2014 の10日目として提供いたします)
皆さん、こんにちは。
アプリケーション開発部の宮下と申します。
本日、 2014/12/10 に新しい Android 用の ChatWork アプリを公開しました
今年4月に Android アプリのリニューアルを行ったのは弊社のブログでお知らせしていたとおりですが、再び Android アプリをリニューアルする運びとなりました。今回はその裏話と技術的なお話をしたいと思います。
思いの丈を一通り綴ったので長文となっていますが、お付き合いよろしくお願いします
Project “Harukas”
4月に公開したバージョン 2.0 は、社内では “Harukas (ハルカス) ” というコードネームが付けられていました。大阪にある超高層ビルが由来ですね。
“Harukas” は先だって公開していた iOS アプリのコードを流用して作られたもので、これを実現可能にしたのは Appcelerator Titanium™ によるものでした。
Titanium™ は、 JavaScript ベースでネイティブな UI を持つアプリを作ることができる開発環境です。 HTTP クライアントやデータベースなどの UI が絡まないレイヤーや、ビジネスロジック部分を iOS / Android でコードを共通化することができ、 UI は提供するプラットフォームに合わせて書き分けるという開発スタイルを取ることができます。
この技術を使うことによって、少人数で開発が始まった ChatWork も、初期の頃から Web とアプリの2つの側面からサービスを提供することができました。
このまま Titanium™ で開発を進めるべきか
“Harukas” のリリース後、振り返りを行ってみると課題が見えてきました。
- Titanium™ の Android API は UI に制約が多い
- 最新の Android OS への対応が遅れがち
- コード、機種、 Titanium™ のどこに問題があるのかが追いづらい
などです。特に UI に関しては当初思い描いていた形から変えざるを得ない部分が多く、制約を強く感じたところでした (これに関しては次期 Titanium で、アーキテクチャが一新される Ti.Next で大きく改善されるのではないかと、個人的に期待しているところです) 。
また、4月にアプリをリリースしましたので、1〜2ヶ月後には Google I/O があり、そこで新しい Android OS が発表されるであろうことはすでに噂されていましたし、新 OS への対応への懸念や、 iOS のネイティブアプリ開発がスタートしている中、 Android もこのまま Titanium™ で開発を進めるべきかという考えが生まれていました。
Project “The Shard”
東京オフィスの移転の後、エンジニア面談の場が設けられたのですが、上述の課題を踏まえた上で、「Android アプリもネイティブ化しましょう!」という提案を行い、始まったのが “The Shard (ザ・シャード) ” プロジェクトです (ロンドンにある超高層ビルが由来) 。
プロジェクトチャット用に作ったアイコン
Better “Harukas”
先だって開発が始まっている iOS ネイティブアプリでは、サーバサイド API も Scala で書き直されたものが使われる予定で、アプリだけでなく、サーバサイドも含めて、何もかもを一新する大プロジェクトとなっています。
しかし、 “The Shard” では既存のインフラを使いつつ、クライアント側でできる限りのパフォーマンスアップを行うことを目的としました。これは、
- Scala 版の新 API を今後 Android でも使うための下地作り
- できるだけ早くアプリを提供する
を見込んだものです。機能セットも “Harukas” でできること + α にとどめて、まずはアプリを1つ完成させるために動き出しました。
開発をはじめて
いざネイティブ版の開発を初めてみると、意外とすんなりスタートすることができました。というのも、 Titanium™ で開発しているときの知識によって「こういう API があるはずだ」「こういうモジュールを書いたから、ああいうことができるはずだ」といったアタリが付けられたからです。
Titanium™ でプロトタイプを作ってリリースし、検証を繰り返しながらネイティブに移行していくパスはアリだなとあらためて思いました。 Titanium™ SDK は GitHub でコードが公開されているので、 Titanium™ の API からさかのぼって行って、 Android 側の API では何が使われているのかの手がかりにしました。
実機で開発
開発中はとにかく実機を使っていました。 Android エミュレータは遅いですし、 Genymotion は高速すぎる (IO とか) ので、実機です。 Nexus 5 (Android 4.4.4 と 5.0 の2台) を開発機に据えて、最下限は Galaxy S2 (Android 4.0.4) 、最上位では Galaxy Note Edge (Android 4.4.4) などの端末で確認しています。
また、地味に役立ったのは Nexus 4 でした。 Nexus 4 は LTE に対応していないこともあり、 SIM を入れて動かすと 3G でのみ動作します。なので、恒久的な非 LTE 環境下を作り出す際には Nexus 4 が役立ちました。また、意図的に回線速度を 200kbps のモードに切り替えて、低速時の確認をしながら開発を進めました。
UI に関してもモックアップから実機に落としてみると、モックアップ上では大きいかなぁ……?という感想を持っていたところも、ぴたりと使いやすいサイズだったりしました。なので、これから Android アプリの開発を始める方には実機を1台用意されることをオススメします。
開発フロー
開発は GitHub 上で、 GitHub Flow を変形させたような形で行いました。
- 検証を行う際 :
investigate-
- 実装を行う際 :
implement-
- バグを修正する際 :
fix-
のようにある程度統一したルールでブランチを切り、 Work In Progress 形式の Pull Request を送って、タスクを消化していく形です。
タスクが消化されたものから master
ブランチにマージします。レビューやペアプロの際には ChatWork Live の画面共有機能を活用しました。
検証フロー
検証の際は DeployGate を活用しました。 DeployGate SDK の組み込みは非常に簡単でしたし、配布からログ収集まで一括して管理することができます。基本的には、1日の終わりに master
ブランチの内容をビルドして DeployGate で配布するという形を取っていました。
配布後は専用の検証チャットの上で配布報告と簡単なリリースノートを出し、チャット上でフィードバックをもらっていました。そのフィードバックを元にして GitHub Issues に登録し、また開発を進めるというサイクルで開発と検証を行っています。
また、一斉テストの際には Google SpreadSheet も活用しました。リアルタイムに複数人が同時更新できるので、多重に報告される問題とそうでない問題の切り分けに役立ちました。
大変だったこと
開発を始めたのは実質的に5月のゴールデンウィーク明けだったのですが、 Google I/O で Material Design が発表され、その後10月後半には AppCompat v21 ライブラリが登場したことで、 Android 4.4 以下にも Material Design のアプリが提供できるようになりました。
このライブラリがあるのに、リリースされるアプリが Holo のままで本当に良いのか、リリース後に Material Design 化するよりも先にベーステーマだけでも置き換えた方が良いんじゃないか……などなど考えた結果、リリース版から AppCompact v21 を使うことに決めました。
単純にテーマを置き換えただけでも印象は変わりましたが、やはり不格好に見える場所もあったため、 Material Design のガイドラインの一部を取り入れていきました。まだレイヤーの考えなどはまだ取り込めていないですし、今後のアップデートで改善していきたいところの1つになっています。
技術的なお話
開発環境
Android Studio
“The Shard” の開発では ADT は使わず、はじめから Android Studio で開発を行っています。開発当初は Canary チャンネルしかありませんでしたが、 Google I/O 2014 で Beta チャンネルが公開されたことで、基本的には Beta チャンネルで運用していま …… した。
この原稿を書いている時点では Canary チャンネル に Release Candidate が来ていたのですが、 Beta Channel にも RC4 が来て、そして、 “The Shard” を公開しようというまさに前日、 1.0 が登場しました。今後は ADT ではなく、 Android Studio が正式な開発プラットフォームになるのでしょう。
ライブラリ
“The Shard” 開発では多くの OSS ライブラリに助けられています。ここでは使用しているライブラリの一部を紹介します。
ActiveAndroid
ActiveAndroid は Android 用の ORM で、 Active Record パターンを採用しています。 Sprinkles や greenDAO などの使用も考えましたが、使い勝手や導入事例、 API のシンプルさを優先して ActiveAndroid を選択しました。ただ、既存のサーバサイド API との相性があまり良くない部分があることも開発中に判明しており、特に INSERT
処理が遅いため、一部で Realm を採用しています。
Realm
Realm は SQLite と Core Data の置き換えを目的とした iOS / Android 向けのデータベースライブラリです。 SQLite よりも高速に読み書きができ、今回の “The Shard” では一部を ActiveAndroid から Realm に置き換えた結果、書き込みのパフォーマンスが 5x 〜 10x 高速になりました。
API はシンプルなものが揃っているのですが、データオブジェクトの管理法に若干の癖があります。 Realm に関しては今後、個別の記事にしたいと考えています。
OKHttp
OkHttp は決済サービスを提供する Square 社が OSS として公開している HTTP クライアントライブラリです。 “The Shard” 開発当初は Volley を使っていたのですが、いくつかの場面で Volley だと融通が効かず、対応が難しい部分が出てきてしまったため、 OkHttp に切り替えました。
私個人の Qiita で雑感を書いていますが、 HTTP を良い感じに抽象化して使うことができるところが気に入っています。
Picasso
Picasso は OkHttp と同じく、 Square 社が公開している画像のダウンロードとキャッシュ管理、 ImageView
への反映などを管理してくれるライブラリです。 iOS でいうところの SDWebImage に近いものでしょうか。 Volley を使っていたときは、 セットされている NetWorkImageView
や ImageLoader
を使っていましたが、 OkHttp への乗り換えの際に Picasso に切り替えました。
Transform
を使うことで、角丸化や円形のくり抜きもできます。ただ、 GIF を読み込ませるとクラッシュする点に悩まされました (現在進行中) 。
Butter Knife
Butter Knife は OkHttp と同じく、 Square 社の中の人の1人である Jake Wharton 氏 (神) が開発しているインジェクション用ライブラリです。普通、 Android で XML 側に書いたウィジェットと Java を紐付けるには、
のように、 findViewById
メソッドを使って ID 参照した後、キャストを行わなければなりませんが、 Butter Knife ならば、
としておけば自動的にインジェクションされます。大変便利です。ただし、 @InjectView
を付ける変数は private
ではダメなので、既存のコードを置き換えるときは注意が必要です。 @OnClick
などの便利なアノテーションも用意されているので、ビューに関することに集中した、小さくて素敵なライブラリです。
EventBus
EventBus は greenDAO を作る greenrobot 製のライブラリです。 Android に最適化された形のイベントの Pub/Sub 機構を導入することができます。
“The Shard” では様々な場面で EventBus を駆使しています。例えば認証時の成否や、更新を受け取った後に JSON を処理して、その結果を Activity や Fragment に通知したりしています。高速に動作しますし、 interface を駆使した複雑なコールバック機構を意識しなくても開発できるのは心強いです。
おわりに
まずは無事に “The Shard” をリリースできたことにホッとしています (この文章を書いている時点では、まだ公開されていないのですが、ホッとしていることでしょう) 。しかし、先に書いたとおり、 Scala 版の新 API を今後 Android でも使うための下地作り でもあり、 Java ネイティブ版としてのスタート地点から走り始めたばかりのバージョンです。
いくつも手を入れていきたいところがあります。そして改善を進めていきたいと思っています。こうだったらいいなというご要望は、ChatWork ご意見・ご要望フォーラムに送信していただければ幸いです。
また、 iOS ネイティブ版も現在鋭意開発中です! そして、 iOS / Android アプリの開発に携わりたいエンジニアも大募集中! iOS アプリでは ReactiveCocoa を使った Reactive Programming を実践中ですよ。