Google I/O 2017 に行ってきました


はじめに

みなさま、こんにちは。株式会社はてなの id:funnelbit です。はてなでは Android アプリ、また最近では iOS アプリの開発に携わっています。

さて、Google は毎年5月に Google I/O という開発者向けイベントを開催しています。今年も現地時刻で5月17日から開催されました。Google I/O は抽選でチケットが決まる仕組みで、僕はこれまで当選することはなかったのですが、この度運良く Google I/O 2017 に行く事ができ、現地で発表と空気感を味わってきましたので、(少し前の話題になりますが)その一部を共有したいと思います。

今回の Google I/O では去年に引き続き機械学習を軸にした機能を押してきており、さらに AI にシフトしていくと強く明言。もはや「どのプラットフォームでソフトウェアを作る」かはさほど重要ではなく、いかなる環境においても、Google が作り出した AI の恩恵を与えていく、ということです。これは凄まじい強みでしょう。もはや時代の流れでハードがどうなろうがあまり関係ないのです。

Google Assistant は様々なデバイスで使えるものとし、iOS でも利用可能になるとされました。デモではほぼ音声のみで買い物をやってのける様を披露しました。また Google Home が Google Assistant と絡めてプッシュされ、しっかりとした骨格を持ったデバイスになった印象です。Google Assistant は 日本語にも対応することがアナウンスされ、すでにアップデートの配信が始まっています。

assistant.google.com

写真アプリでは機械学習の力で、賢い写真のシェアを実現。例えば写真に自分と恋人が映っていた場合、恋人にもシェアすべきではとレコメンドされたり、自動的にシェアする機能までもが追加されます。また機械学習とは関係ないですが、写真を実物のアルバムにできるサービスも発表されました。

https://photos.google.com/photobooks


機械学習の成果を最も派手に体感できるアプリ Google Lens も発表されました。スマートフォンのカメラを対象に向けることで、然るべき処理を行うというものです。何の店なのか、何の植物なのかが分かったり、wifiに接続したり、文章を翻訳したり、色んな事ができるようです。提供されるのはまだ先ですが、楽しみなアプリです。

ところで、僕は Android アプリを担当するエンジニアですので、基本的には Android セッションを中心に会場を回っていました。ここでは Android 系セッションから得た面白い情報をざっと共有したいと思います。殆どがドキュメント化されてますので、詳細はリンク先を見てください。

