sumioの技術メモ

Androidについての記事が多くなると思います。

Android Gradleプラグインにおけるビルドタイプ・フレーバー・フレーバーグループ

Android Gradleプラグインには、「同じような機能を持つけれども少しだけ異なるアプリ」を、便利に開発するための機能が備わっています。
そのためには以下の3つの概念を理解しておく必要があるのですが、すぐに分からなくなってしまうので、ここにメモしておこうと思います。

  • ビルドタイプ
  • フレーバー
  • フレーバーグループ

ビルドタイプ

ビルドタイプは「デバッグ版」「リリース版」を分けるのに使います。デフォルトでは、デバッグ版を表すdebugと、リリース版を表すreleaseの2つのタイプが定義されています。
デバッグ版にはデバッグ署名が付けられ、リリース版には、build.gradleに書いた設定にしたがって、リリース向けの署名が付けられる、といった具合です。

もちろん、必要であれば第3のビルドタイプ、第4のビルドタイプを定義することもできますし、ビルドタイプごとに、ソースコードを差し替えたり、リソースを差し替えたりすることもできます。

なお、デフォルトでは、テストは「デバッグ版」に対してしか実行されません。試験対象を他のビルドタイプに変更することはできますが、複数のビルドタイプを試験対象にすることはできません*1

フレーバー

フレーバーは、アプリケーションの一部の機能や振舞いをカスタマイズするために使います。たとえば「広告あり」フレーバーと「広告なし」フレーバーを定義する、といった具合です。
フレーバーは、build.gradleに定義することではじめて作られますが、1つもフレーバーが定義されていない場合は、暗黙的に名前のない1つのフレーバーが定義されているとみなされます。

ビルドタイプと同様に、フレーバーについても、それぞれソースコードを差し替えたり、リソースを差し替えたりすることができます。

こちらは、ビルドタイプとは異なり、全てのフレーバーが試験対象となります。そのため、テストコードもフレーバーごとに差し替えることが可能になっています。

フレーバーグループ

フレーバーが複数定義されている場合、gradle assembleコマンドによってビルドされるapkは、ビルドタイプの集合とフレーバーの集合の全組み合わせになります。
たとえば、ビルドタイプとフレーバーが、それぞれ以下のように定義されているとします。

  • ビルドタイプ: debug, release
  • フレーバー: f1, f2, fa, fb

この場合にビルドされるapkは、以下の8種類になります。

  • ビルドタイプがdebugで、かつ、フレーバーがf1のもの
  • ビルドタイプがdebugで、かつ、フレーバーがf2のもの
  • ビルドタイプがdebugで、かつ、フレーバーがfaのもの
  • ビルドタイプがdebugで、かつ、フレーバーがfbのもの
  • ビルドタイプがreleaseで、かつ、フレーバーがf1のもの
  • ビルドタイプがreleaseで、かつ、フレーバーがf2のもの
  • ビルドタイプがreleaseで、かつ、フレーバーがfaのもの
  • ビルドタイプがreleaseで、かつ、フレーバーがfbのもの

フレーバーグループは、上記のようなapk生成時の組み合わせを制御するためのもので、フレーバーを複数のグループに分割するために利用します。たとえば、この4つのフレーバーを、以下のように2つのフレーバーグループに所属させてみます。

  • フレーバーグループ1: f1, f2
  • フレーバーグループ2: fa, fb

このようにグループ分けを行うと、ビルドされるapkは、ビルドタイプの集合と、各フレーバーグループの集合の全組み合わせとなります。この場合だと{build, release} × {f1, f2} × {fa, fb}という組み合わせになりますので、以下の8種類のapkがビルドされることになります。

  • ビルドタイプがdebugで、かつ、フレーバーがf1、かつfaのもの
  • ビルドタイプがdebugで、かつ、フレーバーがf1、かつfbのもの
  • ビルドタイプがdebugで、かつ、フレーバーがf2、かつfaのもの
  • ビルドタイプがdebugで、かつ、フレーバーがf2、かつfbのもの
  • ビルドタイプがreleaseで、かつ、フレーバーがf1、かつfaのもの
  • ビルドタイプがreleaseで、かつ、フレーバーがf1、かつfbのもの
  • ビルドタイプがreleaseで、かつ、フレーバーがf2、かつfaのもの
  • ビルドタイプがreleaseで、かつ、フレーバーがf2、かつfbのもの

このように、フレーバーグループを適切に使うことで、いくつもの差分を積み重ねたapkを一気にビルド・テストすることができるようになります。

優先順位

これらの機能を駆使して、差分を積み重ねたapkがビルドできるようになると、各差分に同一の定義がある場合(たとえば同じ名前のstringリソースが、debugf1faに定義されている場合など)に、何が優先されるのか、ということが問題になります。

それもきちんと決まっていて、以下のリストのうち、上にある方がより優先度が高いことになっています。言い換えると、リストの下から順に上書きされていきます。

  • ビルドタイプ
  • フレーバーグループのうち、1つめに宣言したもの
  • フレーバーグループのうち、2つめに宣言したもの
  • ...

このように、フレーバーグループの宣言順序によって優先度が決まってしまうので、フレーバーグループの宣言には気を使う必要がありあます。なお、フレーバーグループの宣言は、以下のような感じで行います。

android {
    ...
    // "group1"の方が"group2"より優先度が高い
    flavorGroups "group1", "group2"
    ...
}

まとめ

特に分かりにくいと思われる点をざっくりまとめてみます。

  • ビルドタイプもフレーバーも、ソースコードやリソースの一部を差し替えることが出来る、という点では同じですが、ビルドタイプは1つしかテスト対象にできない点に注意が必要です。
  • ビルドされるapkは、ビルドタイプとフレーバーの組み合わせになりますが、フレーバーグループを定義することで、組み合わせ方法を制御することができます。
  • フレーバーグループの宣言順序によって、差分適用の優先度が変化することに注意が必要です。

*1:adt-devのやりとりによると、近い将来にこの制限は撤廃されそうな雰囲気です。