78
81

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Androidアプリのビルド設定管理(Product Flavor、Build Type)

Posted at

Product FlavorとBuild Type

Android Gradle pluginにはProduct Flavor(以下Flavor)とBuild Typeという機能があり、テスト用、本番用などでアプリのビルド設定を切り替えることができる。
Flavorは主にアプリで使用する文字列や画像などのリソースの切り替え、Build Typeは署名や圧縮の設定切り替えをすることが多い。

Flavorは任意の名前のものを自分で定義するが、Build Typeは標準でdebugrelease
の2種類が用意されている。
Build Typeを追加することもできるが、特に必要なければdebugとreleaseをそのまま使用すればよい。

Build Variants

FlavorとBuild Typeを組み合わせたものをBuild Variantsという。
例えば、Flavorをa、b、cの3種類定義し、Build Typeを標準のdebugとreleaseのままにした場合、Build Variantsは以下の6種類となる。

  • aDebug
  • aRelease
  • bDebug
  • bRelease
  • cDebug
  • cRelease

Android Studioでアプリをビルドする場合、Build Variantsのウィンドウで任意のBuild Variantを選択してビルドすることができる。

スクリーンショット 2018-05-01 16.09.51.png

Variant Filter

Build VariantはFlavorとBuild Typeの全ての組み合わせが自動で作成されるが、variantFilterを用いて不要な組み合わせを作成しないようにできる。

build.gradle

    variantFilter { variant ->
        // buildTypeが"debug"、flavorが"a"のBuild Variantは作成しない
        if (variant.buildType.name == "debug" && variant.flavors*.name.contains("a")) {
            setIgnore(true)
        }
    }

variantFilter内に任意の判定を書いて、setIgnore(true)とするとそのBuild Variantは作成されなくなる。

Flavorはvariant.flavorsの形でListで取得されるが、ここに記載するbuild.gradleではflavorsには一つのflavorしか入らない。

FlavorおよびBuild Typeで切り替えられること

必要であれば様々な設定を切り替えられるが、主に以下を切り替えることが多い。

applicationId
applicationIdをFlavor毎に変えることで、各Flavorでビルドしたアプリを別アプリとして同じ端末にインストールできる
文字列リソース
strings.xml などの文字列リソースをFlavorによって切り替えられる
プログラム処理
Flavorによってプログラム処理を切り替えられる
署名の設定(SigningConfig)
Build TypeまたはFlavorによってアプリの署名設定を切り替えられる
プロガード(難読化)の設定
Build TypeまたはFlavorによってプロガードの有効/無効などを切り替えられる

build.gradleの設定

以下はproduction、staging、develop3つのFlavorを定義して、それぞれapplicationIdを変更するbuild.gradleの例。

