How to add Version Catalog to your Android App?
Tags: android, kotlin, gradle, beginners
Published: 2023-01-06 23:00:00

**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](https://vtsen.hashnode.dev/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.

- [How to Convert Android Gradle Groovy to KTS?](https://vtsen.hashnode.dev/how-to-convert-android-gradle-groovy-to-kts) 

## 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.

```ini
[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.

```ini
[bundles]
android-gradle-plugin = ["android-application", "android-library"]
```

## 3\. Update the plugins block

**build.gradle.kts (root / project level)**

Replace

```kotlin
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

```kotlin
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

```kotlin
plugins {
    id ("com.android.application")
    id ("org.jetbrains.kotlin.android")
}
```

with

```kotlin
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](https://youtrack.jetbrains.com/issue/KTIJ-19369). 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.

```kotlin
@Suppress("DSL_SCOPE_VIOLATION")
plugins {
    /*...*/
}

//Workaround for "Expecting an expression" build error
println("")
```

## 4\. Update kotlinCompilerExtensionVersion

Instead of hard coding `kotlinCompilerExtensionVersion`

```kotlin
composeOptions { 
    kotlinCompilerExtensionVersion = "1.2.0" 
}
```

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

```kotlin
composeOptions {
    kotlinCompilerExtensionVersion = libs.versions.androidxComposeCompiler.get()
}
```

## 5\. Update library dependencies

**Example 1 - Single library**

```kotlin
dependencies { 
    implementation("androidx.core:core-ktx:1.8.0") 
}
```

is replaced with

```kotlin
dependencies {
    implementation(libs.androidx.core.ktx) 
}
```

**Example 2 - Multiple libraries**

```kotlin
dependencies { 
    val lifeCycleVersion = "2.5.1" 
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifeCycleVersion") 
    implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifeCycleVersion") 
}
```

are replaced with

```kotlin
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)](https://github.com/vinchamp77/Demo_CleanEmptyCompose/tree/master_vercatalog)

Convert to Version Catalog: [diff](https://github.com/vinchamp77/Demo_CleanEmptyCompose/compare/c4a7296c35e4ba953c53b589c793b81ac1fa05df..af1635c09ba3040f025bed720ef2ef0e80c68ccb)

---

*Originally published at [https://vtsen.hashnode.dev](https://vtsen.hashnode.dev/how-to-add-version-catalog-to-your-android-app)*.