Android Gradle Version Catalog | By Gopal

Gopal
5 min readDec 23, 2023

--

As our projects grow, managing dependencies becomes a challenge. Consistency and avoiding version conflicts are crucial for stable builds. Gradle Version Catalogs — a solution to simplify this task.

In this article, we’ll explore what Gradle Version Catalogs are, why they’re essential, how to set them up, and their use in other projects.

What is a Version Catalog

Introduced in Gradle 7.0 by the Gradle team, the Android Gradle Version Catalog enables you to add and maintain dependencies and plugins in a scalable way. Using Gradle version catalogs makes managing dependencies and plugins easier when you have multiple modules.

Instead of hardcoding dependency names and versions in individual build files and updating each entry whenever you need to upgrade a dependency, you can create a central version catalog of dependencies that various modules can reference in a type-safe way with Android Studio assistance.

💡 Update: Android Version Catalog has become default for new project since Android Studio Hedgehog. If you want a sample Version Catalog template, just create a new project, and you will have it.

Benefits of Android Version Catalogs

  1. Centralized Management: All the dependencies and their versions are kept in one place, making it easier to manage and update them.
  2. Consistency Across Projects: By sharing the same version catalog, all projects can ensure they are using the same versions of dependencies, reducing the likelihood of conflicts.
  3. Conflict-free dependencies
    Version catalog eradicates the conflict between the dependencies which is consumed across the modules
  4. Type-safe dependency declarations
    When you declare dependencies in a version catalog, you can use type-safe syntax. This helps to prevent errors and makes it easier to read and understand your build scripts.
  5. Support for bundles
    A version catalog can also support bundles, which allow you to group a set of dependencies. This can be useful for organizing your dependencies and making it easier to upgrade them.
  6. Scalability
    Scales effectively with larger projects and multiple modules.
  7. Library version Update Hints
    It gives you a hint if there is any update available in any library.

How to Set Up a Gradle Version Catalog

  1. Since the Version catalog became stable in Gradle version 7.4+, upgrade your Gradle version to 7.4+ to access the stability and benefits of the Version Catalog introduced in this release.
  2. Create libs.versions.toml under gradle/wrapper directory. Gradle looks for the catalog in the libs.versions.toml file by default, so it is recommended to use this default name.
    The .toml file extension indicates that the file is written in the TOML (Tom's Obvious, Minimal Language) format, which is easy to read and write.

Version Catalog File and Structuring

In your libs.versions.toml file, add these 4 sections

[versions]

[libraries]

[bundles]

[plugins]

1. [versions]: This section is used to define version numbers for your dependencies and plugins. By defining versions here, you can easily update them in one place when needed.

2. [libraries]: Here, you define your project's dependencies. Instead of specifying the version directly, you reference the version defined in the [versions] section.

3. [plugins]: Similar to the [libraries] section, this section is for defining your project's plugins, referencing the versions from the [versions] section.

4. [bundles]: This section allows you to group several dependencies. This is useful when multiple dependencies are used together frequently.

Note: If names in .toml file is in kebab-case or snake_case , when we refer them in our Gradle build scripts, they all get normalised to . so we have to change them to . there. For example, if we definecompose-ui , it will become libs.compose.ui when we call it.

[versions]
agp = "8.1.4"
org-jetbrains-kotlin-android = "1.8.10"
core-ktx = "1.9.0"
junit = "4.13.2"
androidx-test-ext-junit = "1.1.5"
activity-compose = "1.8.1"
rxJava = '2.2.21'
rxAndroid = '2.1.1'

[libraries]
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-test-ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-ext-junit" }
reactivex-rxjava2-rxjava = { module = "io.reactivex.rxjava2:rxjava", version.ref = "rxJava" }
reactivex-rxjava2-rxandroid = { module = "io.reactivex.rxjava2:rxandroid", version.ref = "rxAndroid" }

[plugins]
com-android-application = { id = "com.android.application", version.ref = "agp" }
org-jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "org-jetbrains-kotlin-android" }

[bundles]
rxjava = ["reactivex-rxjava2-rxandroid", "reactivex-rxjava2-rxjava"]

Here’s how you can incorporate the TOML file into any module of your choice.

@Suppress("DSL_SCOPE_VIOLATION")
plugins {
alias(libs.plugins.com.android.application)
alias(libs.plugins.org.jetbrains.kotlin.android)
}

android {
namespace = "com.example.versioncataloguetest"
compileSdk = libs.versions.compileSdkVersion.get().toInt()

defaultConfig {
applicationId = "com.example.versioncataloguetest"
minSdk = libs.versions.minSdkVersion.get().toInt()
targetSdk =libs.versions.targetSdkVersion.get().toInt()
versionCode = 1
...
}
}

dependencies {
implementation(libs.core.ktx)
implementation(libs.lifecycle.runtime.ktx)
implementation(libs.activity.compose)

//Including bundles
implementation(libs.bundles.rxjava)
debugImplementation(libs.ui.test.manifest)
}

Now to include the plugin correctly, in your project's module you have to define each plugin in project level gradle file as apply false.

The apply false suffix is used to prevent the plugin from being applied to the current module. This is useful when you want to apply a plugin to a specific module, but not to the entire project.

Note: If you are using a version of Gradle below 8.1, you need to annotate the plugins{} block with @Suppress("DSL_SCOPE_VIOLATION") when using version catalogs. Refer to issue #22797 or Known Bugs for more info.

@Suppress("DSL_SCOPE_VIOLATION")
plugins {
alias(libs.plugins.com.android.application) apply false
alias(libs.plugins.org.jetbrains.kotlin.android) apply false
}

Extended Usage

  1. We can also move the minSdk and targetSdk to version catalog, like we did in the above example.
  2. Receive project update suggestions in the Android Studio Project Structure tab, allowing for effortless modification of dependencies.

You can find an example of this code in my GitHub Repository

Conclusion

Developers might question the choice between version catalogs and buildSrc, which relies on Kotlin for managing Gradle scripts. The distinction arises because, with buildSrc, updating a dependency initiates a complete project build, resulting in extended build times — particularly noticeable in projects with numerous modules. On the other hand, version catalogs facilitate updating dependencies without necessitating a complete project rerun.

However, it is important to note that using Gradle Version Catalog doesn’t limit you to this approach alone. You can still directly specify versions of dependencies and plugins if needed for your project.

Additionally, version catalogs are shareable with other projects, which simplifies dependency management when starting new projects and saves development time.

Thank you for reading this post, I hope this was helpful to you, you can view all the code from my GitHub Repository.

Leave a comment below if you have any questions I will try to answer them to the best of my knowledge.

Follow me on LinkedIn, Medium, and Github✌️

--

--