fkm blog

software開発に関することを書いていきます

Google I/O 2019: Build a Modular Android App Architecture

youtu.be

動画の終盤でTL;DRが出てるけど、「アプリをモジュール使ってrewriteしよう」というセッション。

どうやってAndroidアプリをモジュール化するかがテーマ。

なぜモジュール化する?

  • エンジニアが増えてきたとき、お互いの作業をストップさせないようにするため。
  • メンテナス性のため。1つのでかいアプリだと、レイアウトXMLの名前だけみても面倒なことになるが、モジュール化しておけばだいぶ解決する
  • コンパイル速度をあげるため。

ビジネス面でもモジュール化は大事。

  • App bundle
  • Dynamic features

例えばPMが「イケてるライブラリ見つけてきたぜ!でも10MBもあるけどな!」という話を持ってきたとき、モジュール化していればdynamic featureとして作っておき、A/Bテストで一部のユーザーにだけ使わせるといった手法がとれる。

どうやってモジュール化するか?

切り口は2つ。Feature(機能)とLayer(レイヤー)。

Feature

ベースアプリは単なるアプリ

// :app
apply plugin 'com.android.application'

モジュールはAndroidライブラリにする。

// :module1
apply plugin 'com.android.library'

そしてベースアプリはmodule1に依存するようにする。

// :app
implementation project(':module1')

モジュールはDynamic featureとして作ることもできる。その場合は次のようにする。

// :module2
apply plugin 'com.android.dynamic-feature'

この場合、モジュール側がベースアプリに依存するようにする(この依存が気持ち悪いという意見も)。

// :module2
implementation project(':app')

ベースアプリはDynamic featureとして用意したmodule2にはアクセスできない点に注意(循環参照になっちゃう)。

Dynamic featureはオンデマンドでのダウンロードもできる。デフォルトではoffなので、apkに含まれる。

もしモジュール間で共通して使いたいコードがある場合は、ベースアプリに持たせるのではなく、coreといった別モジュールを用意しよう。

どの機能をDynamic feature(onDemand)にするか?パレートの法則(80:20の法則)にしたがってみるのがよさそう。ほとんどのユーザーが使う20%ほどの機能はライブラリモジュールとし、それ以外をDynamic featureにしてみる。

レイヤー

ボトムアップで考えてみよう。Roomを使うようなデータベースモジュール。Webサービスとの通信とかをやるWebサービスモジュール。それらをまとめたリポジトリモジュール。リポジトリモジュールの上にUIモジュール(図がいるな。。)。

apiとimplementation

モジュールAがモジュールBに依存している場合。

  • apiの場合:モジュールBはモジュールAのpublic APIの一部
  • implementationの場合:モジュールBはモジュールAの実装の一部(=どんな処理するかまでモジュールAは知っている)

Fake implementation

「モックを作る」という言い方のほうがわかりやすいかも。テスト時にモック用実装に差し替えれるよね!

既存アプリはどうする?

まずはレイヤー化からやってみよう。機能でわけるのはそれから。

Dynamic featureを使おう

ナビゲーション

ベースアプリからDyamic featureは見れないので、

  • Intentを投げる時は文字列でクラス名を指定
  • Fragmentの場合は Class.forName()

