ProductFlavorで異なるソースを使ったアプリケーションを作成する

## ビルドバリアント
Androidにはビルドバリアントと呼ばれる様々なバージョンのアプリを作成する機能があり
環境の切り替え方には以下の2種類がある

- BuildType: 本番用(release)、開発用(debug)などの違いで環境を切り分けるもの
- ProfuctFlavor: 無料用、有料用といった共通のソースをベースに亜種をつくるもの

デフォルトではProductFlavorは設定されておらずBuildTypeのみが設定されている

## Product Flavorの設定方法
AndroidStudioのGUIで行う方法とgradleでの設定の2通りある。
下記ではgradleファイルを編集する形で修正する

```title:app/build.gradle
android {
    compileSdkVersion 29
    buildToolsVersion "29.0.0"
    defaultConfig {
        applicationId "com.example.test01"
        minSdkVersion 26
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    // ここから以下を追加
    flavorDimensions 'mode'
    productFlavors {
        blue {
            dimension = 'mode'
        }
        freen {
            dimension = 'mode'
        }
    }
  // ここまで
}

 ```


ProductFlavorは必ずFlavorDimensionに属している必要がある。上記では以下の形で構成している

**mode** (dimension)
┝ **blue**
┝ **green**

このように設定すると既定値でソースセットが以下に変わる

```
// 一部抜粋
------------------------------------------------------------
Project :app
------------------------------------------------------------

blueDebug
---------
Compile configuration: blueDebugCompile
build.gradle name: android.sourceSets.blueDebug
Java sources: [app/src/blueDebug/java]
Manifest file: app/src/blueDebug/AndroidManifest.xml
Android resources: [app/src/blueDebug/res]
Assets: [app/src/blueDebug/assets]
AIDL sources: [app/src/blueDebug/aidl]
RenderScript sources: [app/src/blueDebug/rs]
JNI sources: [app/src/blueDebug/jni]
JNI libraries: [app/src/blueDebug/jniLibs]
Java-style resources: [app/src/blueDebug/resources]

blue
----
Compile configuration: blueCompile
build.gradle name: android.sourceSets.blue
Java sources: [app/src/blue/java]
Manifest file: app/src/blue/AndroidManifest.xml
Android resources: [app/src/blue/res]
Assets: [app/src/blue/assets]
AIDL sources: [app/src/blue/aidl]
RenderScript sources: [app/src/blue/rs]
JNI sources: [app/src/blue/jni]
JNI libraries: [app/src/blue/jniLibs]
Java-style resources: [app/src/blue/resources]

green
-----
Compile configuration: greenCompile
build.gradle name: android.sourceSets.green
Java sources: [app/src/green/java]
Manifest file: app/src/green/AndroidManifest.xml
Android resources: [app/src/green/res]
Assets: [app/src/green/assets]
AIDL sources: [app/src/green/aidl]
RenderScript sources: [app/src/green/rs]
JNI sources: [app/src/green/jni]
JNI libraries: [app/src/green/jniLibs]
Java-style resources: [app/src/green/resources]

debug
-----
Compile configuration: debugCompile
build.gradle name: android.sourceSets.debug
Java sources: [app/src/debug/java]
Manifest file: app/src/debug/AndroidManifest.xml
Android resources: [app/src/debug/res]
Assets: [app/src/debug/assets]
AIDL sources: [app/src/debug/aidl]
RenderScript sources: [app/src/debug/rs]
JNI sources: [app/src/debug/jni]
JNI libraries: [app/src/debug/jniLibs]
Java-style resources: [app/src/debug/resources]

main
----
Compile configuration: compile
build.gradle name: android.sourceSets.main
Java sources: [app/src/main/java]
Manifest file: app/src/main/AndroidManifest.xml
Android resources: [app/src/main/res]
Assets: [app/src/main/assets]
AIDL sources: [app/src/main/aidl]
RenderScript sources: [app/src/main/rs]
JNI sources: [app/src/main/jni]
JNI libraries: [app/src/main/jniLibs]
Java-style resources: [app/src/main/resources]

```

* main: 共通で利用されるソース
* blue,green: Flavorを指定した際に優先的に参照されるソース

## 利用ソースセットの優先順位
ソースセットは以下の順で参照される

1. buildType、ProductFlavorが一致
2. buildTypeが一致
3. ProductFlavorが一致
4. その他(mainソースセットを参照)

## サンプル
以下ではBlueフレーバー、Greenフレーバーの2種でのソース切り替えを行う

### ディレクトリ概要
---

* mainに各フレーバーで利用するソースを記述
* blueには切り替え用のMainActivityとMainActivity指定用にManifestファイルを設置

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298034/5d4b4c6b-c7c9-3cdc-0f96-2f55cf4e65a5.png" width=50%>

### ProductFlavor設定
---

```build.gradle
android {
    compileSdkVersion 29
    buildToolsVersion "29.0.0"
    defaultConfig {
        applicationId "com.example.test01"
        minSdkVersion 26
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    flavorDimensions 'mode'
    productFlavors {
        blue {
            dimension = 'mode'
            applicationIdSuffix ".blue"
        }
        green {
            dimension = 'mode'
            applicationIdSuffix ".green"
        }
    }
}
```
### mainソースセット
---

```kotlin:com.example.test01.MainActivity
package com.example.test01

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setFragment()
    }

    private fun setFragment() {
        val transaction = supportFragmentManager.beginTransaction()
        val fragment = GreenFragment()
        transaction.replace(R.id.fragment_base, fragment)
        transaction.commit()
    }
}

```

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

    <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>
```

### Blueソースセット
---

```kotlin:com.example.com.blue.MainActivity
package com.example.test01.blue

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setFragment()
    }

    private fun setFragment() {
        val transaction = supportFragmentManager.beginTransaction()
        val fragment = BlueFragment()
        transaction.replace(R.id.fragment_base, fragment)
        transaction.commit()
    }
}


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

    <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">

        <!- ↓のnameが変わった->
        <activity android:name=".blue.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

```
### 結果
---

#### blueDebug
<img display=inline-block width=30% src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298034/6cc3bfcb-2e63-3612-5ef1-aebb3058bcb1.png'>

#### greenDebug
* greenは個別に設定していないのでmainソースセットをそのまま参照している
<img display=inline-block width=30% src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298034/c4c153f4-293f-4252-8ae2-0ddeace7a145.png'>