Googleが教えてくれないアプリのリリース作業の話

リリース作業をしていて、いつも不安になって気が気じゃないので、バージョンコードとバージョンネームの仕様についてまとめてみたいと思います。

もしかしたら、Android上級者はリリースフローを自動化したり、CI/CDツールの活用によってこういった問題にぶち当たることはないのかもしれないですが、GooglePlayConsoleの仕様を理解する、という目的なので、今回はそういったハイスキルな部分には触れないつもりで、初級〜中級者向けにまとめるつもりで書きたいと思います:santa_tone1:

## 1. 作ったアプリのAPK/AABファイルをストアに公開する
ユーザーにアプリを公開する場合、GooglePlayConsoleの `[リリース管理]` -> `[アプリのリリース]` ページにて `製品版トラック` と書かれたところに作成したビルドファイルをアップロードして公開処理をすればリリースが可能です。
<img width="976" alt="スクリーンショット 2018-12-22 16.56.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/83877/83067571-fc01-7dd9-e34b-a70227c6f889.png">

最初のリリースではあれば特に問題なくリリースできる、だろうと思います。

上記画像でいうと、バージョンコードは `1` 、バージョンネームは　`1.0` を表していることになります。
これは `app/build.gradle` に設定されている　`versionCode` と `versionName` に紐付いていることになりますね。

さて、初めて問題にぶち当たる(不安を抱える)のは製品版アプリのバージョンアップをしたいときでしょう。

## 2. 公開済み製品版アプリを更新したい
様々な理由によって、製品版アプリは更新されていくべきです。
その際、特に何も考えずにAPK/AABファイルを公開しようとすると、以下のような問題が起きるかもしれません。
<img width="966" alt="スクリーンショット 2018-12-22 16.59.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/83877/07e5b4ca-3160-e3be-cb08-ef3541d849af.png">

バージョンコードを `1` 以外にしてくれと怒られていますね。
バージョンコードが `1` のビルドは初めてアプリを公開した時にもう使ってしまっています。同じバージョンコードを持つビルドファイルを複数アップロードすることはできないのです。
それでは、バージョンコードを変えるために `app/build.gradle` を変更しましょう。


....ただ、このときどういう風に値を変えるのが良いのでしょう。例えばこんな疑問が生まれないでしょうか？

- バージョンコードは数字なのでとりあえずインクリメントしとけばOK？
- 既存のバージョンコードと被らないなら大きな数値でもいいの？
    - Javaでいう `System.currentTimeMillis()` とか？
- 『別のバージョンコード』なら現存のバージョンコードより低くてもいいわけ？
- バージョンネームの方は一緒でいいのかどうなんだい？

それぞれ解決していきましょう。

### ・ バージョンコードは数字なのでとりあえずインクリメントしとけばOK？
アプリ更新時はどんなときもインクリメントでOKです。インクリメントしておけば誰も不幸にならないはずです。

