Androidプロジェクトをコマンドラインでビルドする

Androidのアプリ開発をするエンジニアは、大抵Android Studioで作業をすると思います。Android Studioはコードの編集からアプリの実行・デバッグ・ストア配布用バイナリの作成までGUIで簡単に行える素晴らしいツールです。Android Studioが使いやすすぎるので他の開発環境に行きたくないという気持ちになってしまいます。

そんなAndroid Studioにも欠点はあります。特に大規模なプロジェクトを開く時には読み込みに数分～十分以上待たされたりしますし、build.gradle(.kts)に変更を加えたりしてビルド構成が変化したときはビルドする前に一度Sync with Gradleを実行する必要があったり、ちょっとだけ不便なことはあります。
![Sync with Gradleをしている様子。](https://storage.googleapis.com/zenn-user-upload/8b2f9a45985b-20241222.png)

**「ブランチを切り替えてとりあえずビルドができるか確認したいだけなのに…」** というときに、Android Studioがビルド前に数分かけてプロジェクト読み込みをしているのを待っているのは非常に無駄な時間に思えます。

そこで、Android Studioを開かずにコマンドラインからプロジェクトをビルドする方法を知っていると、**Android Studioの待ち時間に悩まされることなくスムーズに作業をすることができるようになります。**

## Gradleについて

コマンドラインからAndroidプロジェクトをビルドする方法について説明する前に、Gradleについて軽く紹介しておきます。

Gradleは主にJavaやKotlinを使用するプロジェクトで使用されることの多いビルドツールで、Androidアプリの開発でもGradleを使ってビルド環境を整えることが多いです。Android Studioが作成するAndroidアプリケーションのプロジェクトはGradleプロジェクトになっています。Android StudioがGUIで行えるようにしている様々な処理は、実はほとんど裏でGradleのタスクを実行しているものです。逆に言えば、**Gradleを扱えるようになるとAndroid Studioが行っている処理の大半をAndroid StudioをGUIで操作せずともコマンドラインから実行できるようになる**ということです。

### ./gradlewについて

Gradleの実行コマンドは `gradle` です。普通、Gradleをインストールした場合は `gradle` コマンドで実行することになるのですが、**一般的にはこれは推奨されていません。** 代わりにGradle Wrapperという仕組みを使って、これ経由でGradleを実行することが推奨されています。

リポジトリのルートに`./gradlew` というスクリプトファイルがあります。これがGradle Wrapperです。

`./gradlew` は、 `gradle/wrapper/gradle-wrapper.properties` ファイル内に記述されたバージョンのGradleをダウンロードして実行するシェルスクリプトです。一度ダウンロードしたGradleの実行バイナリはローカルに保存されるため、次回以降の `./gradlew` コマンド実行の際はダウンロードは行われず、素早くGradleが起動します。ローカルに保存されたGradleの実行バイナリは異なるプロジェクトでも再利用できます。

Gradle Wrapperを使うことによって、プロジェクトが使用するGradleのバージョンが明確になり、使用するGradleのバージョンが違うことに起因するビルドエラーが回避できます。ということで、Gradleの実行には `gradle` コマンドよりも `./gradlew` コマンドを使う方が一般的です。以降の解説でも `./gradlew` を使ってGradleを実行するものとして説明します。

### Gradleタスクについて

Gradleを実行する際には、 `./gradlew タスク名` というふうに、実行したいタスク名を指定します。例えば以下のようなタスクがあります。

- `./gradlew build`
- `./gradlew assemble`
- `./gradlew test`

マルチモジュール構成をとっているGradleプロジェクトの場合は、 `./gradlew モジュール:タスク名` というふうにモジュールを指定してタスクを実行できます。

- `./gradlew :app:build`
- `./gradlew :libraries:hoge:assemble`

:::note
Gradleではモジュールの階層区切りに `:` を使用します。ディレクトリの区切りに `/` を使うのと同じようなモノだと思っておけば良いです。
:::

複数のタスクを実行したい時には `./gradlew タスク名1 タスク名2` のように複数書くこともできます。

- `./gradlew clean build`

他にも解説したいことはたくさんありますが、一旦ここまでにしておきます…詳しく知りたい方はGradleのドキュメントをご覧ください。

[Using Tasks](https://docs.gradle.org/current/userguide/tutorial_using_tasks.html)

## Androidアプリエンジニアが知っておくべきGradleタスク

いよいよここからが本題です。

### apk, aarをビルドする

```bash
./gradlew build
```

一番簡単なコマンドです。**これくらいは空で打てるようになりましょう。**

ほぼどんなプロジェクトでも使えて便利なコマンドなのですが、後述するコマンドと比べて必要以上のタスクを実行する場合があり、時間がかかります。ユニットテストの実行やlintの実行も含まれます。

プロジェクトによっては build で実行される全てのタスクが常に成功するようになっていなかったりしますので（製品版のビルドはCI上でのみ可能になっていたり、lintの指摘事項の対応が漏れていたり）、 `./gradlew build`によるビルドは失敗することがよくあります。

こういう時には、次のコマンドを使いましょう。

```bash
./gradlew assemble
```

こちらはbuildと違ってapkやaarといったモジュールの成果物の生成のみを行い、テストや静的解析は実行しません。メインブランチがapkやaarのビルドができない状態に陥ることはあまりないと思うので、assembleの方がbuildよりも成功する可能性が高いです。**日常的によく使うのはこっちかもしれません。**

こちらもほぼどんなプロジェクトでも使えて便利ですが、**すべてのモジュール・ビルドバリアント・ビルドタイプのapk, aarの生成を行う**ので、大規模なコードベースではやはり時間がかかります。

### モジュールを指定する

build, assembleを実行すると全てのモジュールがビルドされます。リポジトリをクローンしてきた後に実行するビルドとしては良いでしょう。しかし、普段コードを編集するときは大抵コードベースの一部分だけを変更して再ビルドをすることになると思います。その場合に手を入れていない他のモジュールにまで再ビルドを毎回実行するのは時間の無駄です。

こういう時には以下のようにして**モジュールを指定したビルドを実行する**のがおすすめです。
```
./gradlew :app:build
```
```
./gradlew :libraries:hoge:assemble
```

たとえば`libraries:hoge`のモジュールに修正を加えているのであれば、`libraries:hoge`のみをビルドすれば短時間で終了します。これによりコンパイルエラーなどが迅速に発見でき、快適に開発できます。

### ビルドタイプを指定する

Androidはデフォルトで `debug`, `release` の2種類のビルドタイプを定義しています。assembleやbuildを実行すると、これら両方のビルドを行うため、時間がかかります。**より高速にイテレーションを回すためには、debugビルドだけを作るようにするのが良いでしょう。**

:::note
releaseビルドではコンパイル時に追加の最適化が行われたりするので、debugビルドと比べて実行時間が長くなる傾向があります。普段の開発ではdebugビルドだけで検証を進め、コードが仕上がってきた段階でreleaseビルドをして最終チェックをするのが良いでしょう。
:::

以下のコマンドは、 `app` モジュールのdebugビルドのみを実行するという指定になります。

```bash
./gradlew app:assembleDebug
```

### ビルドフレーバーを指定する

- 開発環境と製品環境でAPIサーバーの向き先を変えたい
- 開発版アプリと製品版アプリを両方同一端末にインストールしたい

といった様々な理由により、多くのプロダクトではビルドフレーバーを使ってdebug, releaseの種類とは別にビルドを出し分ける設定をされていると思います。以下は開発環境・製品環境として `develop` , `production` のビルドフレーバーを定義している例です。

```kotlin
android {
    ...
    defaultConfig {...}
    // 開発環境・製品環境を出しわけるビルドバリアント
    flavorDimensions += "environment"
    productFlavors {
        create("develop") {
            dimension = "environment"
            applicationIdSuffix = ".dev"
        }
        create("production") {
            dimension = "environment"
        }
    }
}
```

このような定義をしている場合には、以下のようなコマンドで **develop フレーバーの debug ビルドのapkのみ** を生成できます。

```bash
./gradlew app:assembleDevelopDebug
```

特に複数のビルドバリアントを持つプロジェクトを扱っている場合は、Android StudioでBuild Flavorを切り替えていちいちSync with Gradleを待つよりもGradleのビルドコマンドを手打ちしてしまった方がサクッとビルドが作れて良いです。

## apkをビルドした後に端末へのインストールまで行う

apkをビルドするだけではなく端末へのインストールまで行いたい場合は、 install タスクが使えます。

```bash
./gradlew app:installDebug
```

ただ、自分の環境では install コマンドが端末へのインストール時点でなぜか失敗することが多かったので、あまり使わなくなりました…

## おわりに

コマンドラインからビルドできるようになればAndroidアプリの開発がより快適になるでしょう。また、GitHub ActionsなどのCI環境を整える際にも役立ちます。

他にもこんなコマンドが便利だよとかありましたらコメントで教えてください。