Step-by-step guide to implement Version Catalog (a dependency management tool developed by Gradle team) into your Android app
Version Catalog is a dependency management tool developed by the Gradle team. The benefit of using it is you don't need to hard code the version in multiple places, especially if you have a multi-modules project.
This article provides a step-by-step guide to integrating Version Catalog into your Android app using Android Studio. The example is based on this clean empty Jetpack Compose app template.
1. Upgrade Gradle Version
The minimum Gradle version requirement to run Version Catalog is 7.4. However, version 7.4.2 contains the latest fixes.
In the terminal, check your Gradle version.
./gradlew -version
If it is less than 7.4.2, upgrade it.
./gradlew wrapper --gradle-version 7.4.2
After running the above command, the .\wrapper\gradle-wrapper.jar
, .\wrapper\gradle-wrapper.properties
and .\build.gradle.kts
are updated.
If you're curious about *.kts, it is a Gradle Kotlin Script. For more information, you can refer to this blog post.
2. Create libs.versions.toml
Create this .\gradle\libs.versions.toml
file. Please make sure you name it correctly. I named it wrongly at first, and it took me a while to figure that out.
An example of libs.versions.toml
looks like this.
[versions]
androidGradlePlugin = "7.3.0"
androidxCore = "1.8.0"
androidxComposeCompiler = "1.2.0"
[plugins]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" }
[libraries]
androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidxCore" }
androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidxLifecycle" }
androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidxLifecycle" }
[bundles]
androidx-lifeycle = ["androidx-lifecycle-runtime-ktx", "androidx-lifecycle-viewmodel-compose"]
[versions]
- declare versions that are referenced by[plugins]
and[libraries]
[plugins]
- define a set of plugins with version[libraries]
- define a set of library dependencies with version[bundles]
- combine multiple libraries into a single reference
[bundles]
works only with libraries. It won't work for plugins. For example, the following won't work.
[bundles]
android-gradle-plugin = ["android-application", "android-library"]
3. Update the plugins block
build.gradle.kts (root / project level)
Replace
plugins {
id("com.android.application") version "7.2.2" apply false
id("com.android.library") version "7.2.2" apply false
id("org.jetbrains.kotlin.android") version "1.7.0" apply false
}
with
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.kotlin.android) apply false
}
app\build.gradle.kts (app / module level)
Replace
plugins {
id ("com.android.application")
id ("org.jetbrains.kotlin.android")
}
with
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
}
It compiles and runs fine, but you can still see the following errors.
val Project.libs: LibrariesForLibs' can't be called in this context by implicit receiver. Use the explicit one if necessary
It looks like a known bug here. To get rid of this error, you can add @Suppress("DSL_SCOPE_VIOLATION")
[Updated - Jan 2, 2023]: If you get the "Expecting an expression" build error, you want to add this
println("")
at the end of the file as a workaround.
@Suppress("DSL_SCOPE_VIOLATION")
plugins {
/*...*/
}
//Workaround for "Expecting an expression" build error
println("")
4. Update kotlinCompilerExtensionVersion
Instead of hard coding kotlinCompilerExtensionVersion
composeOptions {
kotlinCompilerExtensionVersion = "1.2.0"
}
use libs.vesions.compose
which you defined androidxComposeCompiler
in the [versions]
section in libs.versions.toml file
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.androidxComposeCompiler.get()
}
5. Update library dependencies
Example 1 - Single library
dependencies {
implementation("androidx.core:core-ktx:1.8.0")
}
is replaced with
dependencies {
implementation(libs.androidx.core.ktx)
}
Example 2 - Multiple libraries
dependencies {
val lifeCycleVersion = "2.5.1"
implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifeCycleVersion")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifeCycleVersion")
}
are replaced with
dependencies {
implementation(libs.bundles.androidx.lifeycle)
}
Current Issue
The major issue with Version Catalog in my opinion is it won't prompt you the message when there is a new version of the library. For example:
A newer version of
androidx.core:core-ktx
than 1.8.0 is available: 1.9.0
There is a third-party library here, but I think it still requires you to manually run the Gradle command.
[Updated - Feb 17, 2024]: Tried latest Android Studio Hedgehog, the auto-detecting new version seems to be working now. However, it reports the wrong warnings for unused libraries. For example:
"Version reference 'androidxComposeCompiler' is not used in build scripts"
Well, it is used in my app\build.gradle.kts.
"Dependency alias 'androidx-lifecycle-runtime-compose' is not used in build scripts"
Well, it is used too in the bundles that I defined in libs.versions.toml which is used by the \build.gradle.kts.
Source Code
GitHub Repository: Demo_CleanEmptyCompose(master_vercatalog branch)
Convert to Version Catalog: diff
Originally published at https://vtsen.hashnode.dev.
Top comments (0)