Hey! Welcome to Since Last Commit. A publication where I highlight all of my learnings while building Android applications. These days, I am building the Hangar app. More about that at the end of the post.
Working with dependencies is one of the core experiences of Android development. As a project grows, the app requires more dependencies to satisfy the feature requirements. Managing these dependencies can be a pain. An outdated dependency could lead to a lot of problems with security, performance and potential bugs. However, managing these dependencies at a larger scale can make it very challenging to stay focused and organized.
While I was working on the Hangar Android app, I came across an article that spoke about Version Catalog being introduced to Android development. In essence, dependencies can now be defined in a centralized place that can be referenced in any of the build.gradle files. This is a step up from manually updating the hard-coded dependency version in the build.gradle files for each module. This could be painful if an app has a large number of modules. Although the Hangar app does not support multi-modules yet, I gave it a try to see how they work. Even with a simple app, I found it to be a cleaner and centralized approach for managing dependencies.
Text within this block will maintain its original spacing when published
As a side note, it feels like dependencies andbuild.gradlefiles have always remained the same throughout the years. However, changes like Version Catalog and Kotlin DSL, there seems to be a new way how projects could be structured in the future. With this project, I am planning to migrating mybuild.gradlefile from groovy to Kotlin and adding support to Version Catalog.
So what is Version Catalog, you might ask. It is a simple .toml file that needs to be added to a specific path in your project that defines all of your versions, libraries and plugins. Using the defined name and path as the documentation suggests, Gradle will automatically start using that .toml file in your build process. A .toml file is basically a minimal configuration file that organizes the dependency that any build.gradle file could use. More about that later, let’s start with the basics.
As mentioned, a .toml file is a minimal configuration file that ends with the .toml file extension. In a basic view, it is basically a series of keys and values with native types such as arrays and tables.
A simple definition and comment would look like
# This is how a key and value are defined.
some-key = “some value” # Comments can be added here as well As noted in the developer documentation, the recommended naming conventions for the key are kebab-case.
In addition, tables are also supported which are a series of key and value pairs. Table are defined as
[my-table]
my-key = “my value”
your-key = “your valueNext, inline tables are also useful for expressing tables in a compact way. Example of an inline table is
my-table = { my-key = "my value", your-key = "your value" }
# The following inline table could be expressed in the table definition below.
[my-table]
my-key = "my value"
your-key = "your value"Back to Android development. To leverage Version Catalog, we have to represent a given dependency in the TOML structure. For simplicity, we will create a new file with the default name. So go ahead and create libs.versions.toml file in the root Gradle folder in your project. Gradle will automatically use that file when there is any reference in the build.gradle file.
We will have three sections that will represent our dependencies: versions, libraries and plugins. The version block will have the corresponding version of a dependency, such as the version code. The libraries will reference the library name. The plugins simply reference the plugin name that we will use in the project.
An example of how the libs.versions.toml could look like for you
[versions]
core = "1.10.1"
android = "8.1.0"
[libraries]
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core" }
[plugins]
android-application = { id = "com.android.application", version.ref = "android" }
android-library = { id = "com.android.library", version.ref = "android" }
A typo in any versions or version.ref will result in a build time error.
Once we have our libs.versions.toml file structured, next is the reference in the build.gradle(root) and build.gradle(app) file respectively.
plugins {
alias libs.plugins.android.application apply false
alias libs.plugins.android.library apply false
}plugins {
alias libs.plugins.android.application
alias libs.plugins.kotlin.android
}
dependencies {
implementation libs.core.ktx
}
Notice how the dashes in the TOML file are replaced by dots when being referenced in the build.gradle file.
The one question I had when I was playing around with Version Catalog is how can I break it down to different files. Eventually, the libs.versions.toml could get very large and messy. Although I am not sure if this is best practice or not, but in my project I decided to give it a try to have multiple TOML files. Although I am not sure if this is best practice or not, I decided to give it a try. The thought I had was to divide the TOML file into its use case. This meant creating a separate TOML file for the core, unit testing, instrumentation testing and data related dependencies. So I ended up having 4 .toml files named as
libs.versions.toml
data.versions.toml
tests.versions.toml
android.tests.versions.toml
Creating a TOML file that does not have a specific name will manually need to be added to the Gradle settings. So in the settings.gradle file in the root of the project, I added the reference to these files in the dependencyResolutionManagement block under the versionCatalogs definition. An example can be found below.
dependencyResolutionManagement {
…
versionCatalogs {
create("dataLibs") {
from(files("./gradle/data.versions.toml"))
}
create("testLibs") {
from(files("./gradle/tests.versions.toml"))
}
create("androidTestLibs") {
from(files("./gradle/android.tests.versions.toml"))
}
}
}
This meant I had to reference these specific dependencies in a different manner. For example, the JUnit dependency is referenced in a specific format shown below in the build.gradle file.
testImplementation testLibs.junitVersion Catalog is still something new within Android development. There will be more improvements throughout the coming months and better use cases for me within my application once I start developing multi-modules. As of now, this is still in the exploratory phase.
That’s all for this post. Here was a quick snapshot of what I have been working on lately on the Hangar android app. If you are interested in following my android development journey, consider subscribing and sharing this newsletter. Thank you!
No posts

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.