GradleのVersion catalogでAndroidアプリのライブラリを管理する

KARASTAのAndroidエンジニアをしているoidyです。
マルチモジュール構成のAndroidアプリを開発する際、どのようにライブラリのバージョンを一元化するかが一つの課題になります。
依存関係をモジュール間で共有する手法として、Gradleのext
やbuildSrc
を使う方法がよく見られます。
この記事では、Gradle v7.0からfeature previewとして導入されているVersion catalogを使って依存関係を管理する方法を紹介します。
アプリのマルチモジュール化に関しては以前の投稿も是非ご覧ください。
従来の方法
ext
で管理する
プロジェクトのbuild.gradle
のext
ブロックで依存関係を管理する例を示します。
buildscript {
ext.versions = [
app : [
versionCode: 1,
versionName: "1.0.0"
],
android : [
compileSdk: 31,
targetSdk : 31,
minSdk : 21,
gradle : "7.0.0"
],
kotlin : [
gradle : "1.6.10",
coroutines: "1.5.2"
],
androidx: [
core : "1.7.0",
lifecycle: "2.4.0"
]
]
ext.libs = [
kotlin : [
coroutines: "org.jetbrains.kotlinx:kotlinx-coroutines-android:$versions.kotlin.coroutines"
],
androidx: [
core: "androidx.core:core-ktx:$versions.androidx.core",
lifecycle: [
liveData : "androidx.lifecycle:lifecycle-livedata-ktx:$versions.androidx.lifecycle",
viewModel: "androidx.lifecycle:lifecycle-viewmodel-ktx:$versions.androidx.lifecycle"
]
]
]
ext.gradlePlugins = [
android: "com.android.tools.build:gradle:$versions.android.gradle",
kotlin : "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlin.gradle"
]
repositories {
google()
mavenCentral()
}
dependencies {
classpath gradlePlugins.android
classpath gradlePlugins.kotlin
}
}
モジュールのbuild.gradle
からは以下のように参照できます。
android {
compileSdk versions.android.compileSdk
defaultConfig {
minSdk versions.android.minSdk
targetSdk versions.android.targetSdk
versionCode versions.app.versionCode
versionName versions.app.versionName
}
}
dependencies {
implementation libs.kotlin.coroutines
implementation libs.androidx.core
implementation libs.androidx.lifecycle.liveData
implementation libs.androidx.lifecycle.viewModel
}
buildSrc
で管理する
Gradle Kotlin DSLを導入しているプロジェクトではbuildSrc
でライブラリを管理していることが多いと思います。
上記のext
と同等の依存関係を定義するためのbuildSrc
の記述を以下に示します。
object Versions {
object App {
const val versionCode = 1
const val versionName = "1.0.0"
}
object Android {
const val compileSdk = 31
const val targetSdk = 31
const val minSdk = 21
const val gradle = "7.0.0"
}
object Kotlin {
const val gradle = "1.6.10"
const val coroutines = "1.5.2"
}
object AndroidX {
const val core = "1.7.0"
const val lifecycle = "2.4.0"
}
}
object Libs {
object Kotlin {
const val coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.Kotlin.coroutines}"
}
object AndroidX {
const val core = "androidx.core:core-ktx:${Versions.AndroidX.core}"
object Lifecycle {
const val liveData = "androidx.lifecycle:lifecycle-livedata-ktx:${Versions.AndroidX.lifecycle}"
const val viewModel = "androidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.AndroidX.lifecycle}"
}
}
}
object GradlePlugins {
const val android = "com.android.tools.build:gradle:${Versions.Android.gradle}"
const val kotlin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.Kotlin.gradle}"
}
モジュールのbuild.gradle
からは以下のように参照できます。
android {
compileSdk Versions.Android.compileSdk
defaultConfig {
minSdk Versions.Android.minSdk
targetSdk Versions.Android.targetSdk
versionCode Versions.App.versionCode
versionName Versions.App.versionName
}
}
dependencies {
implementation Libs.Kotlin.coroutines
implementation Libs.AndroidX.core
implementation Libs.AndroidX.Lifecycle.liveData
implementation Libs.AndroidX.Lifecycle.viewModel
}
Version catalogを使う
Version catalogは現時点(Gradle v7.3.2)でfeature previewです。settings.gradle
に以下の行を追加するとVersion catalogが使えるようになります。
enableFeaturePreview("VERSION_CATALOGS")
次に、プロジェクトのgradle/
の下にlibs.versions.toml
という名前のファイルを置きます。
tomlファイルの内容は以下のようになります。
[versions]
app-versionCode = "1"
app-versionName = "1.0.0"
android-compileSdk = "31"
android-targetSdk = "31"
android-minSdk = "21"
android-gradle = "7.0.0"
kotlin = "1.6.10"
kotlin-coroutines = "1.5.2"
androidx-core = "1.7.0"
androidx-lifecycle = "2.4.0"
[libraries]
android-gradle = { module = "com.android.tools.build:gradle", version.ref = "android-gradle" }
kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlin-coroutines" }
androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
androidx-lifecycle-viewModel = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidx-lifecycle" }
androidx-lifecycle-liveData = { module = "androidx.lifecycle:lifecycle-livedata-ktx", version.ref = "androidx-lifecycle" }
[versions]
の下にバージョンを、[libraries]
の下にライブラリを定義します。
モジュールのbuild.gradle
からは以下のように参照できます。
android {
compileSdk libs.versions.android.compileSdk.get().toInteger()
defaultConfig {
minSdk libs.versions.android.minSdk.get().toInteger()
targetSdk libs.versions.android.targetSdk.get().toInteger()
versionCode libs.versions.app.versionCode.get().toInteger()
versionName libs.versions.app.versionName.get()
}
}
dependencies {
implementation libs.kotlin.coroutines
implementation libs.androidx.core
implementation libs.androidx.lifecycle.viewModel
implementation libs.androidx.lifecycle.liveData
}
Version catalogのバージョンにはStringしか定義できないため、compileSdk
やminSdk
をVersion catalogから取得する場合はtoInteger()
をする必要があります。
dependencies
ブロックは前述のext
を使った場合と全く同じように書けます。
複数のライブラリを1行にまとめる
「ライブラリAを使うときはライブラリBも必ず使う」といったケースがよくあります。
Androidアプリの開発においては
- テストを書くときにRobolectricとMockitoを一緒に使う
- Jetpack Composeを使うときにComposeのライブラリ群(material, ui-toolingなど)を一緒に使う
といった例が挙げられます。
Version catalogにはこのような複数のライブラリを1つのバンドルとしてまとめる機能があります。
バンドルを定義するには、tomlファイルに[bundles]
セクションを追加します。
次の例では viewModel
と liveData
をバンドル化しています。
[libraries]
androidx-lifecycle-viewModel = ...
androidx-lifecycle-liveData = ...[bundles]
androidx-lifecycle = ["androidx-lifecycle-viewModel", "androidx-lifecycle-liveData"]
bundlesを参照するにはlibs.bundles.[名前]
のようにします。
まとめる前dependencies {
implementation libs.androidx.lifecycle.viewModel
implementation libs.androidx.lifecycle.liveData
}まとめた後dependencies {
implementation libs.bundles.androidx.lifecycle
}
Gradleプラグインを管理する
Android Studio Bumblebee以降では、プロジェクトを新規作成したときのbuild.gradle
が少し変わりました。
repository
の設定はbuild.gradle
からsettings.gradle
に移動し、Gradleプラグインはclasspath
を記述する方法からplugins
ブロックにIDとバージョンを指定する方法に変わっています。
plugins {
id "org.jetbrains.kotlin.android" version "1.6.10" apply false
id "com.android.application" version "7.0.0" apply false
id "com.android.library" version "7.0.0" apply false
}
このプラグインIDとバージョンをVersion catalogを使って管理するには、tomlファイルに[plugins]
のセクションを追加します。
[versions]
kotlin = "1.6.10"
android-gradle = "7.0.0"[plugins]
kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
android-application = { id = "com.android.application", version.ref = "android-gradle" }
android-library = { id = "com.android.library", version.ref = "android-gradle" }
これを参照するには alias(libs.plugins.[名前])
のようにします。
plugins {
alias(libs.plugins.kotlin) apply false
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false
}
Androidアプリの開発で使われるGradleプラグインの多くはplugins
ブロックでの記法に対応しています。
- Kotlin Serialization
- Google Services
- Firebase Crashlytics
- Navigation Safe Args
[plugins]
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
google-services = { id = "com.google.gms.google-services", version.ref = "google-services" }
firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebase-crashlytics" }
androidx-navigation = { id = "androidx.navigation.safeargs", version.ref = "androidx-navigation" }
Hiltは現時点では対応していませんが、このような方法をとればplugins
ブロックに記述できます。
従来のclasspath
を設定する方法でも問題なく動くので、プラグイン側の対応を待っても良いでしょう。
まとめ
Version catalogを導入するとプロジェクトで使うライブラリのバージョンを簡単に一元管理できます。
従来の方法と比較すると、buildSrc
を使う方法よりも導入コストが低く、ext
を使う方法よりもGradle Kotlin DSLで扱いやすいといった利点があります。
バンドル化やプラグイン管理といったVersion catalogならではの便利な機能もあります。
現時点ではfeature previewですが、Gradleの標準的なライブラリの管理方法として今後広く使われていくと思われます。