Android Oについて

  • ピクチャ イン ピクチャ。Activity を小さな画面にして前面に起動し続けることができます。その間他のアプリを開くこともできます。O では前回の OS(N。Android TV のみで使えました) とは少し実装方法が異なります https://developer.android.com/preview/api-overview.html?hl=ja#opip
  • カラーマネジメントするようになりより正確な色表現が可能になるようです。ColorSpace, Half などの便利クラスや @ColorLong アノテーションが追加されます。 https://developer.android.com/preview/api-overview.html?hl=ja#cm
  • なんとマルチ「ディスプレイ」が可能になります。スマートフォンとは全く別のディスプレイに Activity を表示できるわけです。Activity が移動した時は自動的にリサイズ処理が走ります。その際のデバッグ方法も用意されています。adb shell dumpsys displayadb shell start --display ですhttps://developer.android.com/preview/api-overview.html?hl=ja#mds
  • メディア機能が強化され、幾つかの API が生えています。https://developer.android.com/preview/api-overview.html?hl=ja#media
  • WebView に便利な API が数種類追加されました。目を引くのは Google Safe Browsing API。Google は絶えず安全でないサイトの URL を蓄積しているようで、その資産を使ってアンセーフなサイトにユーザがアクセスしようとした場合、警告を出すようになります。実装はほんの少しの xml コードを書くだけです。 https://developer.android.com/preview/features/managing-webview.html?hl=ja#renderer-importance
  • AnimatorSet に新しい機能が追加されました。アニメーションを逆再生できます。とある UI の操作をアニメーション付きで行い、また元に戻す UI 操作をした時の表現に便利としています。 https://developer.android.com/preview/api-overview.html?hl=ja#aset
  • AutoFill。特定のフォームに埋め込む値を提供します。例えば ID と Password を入れるフォームがある場合、そこに予め用意しておいた値を入れることができるというものです。これは I/O に行く前にすでに個人で試していました。iOS でも Safari でログイン用フォームに対してキーチェーンから簡単に入れることができる機能がありますが、AutoFill の場合「利用者が AutoFill するアプリを選択することができる」という点で大きく異なります。また Fill する対象はなんでも良く、AutoFill アプリの実装次第です。https://developer.android.com/preview/features/autofill.html?hl=ja
  • xml フォント機能。R.font.fonname という形式でフォントを利用できるようになります。これまでシステムフォントではないフォントを適用したければ、TextView クラスを継承して、自力でフォントファイルをセットする必要がありました。しかしながら今回の変更により、TextView にフォントを適用したい場合は xml で fontfamilies を作り、レイアウトで利用する場合は android:fontFamily="@font/myfont" と書くだけで済みます。注目すべきは Downloadable Fonts。フォントがアプリケーションにない場合に外部から取ってくる仕組みです。サポートライブラリが存在します。 https://developer.android.com/preview/api-overview.html?hl=ja#wwf
  • テキストサイズの自動化。簡単な設定を書くだけで、TextView のサイズに応じた文字サイズが設定されます。サポートライブラリが存在します。 https://developer.android.com/preview/features/autosizing-textview.html?hl=ja
  • アクセシビリティ。かなりたくさんの機能追加があります。 https://developer.android.com/preview/api-overview.html?hl=ja#a11y
  • findViewById() について。これまではキャストする必要がありましたが必要なくなります。
  • アダプティブアイコン。例えばランチャによってアイコン形状には差異が出る(四角っぽかったり、丸だったり)ものなのですが、その差異を何とかする機能です。 https://developer.android.com/preview/features/adaptive-icons.html?hl=ja
  • アプリのショートカットについて。requestPinShortcut(...) を使えば、アプリ内でホーム画面にアプリのショートカットを置けます。requestPinAppWidget(...) を使えば、アプリ内でホーム画面にウィジェットを置けます。 アクションそのものをショートカットとしておけると言うのは、iOS にはない強みであるといえます。 https://developer.android.com/preview/features/pinning-shortcuts-widgets.html?hl=ja
  • 通知について。大幅な変更が行われています。今回の変更により、通知にはチャンネルを割り当てる必要があります。「とても重要な通知チャンネル」「そこまで重要ではないチャンネル」といった具合です(実際はもっと明確な目的をもったチャンネルわけになるでしょう)。チャンネルは、ユーザが通知を取捨選択するのに利用されます。不必要なものはブロックする、といったことが可能になります。もっともこれまでも自力でそのような仕組みは作れたのですが、OS 側でその仕組が用意された、ということです。 https://developer.android.com/preview/api-overview.html?hl=ja#notifications
  • StrictMode Detector という、アプリ内に何か問題がないかを調べる手段が用意されました。とても簡単に利用することができます。 https://developer.android.com/preview/api-overview.html?hl=ja#strictmode
  • メディアファイルへのアクセスで、シークできるファイルディスクリプタ作成できるようになり、リモートから大きなデータソースを引っ張ってくるというシチュエーションで便利に使えるようになります。この機能を使いたい場合、openProxyFileDescriptor(...) を利用します。 https://developer.android.com/preview/api-overview.html?hl=ja#imfa
  • キャッシュ専用のディスクスペースがアプリごとに割り当てられるようになりました。それに伴い、キャッシュ用の新しい API が生えています。 https://developer.android.com/preview/api-overview.html?hl=ja#cache
  • java の API 追加。java.time, java.nio.file, java.lang.invoke
  • サポートライブラリの version 26 登場。Fonts in XML, Downloadable Fonts, Auto-Sizing TextView、さらに EmojiCompat がバックポートされます!下で詳しく書いてます。
  • 物理学を元にしたアニメーション。これは面白いです。DynamicAnimation で少し詳しく書いています。 https://developer.android.com/preview/features/physics-based-animation.html

DynamicAnimation

これは面白かったので少し深掘りを。発表は以下の URL です。

events.google.com

  • 物理的なアニメーションについてです。FlingAnimation。例えば左右に動くリストで、指を左右に シャッ とした時のアニメーションです。実装するには、Gesture を検知したとき(GestureDetector の リスナ内。onFiling(){})で FlingAnimation インスタンスを作成。幾つかのセッタを読んだ後、start() メソッドが生えているのでそれでアニメーションします。またこのクラスには friction という概念があります。friction は不一致とかいう意味がありますが、ここでは物理的なアニメーションの話なので摩擦力のことです。これを設定すると、例えばシャッとアニメーションした後にリストが慣性である程度動いて、止まりますが、それがどれ位で止まるのかを設定することができます。 https://developer.android.com/preview/features/fling-animation.html
  • バネのような挙動をするアニメーション SpringAnimation。幾つかのオプションがあります。ダンパーの値を入力すれば、跳ねる具合をコントロールできます。これは定数でいくつか用意されています。例えば DAMPING_RATIO_NO_BOUNCY を使えばバウンドしなくなります。また stiffness というのもあります。これはバネの硬さの概念です。バネそのものが硬くなるので、例えばバネを引っ張って話した時、どれぐらいのスピードでバネが「もとに戻ろうとするか」が設定されるようです。またダンバーの挙動にも影響します。柔らかければよくはねますし、硬ければ全然はねません。また SpringAnimation は直線のバネ的挙動のみならず、回転するような挙動にも対応しています。コンストラクタで ROTATIONDynamicAnimation を指定すれば実現できます。FlingAnimation と組み合わせれば、リストのスクロールが終わったときにポヨンとはねて限界を示すようなアニメーションも作成できます(Spring Back)。更に応用技として、複数の SpringAnimation をチェインしてアニメーションする技も披露しています。 https://developer.android.com/preview/features/spring-animation.html

