BuildConfigField は、BuildConfig という自動生成されるクラスに定義する定数をビルドスクリプトから制御する仕組みです。
そしてもうひとつ、ManifestPlaceholders は AndroidManifest のプレースホルダーに放り込む値をビルドスクリプトから制御する仕組みです。
これらを活用すると、BuildVariants を変えただけで気軽にアプリの振る舞いを変えたり、ContentProvider の Authority の衝突を防いで異なる BuildVariants の apk を同じ端末内に共存させたりといったことができるようになります。
ContentProvider の衝突を防ぐという目的では、次のように debug と release のそれぞれの BuildType で別々の Authority を定義するのが一般的です。
android {
buildTypes {
debug {
manifestPlaceholders = [
authorityHogehogeProvider : "com.sample.hogehoge.debug.provider.HogehogeProvider"
]
BuildConfigField "String", "AUTHORITY_HOGEHOGE_PROVIDER", "\"com.sample.hogehoge.debug.provider.HogehogeProvider\""
}
release {
manifestPlaceholders = [
authorityHogehogeProvider : "com.sample.hogehoge.provider.HogehogeProvider"
]
buildConfigField "String", "AUTHORITY_HOGEHOGE_PROVIDER", "\"com.sample.hogehoge.provider.HogehogeProvider\""
}
}
}
こうしておけば、AndroidManifest.xml
は main ソースセット配下の一個だけで済みます。
<manifest>
<application>
<provider
androidname=".provider.HogehogeProvider"
androidauthorities="${authorityHogehogeProvider}"
androidlabel="HogehogeProvider"
androidexported="false"/>
</application>
</manifest>
ここで、この ContentProvider を flavor1 と flavor2 という2つの ProductFlavor でそれぞれ持つことを考えます。
先程の buildTypes で manifestPlaceholders を分けるコードのみでは、flavor1 と flavor2 とで ContentProvider が衝突するため共存できません。
ProductFlavor と BuildType の組み合わせで manifestPlaceholders や BuildConfigField を制御する場合は、次のようにすべての BuildVariants を走査して対応するものを差し込むロジックを書きます。
android {
productFlavors {
flavor1 {}
flavor2 {}
}
buildTypes {
debug {}
release {}
}
applicationVariants.all { variant ->
def flavorName = variant.productFlavors.get(0).name
def typeName = variant.buildType.name
if (flavorName.equals("flavor1")) {
if (typeName.equals("debug") {
variant.mergedFlavor.manifestPlaceholders = [
authorityHogehogeProvider : "com.sample.hogehoge.flavor1.debug.provider.HogehogeProvider"
]
variant.buildConfigField "String", "AUTHORITY_HOGEHOGE_PROVIDER", "\"com.sample.hogehoge.flavor1.debug.provider.HogehogeProvider\""
} else if (typeName.equals("release") {
variant.mergedFlavor.manifestPlaceholders = [
authorityHogehogeProvider : "com.sample.hogehoge.flavor1.release.provider.HogehogeProvider"
]
variant.buildConfigField "String", "AUTHORITY_HOGEHOGE_PROVIDER", "\"com.sample.hogehoge.flavor1.release.provider.HogehogeProvider\""
}
} else if (flavorName.equals("flavor2") {
if (typeName.equals("debug") {
variant.mergedFlavor.manifestPlaceholders = [
authorityHogehogeProvider : "com.sample.hogehoge.flavor2.debug.provider.HogehogeProvider"
]
variant.buildConfigField "String", "AUTHORITY_HOGEHOGE_PROVIDER", "\"com.sample.hogehoge.flavor2.debug.provider.HogehogeProvider\""
} else if (typeName.equals("release") {
variant.mergedFlavor.manifestPlaceholders = [
authorityHogehogeProvider : "com.sample.hogehoge.flavor2.release.provider.HogehogeProvider"
]
variant.buildConfigField "String", "AUTHORITY_HOGEHOGE_PROVIDER", "\"com.sample.hogehoge.flavor2.release.provider.HogehogeProvider\""
}
}
}
}
ProductFlavor は複数定義可能なので、複数ある場合はvariant.productFlavors.get(n)
のn
も適宜どの ProductFlavor に対して BuildConfigField や ManifestPlaceholders を差し込むかによって変えます。
BuildConfigField は variant が直接持っていますが、ManifestPlaceholders は variant.mergedFlavor
配下に対して設定します。variant.buildType
にもmanifestPlaceholders
がありますが、こちらには設定できないことに注意しましょう。