Build Variants によって別バージョンの Android アプリを同じプロジェクトからビルドする (Gradle 使用)
前回の記事 に引き続き、Gradle を使った Android アプリのビルドの話。
今回は build variants (build types と product flavors) について調べたので軽くまとめておく。 複数の build variant を定義しておくと、
- アプリの本体部分のソースコードはほとんど一緒だが、少しだけ違う部分があるアプリを 1 つのプロジェクトでビルドする
- 社内リリース用のパッケージ名は本番リリース用のパッケージとは別にする
といった用途に便利である。
追記: Android Gradle plugin の新しいバージョンでのプロパティ名の変更
New Build System - Android Tools Project Site
ProductFlavor.packageName
is nowapplicationId
. Setters forpackageName
are still temporarily present but will disappear in 1.0
上記リリースノートにあるように、Android Gradle plugin 0.11.0 から、packageName
は applicationId
という名前に変更されました。 packageNameSuffix
は applicationIdSuffix
になりました。 本記事のサンプルコードは修正していませんが、実際にプロジェクトで記述するときには新しいプロパティ名を使ってください。
追記 2 (2015-06-11): 新しいドキュメント
現在では Android Developers のサイトに build variants のドキュメントがあります。 こちらも参考にしてください。
Build Types
「デバッグ用のビルド」 と 「リリース用のビルド」 という感じで、複数のビルドの種類を記述することができる。
デフォルトでは、「release」 と 「debug」 という 2 つの種類のビルドが存在する。 自分で新たにビルドの種類を追加することもできる。 また、各ビルドでのパッケージ名に接尾辞を付けるなどといった変更も行うことができる。
/* build.gradle の例 */ /* ... */ android { /* ... */ buildTypes { debug { /* デバッグ用のパッケージのパッケージ名に接尾辞を付けて、 デバッグ用インストール時に本番リリース用のパッケージを 上書きしないようにする */ packageNameSuffix ".debug" } /* 社内リリース用に新たにビルドの種類を定義する */ inhouse.initWith(buildTypes.release) inhouse { packageNameSuffix ".inhouse" } } }
さらに、Java ソースコードやリソースファイルもビルドの種類ごとに別のものを使用できるようにすることも可能なので、例えば debug ビルドと release ビルドでは別のリソースファイルを使用し、表示する文字列を変えたり、アクセスする先の URL を変えたりすることも可能である。
デフォルトでは、src/main 下のファイルと src/buildType 下 *1 のファイルがビルドに使用される。 両方に同じ ID のリソースが定義されている場合は build type ごとの値の方が優先されるっぽい。 また、同じクラス名の Java ソースコードが両方に存在する場合はエラーになるっぽい。
詳細はユーザーガイドへ。
- Build Type について: Gradle Plugin User Guide - Build Types
Product Flavors
「広告つきの無料版のアプリ」 と 「広告なしの有料版のアプリ」 といったような、同じアプリの (違いの小さな) 別バージョンを同じプロジェクトからビルドできるようにするための仕組みとして、Product Flavors というものがある。 仕組み的には build types のそれと似ているが、用途が違っている。
例えば、有料版と無料版を別パッケージとして定義するには次のように build.gradle に記述する。
/* build.gradle の例 */ /* ... */ android { /* ... */ productFlavors { /* 有料版 */ pro { packageName "info.vividcode.android.app.pfsample.pro" } /* 無料版 */ free { packageName "info.vividcode.android.app.pfsample.free" } } }
Build type の違いによって使用するリソースファイルや Java ソースコードを変化させられたように、Product flavor の違いでも使用するリソースファイルや Java ソースコードを変化させることができる。
各 flavor の名前に対応するリソースファイルと Java ソースコードは、デフォルトでは src/flavorName に配置されることが期待される。 (試してないが変更も可能だと思われる。)
詳細はユーザーガイドへ。
- Product Flavors について: Gradle Plugin User Guide - Product Flavors
Build Variants
Build type と production flavor の組を build variants という。 上の例では、
- pro-debug
- pro-inhouse
- pro-release
- free-debug
- free-inhouse
- free-release
の 6 つの build variants が存在することになる。 ビルドのタスクは、build variant ごとに作られる (assembleProductionFlavorBuildType という形式のタスク名)。 例えば pro-debug の build variant をビルドするためには、
gradle assembleProDebug
というコマンドを使うことになる。 上で述べたように、リソースファイルや Java ソースコードは build type 専用だったり production flavor 専用だったりで提供できるわけなので、assembleProDebug のビルドで使用されるリソースファイルや Java ソースコードは次の位置にあるもの全てが使用される *2。
- src/main (常に使用される)
- src/pro (pro という production flavor 用)
- src/debug (debug という build type 用)
src/pro や src/debug といったディレクトリが存在しなくてもエラーにはならないので、必要なければ作る必要はない。 ちなみに AndroidManifest.xml ファイルが複数個存在する場合には内容がマージされるようである。
複数の build variants を同時にビルドするタスク
assemblePro や assembleDebug、assemble といったような、複数の build variants を同時にビルドする gradle タスクも存在する。 ここで出した例だと、それぞれ
- assemblePro : production flavor が pro であるすべての build types のビルド
- assembleDebug : build type が debug であるすべての production flavors のビルド
- assemble : すべての build variants のビルド
が行われる。
Android Studio では
Android Studio (0.1.6 で確認) も build variants に対応している。 どこから選択するのかめっちゃ迷った *3 のでスクリーンショットを張っておく。
build.gradle ファイルを編集して新たに product flavor を追加した場合などは、メニューバーの 「Tools」 から 「Android」 を選び、「Sync Project with Gradle Files」 を実行すればよいようだ。
ビルドに失敗することがある
build.gradle をいじった後の最初のビルドではなぜか NullPointerException が発生してビルドに失敗することがあった。 まだあんまりちゃんと調べてないのでよくわからないが、同僚も 「なんか失敗することがある」 と言っていたのでビルドシステムにまだ穴があったりするのかも。 とはいえ、軽く使ってみた感じではさほど問題はないように感じたので、必要なら普通に使っていって良さそう。
関連記事
- Gradle+Androidプラグインでプロダクトフレーバーを試してみた - やらなイカ?
- Build Variantsで開発版Androidアプリを分ける - ninjinkun's diary : このエントリを書いた後に追加された Build Variants 関連の機能について説明されています。 ContentProvider の application id も変化させる、とか。 便利!