DynamicAnimation を利用すれば、UX に大きな変革をもたらすことができます。ユーザはより現実的なものとして、画面の中の UI を理解することができるようになることでしょう。思えば iOS にも似たようなアニメーションを見ることができますね。例えば通知センターを勢い良く開いたときのバウンドなど。

TextView 系

今回は Text 系がかなり充実していたなという印象です。サポートライブラリでバックポートされるため、多くのプロダクトで利用可能な機能になると思います。

  • xml フォント機能。R.font.myfont と言った具合に font を扱えるようになります。使い方としては、リソースディレクトリに font ディレクトリを作り、そこに .ttf ファイルを入れていきます。次にフォントにはイタリックとか太文字とかあるので、それをまとめる fontFamily と呼ばれる xml を作ります。最後に TextViewandroid:fontFamily="@font/fontFamily" と書けば適用されるという仕組みです。
  • コードからフォントが欲しい場合でも、ResourceCompatgetFont() が生えているので、それを使えば良いようになっています。
  • DownloadableFont。 これはすごい仕組みで、Font を外部から取ってくるという技です。つまり Font を必ずしもバンドルしなくても良いわけです。どうやって Font をとってくるかというと, FontProvider っていう役を担う外部の Provider がいて、そいつに Font を問い合わせ、そこ経由で取得する、という仕組みです。この Provider は PlayServices が実装しており、800を超える Font のプロバイダとなっています(Google Fonts team とか言うのがいるらしい)。FontProvider は直接呼ぶのではなく、FontsContractCompat っていうクラスがいて、そいつのメソッドを叩くことで呼ばれていくという形です。ここに詳細があります

developer.android.com

  • EmojiCompat 。これはサポートライブラリに入ってます。これもすごくて、絵文字が端末にない場合で、それの表示を試みた場合、四角の中に罰がつく記号になってしまう問題を何とかします(Google の人はこれを豆腐と読んでいるらしい)。もしも絵文字がある場合、そのまま表示。もしもない場合は突如 EmojiSpan というものになって表示されます。利用方法は2つあって、font を download して解決するか、bundled か。前者の場合は FontRequestFontProvider を指定することになります。後者の場合、compile "com.android.support:support-emoji-bundled:$version" としておき、EmojiCompat.Config config = new BundledEmojiCompatConfig(this); することで動作します。 https://developer.android.com/preview/features/emoji-compat.html
  • Autosizing TextViews 。例えばスマートフォンでは丁度いいテキストサイズでも、ChromeBook になった瞬間に小さくなりすぎる、という問題があると思います。Autosizing TextViews はそれを解決する手段です。基本的には普通の TextView のようですが、表示エリアが大きくなれば、表示しているテキストも大きくなります(普通はテキストサイズはそのままで、エリアだけ大きくなる)。開発者は特別な TextView を使う必要はなく、TextViewandroid:autoSizeTextType="uniform" とするだけです。 https://developer.android.com/preview/features/autosizing-textview.html

PreferenceDataStore

面白くて有用なやつで、Preference の保存についてをカスタマイズできます。例えば Bool 値をクラウドに保存。get() で結果を返すのはキャッシュ、など。PreferenceDataStore を継承して実装し、そのインスタンスを PreferenceManager にセットすることで有効になります。
https://developer.android.com/reference/android/preference/PreferenceDataStore.html

Kotlin

Kotlin はこれまでも利用することができましたが、公式の言語ではないという懸念がありました。しかしながら今回、ついに一級の利用可能言語として Google が発表しました。Java をやめるわけではありませんが、Kotlin を使うことについて、Google が推奨することになったのです。これによって、これまで Kotlin を使うべきかどうか悩んでいた開発者は Kotlin を選ぶ上での大きな後押しを得たことになります。この選択は Google が自前コンパイラの開発を結局やめたという事実もあり、今後多くの開発者が Kotlin を利用していくことになると思います。 https://developer.android.com/studio/preview/features/index.html#kotlin_language

Android Architecture Components

これまで Google は下位互換性及び Google プロダクトの API(Map、Ads、Firebase 等) 利用のためのライブラリを提供することはあったとしても、アーキテクチャに関わる部分のライブラリの提供というものはありませんでした。それが今回、提供されたのです。これは非常に興味深いライブラリです。 https://developer.android.com/topic/libraries/architecture/index.html

