Blog Infos
Author
Published
Topics
, , , ,
Published

This image was generated using AI

Whether your build.gradle is written in Groovy or if you already made the jump to Kotlin, there will come a time where you will need to migrate to Gradle version catalogs.

When, you ask?

It will happen when you will want to update your Kotlin compiler version to be 2.0.0 or above. This is because the Jetpack Compose compiler has been moved to the Kotlin repository [Reference]. Due to this, a new plugin was released, the Compose Compiler Gradle plugin. Usually, with every release of the Compose library, you had a specific kotlinCompilerExtensionVersion you would have to use:

composeOptions {
    kotlinCompilerExtensionVersion '1.5.13'
}

But you can see here, that for Kotlin versions 2 and above, you will need to use the Compose Compiler Gradle plugin.

In this article, we will lay out the (possible) path you may need to take:

  1. Your build configuration is in Groovy
  2. Your build configuration is in Kotlin
  3. You don’t have a libs.versions.toml file
  4. You have a libs.versions.toml file
Migrating build configuration to Kotlin

There are two choices if your build configuration is in Groovy:

  • You can migrate your build configuration to Kotlin
  • You can migrate your build configuration directly to Gradle Version Catalog

If you choose the first option, it is a longer route to take, but not by much. If you choose the second option, you can skip this section and go right ahead to the next one.

❗️ Be aware that this article is written assuming the build configuration is in Kotlin so you may need to make the necessary adjustments for Groovy

First, we will need to migrate the project to work with Kotlin in the build.gradle files. There is an article that covers all the needed steps, but here I’d like to showcase a full example of how the build.gradle file looks like before and after the migration.

build.gradle (app level) before the migration:

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 34
    defaultConfig {
        applicationId "com.tomerpacific.laundry"
        minSdkVersion 21
        targetSdkVersion 34
        versionCode 25
        versionName "2.4.8"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        dataBinding {
            enabled = true
        }
    }

    kotlinOptions {
        jvmTarget = 17
    }

    buildFeatures {
        compose true
        viewBinding = true
    }

    composeOptions {
        kotlinCompilerExtensionVersion '1.5.10'
    }

    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            ndk {
                debugSymbolLevel 'SYMBOL_TABLE'
            }
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }

    packagingOptions {
        resources.excludes.add("META-INF/*")
    }
    namespace 'com.tomerpacific.laundry'
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "androidx.fragment:fragment-ktx:1.4.0"
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.4.0'
    implementation 'androidx.activity:activity-compose:1.8.2'
    implementation 'androidx.compose.ui:ui-viewbinding:1.6.2'
    implementation 'com.google.android.material:material:1.8.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
    implementation 'com.google.android.play:app-update:2.1.0'
    implementation 'com.google.android.play:app-update-ktx:2.1.0'

    implementation "androidx.compose.material3:material3:1.2.1"
    implementation "androidx.compose.material3:material3-window-size-class:1.2.1"
    implementation "androidx.compose.material3:material3-adaptive-navigation-suite:1.3.0-rc01"

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    androidTestImplementation 'androidx.compose.ui:ui-test-junit4:1.1.0'
    debugImplementation 'androidx.compose.ui:ui-test-manifest:1.6.2'

}

The key changes you should pay attention to are:

  • Using double quotation marks(“) instead of single quotation marks(‘)
  • Using the equals operator (=) for any setting
  • Any property that has a Boolean value should be prefixed with the is word
  • Plugins block instead of the apply plugin commands
  • Removal of implementation”org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version”

build.gradle after the migration:

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

android {
    namespace = "com.tomerpacific.laundry"
    compileSdk = 34
    defaultConfig {
        applicationId = "com.tomerpacific.laundry"
        minSdk = 21
        targetSdk = 34
        versionCode = 25
        versionName = "2.4.8"
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        buildFeatures {
            dataBinding = true
        }
    }

    kotlinOptions {
        jvmTarget = "17"
    }

    buildFeatures {
        compose = true
        viewBinding = true
    }

    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.10"
    }

    buildTypes {
        release {
            isMinifyEnabled = true
            isShrinkResources = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
            ndk {
                debugSymbolLevel = "SYMBOL_TABLE"
            }
        }
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }

    packaging {
        resources {
            excludes += "META-INF/*"
        }
    }
}

dependencies {
    implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
    implementation("androidx.fragment:fragment-ktx:1.4.0")
    implementation("androidx.appcompat:appcompat:1.4.0")
    implementation("androidx.activity:activity-compose:1.8.2")
    implementation("androidx.compose.ui:ui-viewbinding:1.6.2")
    implementation("com.google.android.material:material:1.8.0")
    implementation("androidx.constraintlayout:constraintlayout:2.1.2")
    implementation("com.google.android.play:app-update:2.1.0")
    implementation("com.google.android.play:app-update-ktx:2.1.0")

    implementation("androidx.compose.material3:material3:1.2.1")
    implementation("androidx.compose.material3:material3-window-size-class:1.2.1")
    implementation("androidx.compose.material3:material3-adaptive-navigation-suite:1.3.0-rc01")

    testImplementation("junit:junit:4.12")
    androidTestImplementation("androidx.test.ext:junit:1.1.3")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0")
    androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.1.0")
    debugImplementation("androidx.compose.ui:ui-test-manifest:1.6.2")

}