JetpackのNavigationでは、今修正中(なのかな

データベース

One-common database

扱いは簡単だけど、全モジュールのDBを抱え込むので分離しようという流れに逆行しちゃう。

モジュール別

分離はできてるけど、「AとBに同時に書き込みたい」みたいな要求がくるとつらい。またDBコネクションもたくさん作っちゃう。

ハイブリッド

くっつけておきたいものを1つにしておく作戦。柔軟だが柔軟すぎて扱いが難しい。

Roomではうまいことマージできないか、改善中。

テストの話

モジュール化すれば非Androidのモジュール(=テストが早く実行できる)も作れるが、それを目的としてモジュール分けするのは得策ではない(単に難しい)。Robolectricがあるのでそっち使おう。

一般的に、依存関係は少なくしよう。またビジネスロジックがUIに紐づかないように といったことも考えよう。

「このアプリの構造はすばらしい」というコメントで★5をつけるユーザーはいない。ユーザーをハッピーにするのが一番大事。

Google I/O 2019: What's New in Android

www.youtube.com

なぜか冒頭の数分が録画されていなかったようで、いきなりBubblesの説明の途中から始まる。。。

Bubbles

Facebookメッセンジャーのような、他のアプリの上に重ねて何かを表示するための機能。今まではSYSTEM_ALERT_WINDOWにViewを追加することで実現していたが、将来的に廃止される予定。

Android Q(API 29)では、開発者オプションで有効にしたら使える機能。正式に出るときはユーザーのオプトインになるっぽい。

ダークテーマ

ユーザーの設定で「ダークテーマを使う」が追加。

アプリ側で対応するには、次の3つの方法がある。

テーマを使う

Theme.AppCompat.DayNight
Theme.DeviceDefault.DayNight
ThemeOverlay.DeviceDefault.Accent.DayNight

強制する

AndroidManifest.xmlandroid:forceDarkAllowed="true" をつけるか、 view.setForceDarkAllowed(true) を呼ぶか。

-nightを使う

がんばろう

共有

共有時に、コンテンツのプレビューが表示されるようになるよ。Facebookでリンクを共有しようとしたとき、OGPの内容がプレビューとして表示されるようなイメージ。

クリップボードにコピー」が右上に表示されるようになるよ。今までは共有先の1つだったけど、クリップボードへのコピー、よく使うよね!

sharing shortcut API

アプリを起動することなく共有する機能が作れるようになったよ。詳細は別セッションにて。

通知

gentleとpriorityの2セクションにわけて表示されるようになるよ。priorityとして表示されるのは、

  • アプリ:優先度の高いもの
  • OS:端末の機能として大事なやつ/人との会話/イベント/アラーム

通知アクション

コンテンツからOSが勝手に「マップで開く」とかをアクションとして追加してくれる機能。スマートリプライのもっといい版。

ジェスチャーナビゲーション

画面の左右端と下端を使って、ジェスチャーによるナビゲーションが導入されそう。そのため、iOSのように「画面の一番下にタップ可能なものを置かない」といった対応がアプリ側で必要。とはいえNavigationDrawerのようなやつもあるので、「左端はアプリが使う!」といった指定も可能になるっぽい。

ここから下はplatformに関するもの。

WebView

レンダリングがハングしたときのcallbackが追加。

アクセシビリティ

ワンライナーアクセシビリティアクションが追加できるように。

テキスト

hyphenation(ハイフネーション)が再びデフォルトでオフに。英語の時に自動でハイフンで繋ぐ機能で、パフォーマンス的にイケてないから。

他にも追加機能たくさん。詳細はテキストのセッションにて。

大鏡

Magnifier.Builder でより設定可能に。

ART

アプリのプロファイルをクラウドで集めて、いいかんじにプリコンパイルする仕組みが追加。アプリの起動時間が15%ほど早くなるらしい。

また、Generational Garbage Collectorを導入。新しいオブジェクトを早めに回収する感じかな?

Kotlin

Qで追加されるAPIにはnullability annotationがついてる。またnullabilityは強制エラーに。今までは警告だった。

kapt 1.3.30でインクリメンタルなアノテーションプロセッシングが導入。

セキュリティ

TLS 1.3がデフォルトに。生体認証ダイアログも改善。パスコード認証にフォールバックさせる仕組みも。Jetpack セキュリティライブラリ使ってみてね。

電源管理

端末の温度が一定以上になったらコールバックを受け取る仕組みが追加。

NN API

60以上の新しいAPIが追加。より低レイテンシに。

ここからはJetpack

Preferences

android.preference はdeprecatedに。androidx.preference を使おう。XMLを読ませるだけでいい感じに設定画面を作ってくれる。

Architecture Component

  • WorkManager: 1.0.1/2.0.1がstableに
  • Navigation: 1.0/2.0がstableに
  • SavedState for ViewModel: 1.0がアルファ
  • Benchmarking: 1.0がアルファ
  • Lifecycler/LiveData/Room: コルーチンサポート

CameraX

より、カメラ使うのが簡単に。機種依存もなんとかする仕組みあり。

Jetpack Compose

多分今年のI/Oで一番すごいやつ。まだまだpreviewな感じなのでみんなで作り上げていこうという感じ。一言で言うとFlutterみたいな感じでUIを作る仕組み。Kotlin compiler plugin使ってる。さよならレイアウトXML

setContent {
    Scaffold {
        Counter(title = "Bad joke")
    }
}

https://d.android.com/jetpackcompose を見てみよう。

ViewPager2

状態はalpha_04。RecyclerViewベースになっている。上下のページングにも対応。

ViewBinding

DataBindingのいい感じ版(という認識)。 <layout> で囲む必要なくなるみたい。

BlendMode

もともと、PorterDuff.Mode というのがあったけど、ドキュメント化されてなかった。さらに困ったことに porterduff とは関係ないモードまであった。なので android.graphics.BlendMode を新しく追加したよ。忘れられてた HARD_LIGHTSOFT_LIGHT とかも追加したよ。

RenderNodeとかは使う機会少なそうなので割愛

Vulkan

64bitデバイスでは1.1がrequiredになるよ。

ANGLE

Vulkan上でOpenGL ESを動かすしくみ。現時点では開発者オプションでONにしないと使えない。

Audio Playback Capture

他のアプリが再生している音をキャプチャーできるよ。キャプチャーされたら困る場合は、AndroidManifest.xmlandroid:allowAudioPlaybackCapture="..." を追加。Qではデフォルトでoff。

ここからは、プライバシーに関する変更

External Storage

Qからはサンドボックスモードがデフォルトになるよ。メディアや画像とかへのアクセスはちゃんとpermissionとる必要がある。ファイルマネージャーのようなアプリの場合は、さらに設定が必要(作れなくなるわけじゃない)。

位置情報

iOSのように、位置情報の取得を「アプリがフォアグラウンドの時だけ許す」「バックグラウンドでも許す」の選択ができるように。

バックグラウンドからのアクティビティ起動

アクティビティを起動するには、

  • フォアグラウンドからの起動
  • フォアグラウンドにいるアプリからのPendingIntent
  • システムからのPendingIntent(例:通知をタップした)
  • システムからのブロードキャスト

のみ。

カメラ

getCameraCharacteristics() はデバイス固有のデータに対しては CAMERAパーミッションが必要になる。

Connectivity

アプリでWifiのON/OFFはできなくなる。Settings Panelを使おう。

盛りだくさんだなぁ

Google I/O 5日目

土曜日はデプロイ肉に初参加。今までは帰国日と重なったりしてて参加できてなかった。

会場はデプロイゲートさんのUSオフィス。約100人ほど参加だったらしい。

deploygate.com

イベント詳細はhttps://www.eventbrite.com/e/deploy-niku-2019-meatup-for-developers-tickets-57951004013#のView Detailsでご覧ください。

Google I/O 4日目

I/O自体は3日目で終了ですが、旅は続くので4日目。

1日空いてる日だったので、お昼ぐらいからComputer History Museumに行ってみた。中の展示をたっぷり2時間ほど。教科書で見たようなコンピューターがたくさん展示されているので、この業界に関わる人は一度行っておいたほうがよさそう。$46のパックを買うとTシャツとかパンチカードとかセットでついてきてお得な感じ。お土産コーナーも1点だけ25%OFFで購入できたりする。

夜は同行人がアメリカでの映画館体験をしたいということで、PM 10時からAvengers Endgameを3人で。帰りのUberがテスラだった。

Google I/O 3日目

あっという間に3日目。15時半からのセッションでおしまいの日。

今年のI/Oは「驚くべきもの」はなかったものの、着実に進歩してるなーと感じたI/Oだった。みなさんちゃんと勉強しましょう(圧

I/O終わってから某社の人をGoogle Merchandise Storeに招待。そのついででL5レイドを3戦ほど。Google社内にもポケモンハンター、それなりにいるっぽい。

夜はex-googlerでポケモンGoコミュニティの方とディナー。日本での課題が見えてきたので、何かやりますよーと(宣言駆動

Google I/O 2日目

2日目は朝からずっとセッションの日。よって詳細は後日のエントリーにて。

14時にこれまた恒例の日本人大集合。にしても日本からの参加者多いなー

集合写真
集合写真

夕方にNEAO(North-east asia and Oceania)な参加者のパーティに参加し、Googleの@taquoさんによるツアーに参加。ぎんのドロイド君とか、Fab的な場所とかを見せてもらった。

2日目の夜はコンサート。例年、様子だけみて早めに帰ること多かったんだけど、今年は最後のほうまで参加。