まだ開発版ですが、正式版リリースがリリースされた暁には大いに導入を検討すべきライブラリです。僕が関わっているチームは偶然にも、すでにアプリがこのライブラリを組み込んだような構成になっていますが、正式版リリース後にはこのライブラリに移行することも検討しています。

LiveData

  • 値の購読を可能にするクラスを生成できます。RxJava で言うと BehaviorSubject が近いです。しかしライフサイクルを考慮するという点でより利便性があります。

https://developer.android.com/topic/libraries/architecture/livedata.html

ViewModel

  • ライフサイクルとはまた別の scope で管理される ViewModel が提供されます。これによって configuration change(画面を回転する、フォント設定を変更する、ハードウェアキーボードを繋ぐ... など)に対処することもできるようになります。多くの場合、LiveData を併用して利用することになるでしょう。注意点としては長期間 Activity を離れて、また戻ってきた時はシステムによって破棄されているので、状態を保存しておく savedInstanceState は不要にはならない、ということです。これを簡単に再現するには、開発者オプションで「アクティビティを保持しない」にチェックを入れて、Activity を一旦バックグラウンド状態にした後、復元し、ViewModel インスタンスの状態を確認すると良いでしょう。

個人的には ActivityFragment、あるいは Fragment 間でのやり取りがとても簡単になるという点に魅力を感じます。

developer.android.com

LifecycleObserver and LifecycleOwner

これまではライフサイクルごとに何か処理を行う場合、自力で行う必要がありました。例えばライフサイクルを提供するための親クラスを用意したり、RxLifecycle を導入したりなどです。今回の LifecycleObserverLifecycleOwner の提供によって、そのような仕組みを自力で用意する必要がなくなります。@OnLifecycleEvent でライフサイクルイベントを指定する方式(ビルド時にコード生成されます)のため、メソッド名に自由があります。

developer.android.com

Room

これまで Google は Android においての永続化については、Android OS に組み込まれている SQLite と簡易的なクラスの提供にとどまっていましたが、今回、突如として永続化ライブラリ Room が発表されました。データベースの row を表す @Entity アノテーションを付与したクラスを定義し、@Dao アノテーションを付けたクラスに SQL を書き、@Database アノテーションを付けたクラスにデータベース情報を記述します。SQL 文はコンパイル時にチェックがなされます。また RxJava2 の PublisherFlowable を返すことも出来るため、リアクティブなコードも容易に書くことができます。

developer.android.com

これによって「Android の永続化ライブラリは何を選ぶべきなのか」という問題に対し、一つの解が与えられたことになります。もちろん、世の中にはすでに様々な良い永続化ライブラリが存在しますが、公式からこのようなライブラリが提供されるという意味は大きいでしょう。

Instant App

忘れてはならないのがこの Instant App。これまではクローズドでしたが、ついに一般開発者が利用可能になりました。Instant App はたとえアプリをインストールしていなくともアプリを起動できるようになります。例えば Google 検索のリンクからいきなりアプリを起動させることができるようになります。このことから、Android のアプリはより Web との親和性を得たことになります。利用するにはアプリの構造を変更する必要があります。

構造の変更方法も必見ですが、こちらの Best practices for user experience も見応えがあります。

Best practices for user experience in an instant app | Android Developers

ただ単にコードを対応すれば良いだけではなく、どのような体験を提供すべきか、UX の考え方(スプラッシュ画面を自作するなとか、インスタント版とインストール版で UI を分けるなとか)などが書かれています。

新しい開発ツール(Android Studio関連)について

細かな改善が多く含まれています。中でも一番おもしろかったのは Android Emulator の改善関連。プロキシが使えたり、Watch の Wear Rotary Control のシミュレートがサポートされたり、 Google Play Store が使えるようになったりします(これは Play Store 利用可能な image が配布されます)。

New Features in Android Studio Preview | Android Studio

まとめ

Android に関して言うと、今年はとにかく開発者向けに大きな発表があったなと言う印象です。逆に言うと、一般のユーザに対してはインパクトに欠けるものだったと思います。しかしながらピクチャ・イン・ピクチャやマルチディスプレイなど、もはや Android OS はコンピュータといえる程の能力を得ていることは明らかです。数年前と比べると、非常にパワフルな OS になりました。また圧倒的な人工知能の進捗があり、Lens や Google アシスタント など一般ユーザに対してもわかりやすい発表が出ていたため、Google の計画通りの結果と言えます。数年前では考えられなかったような機械学習の精度が今、現実となっているのです。

今後 AI First な Google の機械学習によってデバイスやアプリケーション、 OS がどのように変わり、世の中にどう影響を与えていくのでしょうか。またそれによって、我々開発者は何を学び、何を作っていくべきなのでしょうか。テクノロジーは機械学習の急激な進捗とともに加速しつつあります。それに振り落とされないように、常に柔軟に対応していきたいものです。