androidkotlingradlebuild.gradleandroid-room

Kotlin Android different (Module:App) build.gradle structures makes tutorials hard to follow


I am quite new to developing in Android for kotlin.
I was trying to follow a tutorial on how to setup a local Room Database in my App, but my build.gradle looks completely different than the persons gradle in the Tutorial.

My build.gradle

plugins {
    alias(libs.plugins.androidApplication)
    alias(libs.plugins.jetbrainsKotlinAndroid)
}

android {
    namespace = "com.example.myapp"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.example.pomodoro28"
        minSdk = 24
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables {
            useSupportLibrary = true
        }
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
    buildFeatures {
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.1"
    }
    packaging {
        resources {
            excludes += "/META-INF/{AL2.0,LGPL2.1}"
        }
    }
}

dependencies {

    implementation(libs.androidx.core.ktx)
    implementation(libs.androidx.lifecycle.runtime.ktx)
    implementation(libs.androidx.activity.compose)
    implementation(platform(libs.androidx.compose.bom))
    implementation(libs.androidx.ui)
    implementation(libs.androidx.ui.graphics)
    implementation(libs.androidx.ui.tooling.preview)
    implementation(libs.androidx.material3)
    implementation(libs.androidx.room.common)
    implementation(libs.androidx.room.ktx)
    implementation(libs.androidx.navigation.compose)
    testImplementation(libs.junit)
    androidTestImplementation(libs.androidx.junit)
    androidTestImplementation(libs.androidx.espresso.core)
    androidTestImplementation(platform(libs.androidx.compose.bom))
    androidTestImplementation(libs.androidx.ui.test.junit4)
    debugImplementation(libs.androidx.ui.tooling)
    debugImplementation(libs.androidx.ui.test.manifest)
}

Build.gradle from the Tutorial:

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'kotlin-kapt'
}

android {
    namespace 'com.plcoding.roomguideandroid'
    compileSdk 33

    defaultConfig {
        applicationId "com.plcoding.roomguideandroid"
        minSdk 24
        targetSdk 33
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables {
            useSupportLibrary true
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    buildFeatures {
        compose true
    }
    composeOptions {
        kotlinCompilerExtensionVersion '1.2.0'
    }
    packagingOptions {
        resources {
            excludes += '/META-INF/{AL2.0,LGPL2.1}'
        }
    }
}

dependencies {

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
    implementation 'androidx.activity:activity-compose:1.3.1'
    implementation "androidx.compose.ui:ui:$compose_ui_version"
    implementation "androidx.compose.ui:ui-tooling-preview:$compose_ui_version"
    implementation 'androidx.compose.material:material:1.2.0'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
    androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_ui_version"
    debugImplementation "androidx.compose.ui:ui-tooling:$compose_ui_version"
    debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_ui_version"

    // Room
    def room_version = "2.5.0"
    implementation "androidx.room:room-ktx:$room_version"
    kapt "androidx.room:room-compiler:$room_version"
}

As You can see, his dependencies have a structure like this

implementation "androidx.compose.ui:ui-tooling-preview:$compose_ui_version"

While mine look like this

implementation(libs.androidx.activity.compose)

Mine have parentheses, while he has quotation marks.

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'kotlin-kapt'
}
plugins {
    alias(libs.plugins.androidApplication)
    alias(libs.plugins.jetbrainsKotlinAndroid)
}

His plugins have "id" while mine have alias.

And there are few other syntax/structural differences.
I have basically implemented his Room code 1 : 1, the only difference being my build.gradle, but my app immediately crashes when I launch it, so I believe this is where the error lies.

I asked ChatGpt, but Chat juts told me to straight up copy his into mine.

That did not work.

I tried to simply to a sort of combination of both, like this:

plugins {
    alias(libs.plugins.androidApplication)
    alias(libs.plugins.jetbrainsKotlinAndroid)
    id 'kotlin-kapt'
}
dependencies {

    implementation(libs.androidx.core.ktx)
    implementation(libs.androidx.lifecycle.runtime.ktx)
    implementation(libs.androidx.activity.compose)
    implementation(platform(libs.androidx.compose.bom))
    implementation(libs.androidx.ui)
    implementation(libs.androidx.ui.graphics)
    implementation(libs.androidx.ui.tooling.preview)
    implementation(libs.androidx.material3)
    implementation(libs.androidx.room.common)
    implementation(libs.androidx.room.ktx)
    implementation(libs.androidx.navigation.compose)
    testImplementation(libs.junit)
    androidTestImplementation(libs.androidx.junit)
    androidTestImplementation(libs.androidx.espresso.core)
    androidTestImplementation(platform(libs.androidx.compose.bom))
    androidTestImplementation(libs.androidx.ui.test.junit4)
    debugImplementation(libs.androidx.ui.tooling)
    debugImplementation(libs.androidx.ui.test.manifest)

    def room_version = "2.5.0"
    implementation "androidx.room:room-ktx:$room_version"
    kapt "androidx.room:room-compiler:$room_version"
}

that did also not work.

I have looked at a couple of other Room Tutorials, including the one on the Android Developer site, all of those, seem to follow the structure different to mine. I don't know whats "wrong" with mine or why mine is different than everyone elses (it simply autogenerates when I create an empty project in Android studio). But there seems no immediately obvious fix.


Solution

  • Although both are gradle files, theirs uses Groovy syntax, yours uses Kotlin syntax. You can read more about the migration from Groovy to Kotlin here: https://docs.gradle.org/current/userguide/migrating_from_groovy_to_kotlin_dsl.html

    In addition your gradle setup defines the dependencies in a Version Catalog (a file named libs.versions.toml). For more see this migration guide: https://developer.android.com/build/migrate-to-catalogs

    The tutorial you use seems to be quite old. In addition to migrating to Kotlin + Version Catalogs you should also update the Room version number from "2.5.0" to "2.6.1" and migrate from kapt to KSP: https://developer.android.com/build/migrate-to-ksp


    To summarize, for Room you need to add the following to your build files:

    1. libs.versions.toml (merge with the respective sections):

      [versions]
      ksp = "2.0.0-1.0.22" # https://github.com/google/ksp/releases
      room = "2.6.1"
      
      [libraries]
      androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
      androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
      
      [plugins]
      google-devtools-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
      

      Make sure the first part of the ksp version (before the dash) is the same as the Kotlin version you use for your org.jetbrains.kotlin.android plugin. I assumed you used the newest version "2.0.0" (at the time of writing). Always use the newest KSP version compatible to your Kotlin version, you can find all versions here: https://github.com/google/ksp/releases

    2. Top-level build.gradle.kts (merge with the existing plugins block):

      plugins {
          alias(libs.plugins.google.devtools.ksp) apply false
      }
      
    3. Module-level build.gradle.kts (merge with the existing blocks):

      plugins {
          alias(libs.plugins.google.devtools.ksp)
      }
      
      dependencies {
          ksp(libs.androidx.room.compiler)
          implementation(libs.androidx.room.ktx)
      }
      

    That said your module-level gradle file already seems to contain this:

    implementation(libs.androidx.room.ktx)
    

    So your version catalog probably also already contains some of what's needed.