Android ビルド環境の切り分けをする

build.gradle の設定をして、表のような分類で

* (1) ビルドを切り分けする
* (2) 設定値を切り分けする(free と pro で分ける)

|         | debug       | staging       | release |
| --      | --          |  --           |  --     |
| free   | デバッグ用フリー版 | ステージングフリー版 | 本番フリー版  |
| pro    | デバッグ用プロ機能版  | ステージングプロ機能版 | 本番プロ機能版  |


手元の環境

* Android Studio 2020.3.1
* gradle 7.0.3
* JDK 1.8
* Windows 11(21H2)
* Android SDK
    * compile, target, min 共に 28

## (1) ビルドを切り分けする

プロジェクト作りたての場合を想定する。build.gradle(モジュール単位) > `buildTypes` は以下のような作りである。

```build.gradle
.
.
android {
    .
    .
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    .
    .
}
```

### (1-1) buildTypes に debug, staging を追加する

|         | debug (!! 追加 !!)      | staging (!! 追加 !!)       | release(元々ある) |
| --      | --          |  --           |  --     |
| free   | デバッグ用フリー版 | ステージングフリー版 | 本番フリー版  |
| pro    | デバッグ用プロ機能版  | ステージングプロ機能版 | 本番プロ機能版  |


標準で debug の追加設定は不要。Android Studio 側で適当にやってくれる。

もし追加設定したい場合、`debuggable true` は必ず設定する。

```build.gradle
android {
    .
    .
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        
        // 以下2つのビルドタイプを追加(debug, staging)
        /**
         * 1. applicationIdSuffix:
         *      applicationId の suffix(末尾) に .debug を追加する
         * 2. debbugable:
         *      debug 可能とする
         */
        debug {
            applicationIdSuffix ".debug"
            debuggable true
        }

        /**
         * 1. initWith:
         *      debug ビルドから設定をコピーする
         *      (applicationIdSuffix, debbugable をコピーしている)
         *      追加・上書きするものだけ記載する
         * 2. applicationIdSuffix:
         *      applicationId の suffix(末尾) に .debug を追加する
         *      debug の設定を上書きする
         */
        staging {
            initWith debug
            applicationIdSuffix ".staging"
        }
    }
    .
    .
}
```

### (1-2) productFlavors を追加する

|         | debug       | staging       | release |
| --      | --          |  --           |  --     |
| **free (!! 追加 !!)** | デバッグ用フリー版 | ステージングフリー版 | 本番フリー版  |
| **pro (!! 追加 !!)**  | デバッグ用プロ機能版  | ステージングプロ機能版 | 本番プロ機能版  |

`buildTypes` と並べて、`flavorDimensions` と `productFlavors` を記述する。

`productFlavors` 内の `flavor`(例の `free` や `pro`) は、`flavorDimensions` に依存させる。

```
android {
    .
    .
    buildTypes {
      ...
    }
    flavorDimensions "pricing"
    productFlavors {
        free {
            dimension "pricing"
            applicationIdSuffix ".free"
        }
        pro {
            dimension "pricing"
            applicationIdSuffix ".pro"
        }
    }
    .
    .
}
```

以上まで設定すれば、`buildVariants` にて `{productFlavors}{buildTypes}` の名前一覧が表示される。

![buildVariants.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31223/401d42fc-b61d-f6e1-3523-498efe18820d.png)

## (2) 設定値を切り分ける(free と pro で分ける)

values.xml を `free` と `pro` で切り分けたいとする。

### (2-1) free 用の values.xml を追加する

`buildVariants` から `freeXXX` のどれか一つを選ぶ。

[Project] タブ > app > (右クリック) > New > XML > Values XML File > `Target Source Set` を `free` を選択。

(Values File Name はデフォルトのままでよい)

values.xml を例のように記載する。

```app/src/free/values/values.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="pricing">free_plan</string>
</resources>
```

### (2-2) pro 用の values.xml を追加する

`buildVariants` から `proXXX` のどれか一つを選ぶ。

(2-1) と同じ要領で、values.xml を追加する(`Target Source Set` は `pro` を選択)

values.xml を例のように記載する。

```app/src/pro/values/values.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="pricing">pro_plan</string>
</resources>
```

### (2-3) 設定値を使う

(2-1), (2-2) の例に倣えば、`R.string.pricing` と記述したら

* ビルド環境が `freeXXX` ならば `"free_plan"`
* ビルド環境が `proXXX` ならば `"pro_plan"`

を取得できる。

```MainActivitiy.java
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        String pricing = getResources().getString(R.string.pricing); // free or plan で切り分けられる
        TextView text = (TextView) findViewById(R.id.mainTextView);
        text.setText(pricing);
    }
```

設定値以外もあるようだが、最小限のここまでとする。

## 参考

* https://developer.android.com/studio/build/application-id
* https://developer.android.com/studio/build/build-variants
* https://developer.android.com/studio/publish/versioning
* https://developer.android.com/studio/build