ReactNative(Android)でビルドバリアント毎にapk出力(署名つき)

Build Variantで環境と署名を分けている時に、terminalで署名つきapkを吐き出す方法について書きます。
リリースビルドする時にbundleが更新されず、コードの差分が反映されない事があったので、その対応もしました。

##前提

**Build Variantが以下の構成**で、

|  Flavor  |  Build Type  |BuildVariant |
| ---- | ---- |----|
|  develop  |  debug  |developDebug|
|  develop  |  release  |developRelease|
|  staging  |  debug  |stagingDebug|
|  staging  |  release  |stagingRelease|
|  staging  |  debug  |productionDebug|
|  staging  |  release  |productionRelease|

かつ**以下のように署名がフレーバー毎に分かれている**とします。

```gradle
    productFlavors {
        production {
            applicationId 'com.hoge'
            signingConfig signingConfigs.production
        }
        staging {
            applicationId 'com.hoge.staging'
            signingConfig signingConfigs.develop
        }
        develop {
            applicationId 'com.hoge.develop'
            signingConfig signingConfigs.develop
        }
    }
```

Build Variantについて、およびFlavor毎の`signingConfig`の切り分け方については、以前書いた[ReactNativeのAndroid側でFlavorで環境を切り分ける](https://qiita.com/nichi_yo/items/35eb6d3d4a766dc24f3e)もご参照ください。

## terminalでapkを吐き出す方法

既に署名はbuilg.gradleにbuildFlavor毎に定義しているので、以下のようにコマンドを打つだけで署名つきのapkを吐き出してくれます。

developReleaseを吐き出す時

```terminal
cd android
./gradlew assembleDevelop
```

stagingReleaseを吐き出す時

```terminal
cd android
./gradlew assembleStaging
```

productionReleaseを吐き出す時

```terminal
cd android
./gradlew assembleProduction
```

##吐き出されるapkの場所

`android/app/build/outputs/apk...`に配置されます。

developReleaseを吐き出した時

```
android/app/build/outputs/apk/develop/release/app-develop-release.apk
```

stagingReleaseを吐き出した時

```
android/app/build/outputs/apk/staging/release/app-staging-release.apk
```

productionReleaseを吐き出した時

```
android/app/build/outputs/apk/production/release/app-production-release.apk
```

##吐き出されたapkの署名を確認

[[Android] apk 署名 確認](https://qiita.com/wada811/items/7b1f64f7194d05b29e06)などをご参照ください。

##はまったところ(bundleの更新)

今回のbuild variant云々とは関係なく、以前ビルドしようとした時に

`Unable to load script from assets index.android.bundle`

というエラーに悩まされ、

[ReactNative Androidで 『Unable to load script from assets index.android.bundle』エラーが出た時の対処法](https://qiita.com/AkiraTameto/items/5f8cef91fd96d145d6df)などを参考にしながら`package.json`に以下のスクリプトを書いていました。

```json
"android-reset-bundle": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res",
```
以下で実行

```terminal
yarn android-reset-bundle
```

ただ、調査不足なのかもしれないですが、なんだか**リリースビルドをするたびに上記コマンドを打たないと、ソースコードの差分が反映されない**ということに悩んでいました。

リリースビルドをするたびにこの`bundle`が自動で更新されれば良いのですが、何故かやってくれない。
だから、`android-reset-bundle`をし忘れると、前回作ったbundleが読み込まれてしまって、差分が反映されていないのかなと（間違っていたらご指摘ください！）
iOSだと、こういうの必要なく、アーカイブする毎に自動で最新bundleを生成してくれるようですが。

ただ毎回`android-reset-bundle`をしてからapk書き出すのも面倒だし保守的にも漏れの元なので、こいつらをまとめたスクリプトを書きました。

```json
  "scripts": {
    "android-reset-bundle": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res",
    "android-release-develop": "yarn android-reset-bundle && cd android && ./gradlew assembleDevelop",
    "android-release-staging": "yarn android-reset-bundle && cd android && ./gradlew assembleStaging",
    "android-release-production": "yarn android-reset-bundle && cd android && ./gradlew assembleProduction",
  },
```

これにより、例えば

```terminal
yarn android-release-develop
```

と打てば、bundleの再生性とapkの書き出しまでを同時にやってくれます。

以上です。