As for the your project level build.gradle file and the settings.gradle file, here is how they look like after the changes:

build.gradle.kts:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

plugins {
    id("com.android.application") version "8.0.2" apply false
    id("org.jetbrains.kotlin.android") version "1.9.22" apply false
}

settings.gradle.kts:

pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}

rootProject.name = "laundry"
include(":app")
Migrating To Gradle Version Catalog

If you don’t have a libs.versions.toml file, then before you migrate to the Compose Compiler Gradle plugin, you need to migrate your build to Gradle Version Catalog. This means creating a libs.versions.toml file in your project’s gradle folder:

This file includes three sections:

  1. versions – In this section you will have the names of your dependencies with their associated version in the format of version = “x.y.z”
  2. libraries – In this section you will have key value pairs indicating the name of the library with an object representing the group, name and version reference of the library
  3. plugins – Similar to the libraries section, but having only an id and version reference fields

Each dependency or plugin that you migrate from your build.gradle.kts file will be broken up into two parts:

  1. A line under the versions/plugins section, indicating the library name and it’s version
  2. A line under the libraries section, indicating the name of the library followed by an object that contains three keys: group, name and version.ref

For example, if we have the following dependency:

implementation "androidx.fragment:fragment-ktx:1.4.0"

We will break it into three parts and use those parts in our libs.versions.toml file:

  1. fragment-ktx:1.4.0 will be used under the versions section
  2. androidx.fragment-ktx will be used as the key under the libraries section
  3. group = “androidx.fragment”, name = “fragment-ktx”, version.ref = “fragment-ktx” will be the object for the key in step #2

It looks like this:

[versions]
fragment-ktx = "1.4.0"

[libraries]
androidx-fragment-ktx = { group = "androidx.fragment", name = "fragment-ktx", version.ref = "fragment-ktx" }

[plugins]

⚠️ Pay attention that the key you use under the libraries section is the value you will need to use in your build.gradle.kts file

And in our build.gradle.kts file, under the dependencies block, we will use:

implementation(libs.androidx.fragment.ktx)

It is recommended to make sure your project compiles and runs properly after each dependency you migrate

When you migrate one of the plugins you use, you will have to add lines under the versions and plugins section. Let’s show how to do this with an example below:

classpath 'com.android.tools.build:gradle:8.0.2'

Above is the line you have in your project level build.gradle, so you will need to add these lines in the corresponding versions and plugins sections to represent it:

[versions]
androidGradlePlugin = "8.0.2"

...

[plugins]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }

Then in your project level build.gradle, replace the original line with this one:

plugins {
   alias(libs.plugins.android.application) apply false
}

and in your application level build.gradle, replace the line there:

plugins {
    id("com.android.application")  // <--- This line should be removed
    alias(libs.plugins.android.application)
}

⚠️ If you are using a Gradle version below 8.1, you will need to add an annotation above your plugins block in both build.gradle files:

@file:Suppress("DSL_SCOPE_VIOLATION")  // <---- This
plugins {
   alias(libs.plugins.android.application) apply false
}

And in your application level build.gradle:

@file:Suppress("DSL_SCOPE_VIOLATION") // <---- This
plugins {
    alias(libs.plugins.android.application)
}

[Reference]

Migrating to Compose Compiler Gradle

Whether you got here after going through all of the steps, or just jumped to this one, the migration here is rather simple.

  1. Remove any reference you might have in your build.gradle.kts to the Compose Compiler, I.E.
composeOptions {
        kotlinCompilerExtensionVersion '1.5.10'
    }

2. Alter the Kotlin version you have and add this dependency in the libs.versions.toml file:

[versions]
kotlin = "2.0.0"

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

compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }

3. Inside your project level build.gradle.kts, add this line:

plugins {
   id(libs.plugins.compose.compiler) apply false
}

4. Inside your application level build.gradle.kts, add this line:

plugins {
   id(libs.plugins.compose.compiler)
}

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

, ,

Cutting-Edge-to-Edge in Android 15: Using Previews and Testing in Jetpack Compose to Manage Insets.

With the advent of Android 15, edge-to-edge design has become the default configuration. Consequently, applications must be capable of accommodating window insets, including the system status bar and navigation bar, as well as supporting drawing…
Watch Video

Cutting-Edge-to-Edge in Android 15: Using Previews and Testing in Jetpack Compose to Manage Insets.

Timo Drick
Lead Android developer
Seven Principles Mobility GmbH

Cutting-Edge-to-Edge in Android 15: Using Previews and Testing in Jetpack Compose to Manage Insets.

Timo Drick
Lead Android develop ...
Seven Principles Mob ...

Cutting-Edge-to-Edge in Android 15: Using Previews and Testing in Jetpack Compose to Manage Insets.

Timo Drick
Lead Android developer
Seven Principles Mobility ...

Jobs

If you would like to see a complete example of how this migration was done, you can view it here:

This article was previously published on proandroiddev.com.

Menu