はじめに
株式会社ジャンボでAndroidエンジニアをしています。入社後からAndroid開発に長く携わっていますが、毎日のように触れるGradleについてちゃんと理解していないなと実務の中で感じたので、改めてGradleって何なのかを学び直してみようと思いこの記事を投稿しました。
targetSdk, minSdk, compileSdkだったりbuild.gradleってなんで複数個あるかなどなんとなくの理解で触っていた基礎的な部分についてまとめてみたので初学者からちゃんと理解せず開発をしていた方になにか学びになることがあると嬉しいです。
Gradleとはなんなのか
まずはAndroidアプリがどのようにビルドされるのかを理解することでGradleがどのようなものなのかを理解しやすくしてみます。
AndroidアプリにはKotlinソースコード、リソースファイル(xml, 画像)、AndroidManifest.xml、依存ライブラリなどの要素から成り立っており、最終的にこれらをAPKまたはAABというファイルに変換します。
Gradleはこれらの変換作業を自動化するためのビルドシステムとして動作します。
GradleとAGP(Android Gradle Plugin)の関係
Android開発をするうえで切っても切り離せないのがAGPです。AGPとはGradle上で動くプラグインで、Androidをビルドするためのタスクとお作法を提供します。
つまりGradleはアプリをビルドするための一連の手順を管理するツールで、AGPはAndroid向けのプラグインやリソースの処理を担当する拡張機能です。
Gradle Wrapper
チーム開発を行う際に開発者ごとにGradleのバージョンが異なっていると、ビルド実行したときに異なる挙動になってしまい、事故につながる恐れがあります。
Gradle Wrapperを使うことで、Gradleバージョンを自動的に揃えることができます。
gradle-wrapper.propertiesは以下のように定義されています。
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
重要なのはdistributionUrlのGradleバージョンで、これを変更することでプロジェクト内で使用するGradleバージョンを統一できます。
Androidプロジェクトのファイル構成
ここでAndroidのビルドに関連するファイルの構成とそれぞれの役割についてツリー化してみます。
MyApp/
├── settings.gradle.kts どのモジュールを含めるか宣言
├── build.gradle.kts トップレベルビルドファイル
├── gradle.properties Gradle自体の設定
├── local.properties ローカル環境固有の設定(gitignore対象)
├── gradle/
│ ├── wrapper/
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
│ └── libs.versions.toml バージョンカタログ(後述)
├── gradlew, gradlew.bat
└── app/ ← アプリ本体のモジュール
├── build.gradle.kts モジュールレベルビルドファイル
└── src/
├── main/
│ ├── java/ または kotlin/
│ ├── res/
│ └── AndroidManifest.xml
├── test/ ユニットテスト(JVMで実行)
└── androidTest/ インスツルメンテーションテスト(端末/エミュで実行)
主な役割は以下のとおりです。
| ファイル | 役割 |
|---|---|
| settings.gradle.kts | プロジェクト全体の設定。どのモジュールを含めるか宣言 |
| ルートの build.gradle.kts | プロジェクト全体で使うプラグインのバージョン定義(ここではプラグインを適用しない) |
| app/build.gradle.kts | モジュール固有の設定、SDKバージョン、依存関係など |
| gradle.properties | Gradleデーモンのメモリ設定など |
| local.properties | ローカルマシン固有のパスなど。git管理はしない |
settings.gradle.kts
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "My Application"
include(":app")
各ブロックでなにをしているか
pluginManagement { repositories { ... } }
プラグイン本体をどこから取ってくるかを宣言します。AGPなどのプラグインを探しに行く場所です。
-
gradlePluginPortal()→ Gradle公式のプラグイン置き場 -
google()→ Google Mavenリポジトリ(AGPはここにある) -
mavenCentral()→ Maven Central
dependencyResolutionManagement { repositories { ... } }
依存ライブラリ(AndroidX、Retrofitなど)をどこから取ってくるかを宣言します。
include(":app")
「appというモジュールをビルドに含める」という宣言です。マルチモジュール構成にすると include(":app", ":core", ":feature:login") のように増えていきます。
ルートの build.gradle.kts
プロジェクト全体で使うプラグインのバージョンを宣言する場所です。ここでは「どのプラグインを、どのバージョンで使うか」を定義するだけで、実際にプラグインを適用(apply)するのは各モジュールのbuild.gradle.kts側です。
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
}
apply falseを付けることで、「このプラグインはルート側では適用せず、モジュール側で適用する」という意味になります。これによりプラグインのクラスパス解決はルートで一度だけ行い、各モジュールで実際に有効化する形になります。
app/build.gradle.kts(モジュールレベル)
appモジュール固有の設定を記述するファイルです。SDKバージョン、署名設定、ビルドバリアント、依存ライブラリなど、アプリのビルドに関わる大半の設定はここに書きます。
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
}
android {
namespace = "com.example.myapp"
compileSdk = 35
defaultConfig {
applicationId = "com.example.myapp"
minSdk = 24
targetSdk = 35
versionCode = 1
versionName = "1.0"
}
buildTypes {
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
}
compileSdk / minSdk / targetSdk の違い
似た名前で混乱しやすいですが、それぞれ役割が明確に分かれています。
| 項目 | 役割 |
|---|---|
compileSdk |
コンパイル時に参照するAndroid SDKのバージョン。最新APIを使いたければここを上げる。 |
minSdk |
アプリが動作する最低のOSバージョン。これより古い端末にはインストールできない。 |
targetSdk |
アプリが動作確認済みとして宣言するバージョン。OS側の互換動作の挙動に影響する。 |
compileSdkは常に最新、targetSdkもできるだけ最新に追従、minSdkはサポート対象の最低バージョンに合わせる、というのが基本的な運用方針になります。
gradle.properties
Gradle自体の挙動をプロジェクト単位で設定するファイルです。主にビルドパフォーマンスに関する設定を記述します。
org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
org.gradle.parallel=true
org.gradle.caching=true
android.useAndroidX=true
kotlin.code.style=official
-
org.gradle.jvmargs→ Gradleデーモンに割り当てるJVMのメモリ。プロジェクトが大きくなるとここを増やす必要が出てくる。 -
org.gradle.parallel→ モジュールを並列にビルドする設定。マルチモジュール構成で効果が大きい。 -
org.gradle.caching→ ビルドキャッシュを有効化し、変更のないタスクの再実行をスキップする。
git管理対象なので、チーム全員に共通の設定をここに置きます。
local.properties
個々の開発マシン固有の情報を書くファイルで、.gitignoreで除外されます。代表的なのはSDKのパスです。
sdk.dir=/Users/yourname/Library/Android/sdk
APIキーやデバッグ用の認証情報など、リポジトリにコミットしたくない値を一時的に置く用途でも使われます。BuildConfig経由で参照することで、ソースコードに機密情報を埋め込まずに済みます。
libs.versions.toml(バージョンカタログ)
Gradle 7.4以降で導入された依存関係とプラグインのバージョンを一元管理する仕組みです。gradle/libs.versions.tomlに記述し、各モジュールからlibs.xxxという形で参照します。
[versions]
agp = "8.5.0"
kotlin = "2.0.0"
coreKtx = "1.13.1"
appcompat = "1.7.0"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
-
[versions]→ バージョン番号の定義 -
[libraries]→ ライブラリ本体の定義(versions側をversion.refで参照) -
[plugins]→ プラグインの定義
これにより、複数モジュールで同じライブラリを使っていてもバージョン定義は1箇所で済み、アップデート時の漏れを防げます。IDE上での補完が効くのも大きなメリットです。
まとめ
今回はGradleを「ちゃんと理解する」ための入り口として、Androidプロジェクトに含まれる各種Gradle関連ファイルの役割を一つずつ整理しました。まとめると以下のとおりです。
- Gradleはビルドシステム本体であり、AGPはその上で動くAndroid向けプラグイン
-
gradle-wrapperを使うことでチーム内のGradleバージョンを揃えられる - ビルド設定は 「プロジェクト全体に効くもの」と「モジュール固有のもの」 に分かれて配置されている
-
settings.gradle.ktsはモジュールの宣言とリポジトリの定義、build.gradle.kts(ルート)はプラグインのバージョン宣言、app/build.gradle.ktsはモジュール固有の設定 -
libs.versions.tomlを使うことで依存関係のバージョンを一元管理できる
それぞれのファイルが「なぜそこに存在するのか」がわかると、build.gradle.ktsを編集する際の迷いがだいぶ減るはずです。
次回は今回触れなかった**Gradleの実行モデル(タスクとビルドライフサイクル)**について書こうと思います。
最後に
株式会社ジャンボでは、一緒に働くエンジニアを募集しています!
少しでも興味がある方は、ぜひカジュアル面談でお話しましょう!