### ・ 既存のバージョンコードと被らないなら大きな数値でもいいの？
[u2020/JakeWharton](https://github.com/JakeWharton/u2020/blob/master/app/build.gradle)ではこんな記述を見かけました。参考にしてもいいかもしれません！

```groovy:u2020/build.gradle
def versionMajor = 1
def versionMinor = 0
def versionPatch = 0
def versionBuild = 0

android {
    
    defaultConfig {

        versionCode versionMajor * 10000 + versionMinor * 1000 + versionPatch * 100 + versionBuild
        versionName "${versionMajor}.${versionMinor}.${versionPatch}"
    }
}
```

ちなみに、 `versionCode` は10桁以上の数字にするとビルドエラーになるようです。数値が大きすぎるものが設定されていると警告も出してくれていましたので、桁外れな数字にするのはやめておきましょう。
そういう意味でいうと、 `System.currentTimeMillis()` の値を使うのは危険ですね:joy:

### ・ 『別のバージョンコード』なら現存のバージョンコードより低くてもいいわけ？

リリースされている製品版のバージョンコードよりも低く設定されたビルドファイルを公開しようとすると、まだ一度もGooglePlayConsoleにアップロードしたことのないバージョンコードが設定されたビルドファイルであれば、アップロードは成功します。ただ、公開が成功することはありません。以下のようなエラーが出ます。
<img width="967" alt="スクリーンショット 2018-12-22 17.56.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/83877/0f7c7f99-0c4e-a563-9a27-7a1cbc11804b.png">
つまり、

**バージョンコードが既存の製品版よりも高い = ユーザーがストアから対象アプリをアップグレードできる**

という仕様のようですね。仮にバージョンコードが低いものを公開したとしても、既存ユーザーには全く影響がないので、やっても無駄だよ、ということでしょうか。
Deploygateからアプリをインストールするときも、インストール済みのアプリよりもバージョンコードが低いアプリを使いたいときは一旦アンインストールする必要がありますからね。

### ・ バージョンネームの方は一緒でいいのかどうなんだい？

デフォルトで設定されている `versionName` が `1.0` なのでバージョンコードと一緒に上げていく必要があるように見えますよね。
バージョンネームに関しては既存と同じでも大丈夫なようです。GooglePlayConsole上で更新可否を決める要因にはなり得ません。
例えば、**バージョンコードが既存の製品版と一緒だが、バージョンネームが異なる場合はそのビルドファイルを製品版として更新することはできません。** GooglePlayConsole側で特に重要なのはバージョンコードみたいです。

しかも、リリース前でもリリース後でもバージョンネームはGooglePlayConsole上で変更が可能ですから、なんのためにあるんでしょうか。。。
さらに、バージョンネームは文字列で指定可能なので数字である必要もありません。
極端に言えば何を設定してもいいわけですね:no_mouth:

設定された値はストアのアプリ詳細画面に表示される以下の `現在のバージョン` 部分に反映されるようです。
<img width="753" alt="スクリーンショット 2018-12-22 18.24.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/83877/6145d1b0-7de5-3821-d3e9-84f0ec3cab00.png">

さて、次は `ベータ版` や `内部テスト版` まで絡めてバージョンコードとバージョンネームの仕様を追ってみましょう！

## 3. 公開前の手動アプリテストを活用したい
デベロッパーが活用できるアプリの公開方法は４種類あります。

- 製品版トラック(製品版)
- オープントラック(ベータ版)
- クローズドトラック(アルファ版)
- 内部テスト版トラック(内部テスト版)

となっています。それぞれの使い方については以下のリンクを参考にしてもらえば十分なので省略します。
[オープンテスト版、クローズド テスト版、内部テスト版をセットアップする](https://support.google.com/googleplay/android-developer/answer/3131213?hl=ja)

この記事内で押さえておいてもらいたいのは、

**内部テスト版はアルファ版としてプロモート(リリース)でき、アルファ版はベータ版に、ベータ版は製品版にプロモート(リリース)できる**

ということです。階層を1段ずつ上がっていけるイメージです。
また、この際、**バージョンコードとバージョンネームは同じ値でプロモートされます。**
まあ、当然と言えば当然ですね。

ただ、このテスト用トラックを活用している時も不安に駆られるときがやっぱりあります。

### ・ 階層が上位のトラックにビルドを公開した場合、バージョンコードの関係によっては下位のトラックビルドが使えなくなるケースがある
アルファ版とベータ版のビルドに関しては、GooglePlayConsoleにも以下のような注釈が出てきました。
> アルファ版とベータ版の APK をテスターが使用できるようにするには、その APK のバージョン コードを製品版 APK より高い数値にする必要があります。

ただこれ、初期表示では見ることができません。(下の画像の`？`を押して初めて見れます)

逆に言えば、アルファ版やベータ版にアップロードされているビルドよりも高いバージョンコードを持ったビルドを製品版として公開すると、そのアルファ版とベータ版のビルドは使えなくなります。
<img width="975" alt="スクリーンショット 2018-12-22 19.54.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/83877/ca6df6fe-4f27-a09a-ec75-ceccf802aff3.png">

ですので、リリースがまだまだ先の機能をテストしたいようなケースでは、ある程度バージョンコードに余裕を持たせてビルドを作成しておくのも良いかもしれません。(使えなくなっても上げ直すのはそんな手間ではないですが笑)

### ・ 内部テスト版トラックにアップロードしているビルドはその他トラックのバージョンコードに関係なく残り続けるようになった？
以前までは、アルファ版やベータ版の機能と同様で、高いバージョンコードを持つビルドが上位のトラックに公開された場合、内部テスト版も同様に使えなくなっていました。
しかし、Google側で仕様の変更があったのか、現在は内部テスト版だけは高いバージョンコードを持つビルドが上位のトラックで公開されても残るようになっているようです。

また、内部テスト版をアルファ版にプロモートした際も、内部テスト版は継続して残り、使えるようです。

不死身だ、、、

この仕様のせいで、製品版よりもバージョンコードの低い内部テスト版ビルドをアルファ版にプロモートする、といったアクションができるようになっています(アルファ版の表示がすぐに製品版に置き換わったという表示になる)。

なぜなのでしょうか。とても気になって夜も眠れません。。。

## まとめ
予想よりも長くなってしまいましたが、主に重要なのはバージョンコードの管理で、バージョンネームは比較的自由に管理しても良さそうですね。
これでリリース作業の不安はほぼほぼ消えそうです！
今年の不安はなるべく消すなり忘れるなりして来年を迎えましょう！

間違った解説をしているところや、物足りないなと感じるところがあれば不安解消のためご指摘お待ちしております:bow_tone2:

ありがとうございました！