DEV Community

Cover image for How to add Version Catalog to your Android App?
Vincent Tsen
Vincent Tsen

Posted on • Edited on • Originally published at vtsen.hashnode.dev

How to add Version Catalog to your Android App?

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"]
Enter fullscreen mode Exit fullscreen mode
  • [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"]
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

with

plugins { 
    alias(libs.plugins.android.application) apply false 
    alias(libs.plugins.android.library) apply false 
    alias(libs.plugins.kotlin.android) apply false 
}
Enter fullscreen mode Exit fullscreen mode

app\build.gradle.kts (app / module level)

Replace

plugins {
    id ("com.android.application")
    id ("org.jetbrains.kotlin.android")
}
Enter fullscreen mode Exit fullscreen mode

with

plugins { 
    alias(libs.plugins.android.application) 
    alias(libs.plugins.kotlin.android) 
}
Enter fullscreen mode Exit fullscreen mode

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("")
Enter fullscreen mode Exit fullscreen mode

4. Update kotlinCompilerExtensionVersion

Instead of hard coding kotlinCompilerExtensionVersion

composeOptions { 
    kotlinCompilerExtensionVersion = "1.2.0" 
}
Enter fullscreen mode Exit fullscreen mode

use libs.vesions.compose which you defined androidxComposeCompiler in the [versions] section in libs.versions.toml file

composeOptions {
    kotlinCompilerExtensionVersion = libs.versions.androidxComposeCompiler.get()
}
Enter fullscreen mode Exit fullscreen mode

5. Update library dependencies

Example 1 - Single library

dependencies { 
    implementation("androidx.core:core-ktx:1.8.0") 
}
Enter fullscreen mode Exit fullscreen mode

is replaced with

dependencies {
    implementation(libs.androidx.core.ktx) 
}
Enter fullscreen mode Exit fullscreen mode

Example 2 - Multiple libraries

dependencies { 
    val lifeCycleVersion = "2.5.1" 
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifeCycleVersion") 
    implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifeCycleVersion") 
}
Enter fullscreen mode Exit fullscreen mode

are replaced with

dependencies { 
    implementation(libs.bundles.androidx.lifeycle) 
}
Enter fullscreen mode Exit fullscreen mode

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)