build.gradle
apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "net.sample.myapplication"
        minSdkVersion 21
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
    }

    // !!!! ProductFlavorの設定 !!!!!
    flavorDimensions "default"
    productFlavors {
        production {
            applicationId "net.sample.myapplication"
        }
        staging {
            applicationId "net.sample.myapplication_staging"
        }
        develop {
            applicationId "net.sample.myapplication_develop"
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
}

リソースの切り替え

build.gradleにFlavorを定義すると、各Flavorで別々に文字列や画像などのリソースを保持することができる。(もちろん共有することも可能)

リソースをFlavor毎に定義する場合、"res/values" フォルダで右クリックし、コンテキストメニューから "New > Values resource file" を選択した後、"Source set"の欄で追加先のFlavorを選択してリソースファイルを追加する。(mainは全Flavorで共通)

スクリーンショット 2018-05-01 14.28.17.png

各ProductFlaovrに固有のリソースは、srcフォルダの下の各ProductFlaovr名のフォルダに配置される。

スクリーンショット 2018-05-01 18.26.33.png

また、FlavorだけでなくBuild Typeごとにリソースを定義したり、FlavorとBuild Typeの組み合わせに対して定義することもできる。

文字列リソースの切り替え

Androidプロジェクトを作成すると標準でmain/resフォルダの下に文字列を定義するための strings.xml ファイルが用意されるが、Flaovr毎に文字列リソースを切り替える場合、これとは別に各Flavor用のxmlファイルを作成する。

ファイル名はstrings.xmlでも良いが、別の名前にしておくと共通の文字列リソースと区別がついて分かりやすい。
ここでは各Flavorごとの文字列リソースファイルをenvironment.xmlとして作成する前提で話を進める。

アプリ名の切り替え

上記「リソースの切り替え」を用いて、ProductFlavor毎にアプリの表示名(ホーム画面のアプリアイコンの下に表示される名前)を変えることができる。

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="net.sample.myapplication">

    <application
        android:label="@string/app_name">
        <!-- 以下略 -->
    </application>

</manifest>

AndroidManifestに記載されたアプリ名は、上記のように標準で文字列リソースのapp_nameを参照するようになっているので、各Flavorの文字列リソースファイルに以下のように別々のapp_nameを記載してやれば、Flavor毎にアプリ名を切り替えることができる。

Flavor developのenvironment.xml

environment.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">DevApp</string>
</resources>

Flavor stagingのenvironment.xml

environment.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">STGApp</string>
</resources>

Flavor productionのenvironment.xml

environment.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">本番アプリ名</string>
</resources>

プログラム内での処理分岐方法

Flavorによってプログラム内の処理を分岐させることができる。
BuildConfig.FLAVORから現在のFlavorを文字列で取得できるので、その値を見て処理を分岐させる。

public class Environment {
    String apiURL = null;

    public Environment() {
        if (BuildConfig.FLAVOR.equals("production")) {
            apiURL = "https://api-prod.net";
        } else if (BuildConfig.FLAVOR.equals("staging")) {
            apiURL = "https://api-stg.net";
        } else if (BuildConfig.FLAVOR.equals("develop")) {
            apiURL = "https://api-develop.net";
        }
    }
}

signingConfigsの切り替え

signingConfigs(署名の設定)はFlavorやBuild Typeとは別に定義して、各FlavorやBuild Typeで任意のsigningConfigを使うことができる。

build.gradle

// 複数のsigningConfigsを定義
signingConfigs {
    foo {
        storeFile = new File('keystore_foo.p12')
        storePassword = 'password'
        keyPassword = 'password'
        keyAlias = '1'
    }
    bar {
        storeFile = new File('keystore_bar.p12')
        storePassword = 'password'
        keyPassword = 'password'
        keyAlias = '1'
    }
}

buildTypes {
    release {
        // BuildType=releaseの場合、signingConfig fooを使用
        signingConfig signingConfigs.foo
    }
    debug {
        // BuildType=debugの場合、signingConfig barを使用
        signingConfig signingConfigs.bar
    }
}

上記の例はBuild TypeによってsigningConfigを切り替えているが、Flavorによって切り替えることもできる。

カスタムフィールド(buildConfigField)の定義

buildConfigFieldを使って各Flavorごとに任意の値をプログラムに渡すことができる。

build.gradle

productFlavors {
    a {
        applicationId "net.sample.myapplication"
        buildConfigField "boolean", "IS_LOG_ENABLED", "false"
    }
    b {
        applicationId "net.sample.myapplication_staging"
        buildConfigField "boolean", "IS_LOG_ENABLED", "true"
    }
    c {
        applicationId "net.sample.myapplication_develop"
        buildConfigField "boolean", "IS_LOG_ENABLED", "true"
    }
}
プログラム側処理
if (BuildConfig.IS_LOG_ENABLED) {
    Log.d("tag", "message");
}

Flavorによって挙動を変えたいが、BuildConfig.FLAVORの判定では分かりづらい場合などに用いる。
boolean以外にStringなども定義できるが、StringについてはFlavorごとに文字列リソースを用意できるので不要かと思われる。

PUSH通知のパーミッション設定

プッシュ通知(GCM)を使う場合、AndroidManifest.xmlにカスタムのパーミッションを記載する必要があるが、どこかのAndroidバージョンからpermission名が重複するアプリがインストールできなくなってしまった。

そのため、複数Flavorのアプリを同時インストールしたい場合、パーミッション名を以下のようにapplicationIdによって動的に切り替える。

AndroidManifest.xml

    <permission android:name="${applicationId}.permission.C2D_MESSAGE" android:protectionLevel="signature" />
    <uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />

78
81
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
78
81

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?