plugins { alias(libs.plugins.android.application) // kotlin-android NOT applied: AGP 9 enables built-in Kotlin by default, // and KSP 2.3.x supports it (PR #2674, merged Oct 2025). serialization // + compose-compiler are language-level Kotlin compiler plugins and // still need explicit application. alias(libs.plugins.kotlin.serialization) alias(libs.plugins.compose.compiler) alias(libs.plugins.ksp) alias(libs.plugins.androidx.room) alias(libs.plugins.hilt) alias(libs.plugins.ktlint) alias(libs.plugins.detekt) } android { namespace = "com.fabledsword.minstrel" compileSdk = 36 defaultConfig { applicationId = "com.fabledsword.minstrel" minSdk = 26 targetSdk = 36 versionCode = 1 versionName = "0.1.0-native" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary = true } } // Room schema export is handled by the androidx.room Gradle plugin via // the room {} block below — replaces the legacy // `ksp { arg("room.schemaLocation", ...) }` pattern in Room 2.7+. signingConfigs { create("release") { val keystorePath: String? = System.getenv("ANDROID_KEYSTORE_PATH") if (!keystorePath.isNullOrEmpty()) { storeFile = file(keystorePath) storePassword = System.getenv("ANDROID_STORE_PASSWORD") keyAlias = System.getenv("ANDROID_KEY_ALIAS") keyPassword = System.getenv("ANDROID_KEY_PASSWORD") } } } buildTypes { release { isMinifyEnabled = false proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro", ) signingConfig = if (System.getenv("ANDROID_KEYSTORE_PATH").isNullOrEmpty()) { signingConfigs.getByName("debug") } else { signingConfigs.getByName("release") } } } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } buildFeatures { compose = true buildConfig = true } packaging { resources.excludes += setOf( "/META-INF/{AL2.0,LGPL2.1}", "META-INF/LICENSE.md", "META-INF/LICENSE-notice.md", ) } } // Kotlin 2.x: `kotlinOptions { ... }` inside `android { }` is gone; the // modern shape is the top-level `kotlin { compilerOptions { ... } }` block, // which works whether Kotlin comes from AGP 9's built-in path or an // explicit plugin alias. kotlin { compilerOptions { jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17) // Opt into the future Kotlin behavior: annotations on // constructor parameters apply to both the param AND the // generated property/field. Without this flag, Kotlin 2.x // emits a deprecation warning at every @Inject / // @ApplicationContext / @ApplicationScope constructor- // parameter use. Setting it now matches what becomes the // default in Kotlin 2.3 (KT-73255). freeCompilerArgs.add("-Xannotation-default-target=param-property") } } // Room schema export — generated JSON dumps live under android/app/schemas/ // for migration-test fixtures. Replaces the legacy // `ksp { arg("room.schemaLocation", ...) }` arg-passing. room { schemaDirectory("$projectDir/schemas") } detekt { toolVersion = libs.versions.detekt.get() config.setFrom(files("$rootDir/config/detekt.yml")) buildUponDefaultConfig = true parallel = true // `autoCorrect` was dropped in detekt 2.0's DSL options list. } // detekt 2.0 moved its task types to the `dev.detekt.gradle` package and // flipped `jvmTarget` to the Property API. Pin to 17 to match our actual // bytecode target (compileOptions.targetCompatibility + // kotlin.compilerOptions.jvmTarget). tasks.withType().configureEach { jvmTarget.set("17") } tasks.withType().configureEach { jvmTarget.set("17") } dependencies { implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.compose) implementation(libs.androidx.lifecycle.viewmodel.compose) implementation(libs.androidx.lifecycle.process) implementation(libs.androidx.activity.compose) implementation(libs.androidx.nav.compose) implementation(libs.androidx.hilt.nav.compose) implementation(libs.androidx.hilt.work) ksp(libs.androidx.hilt.compiler) implementation(libs.androidx.work.runtime.ktx) implementation(platform(libs.compose.bom)) implementation(libs.compose.ui) implementation(libs.compose.ui.graphics) implementation(libs.compose.material3) implementation(libs.compose.ui.text.google.fonts) debugImplementation(libs.compose.ui.tooling) implementation(libs.compose.ui.tooling.preview) implementation(libs.hilt.android) ksp(libs.hilt.compiler) implementation(libs.room.runtime) implementation(libs.room.ktx) ksp(libs.room.compiler) implementation(libs.retrofit) implementation(libs.retrofit.kotlinx.serialization.converter) implementation(libs.okhttp) implementation(libs.okhttp.logging) implementation(libs.okhttp.sse) implementation(libs.kotlinx.serialization.json) implementation(libs.kotlinx.coroutines.android) implementation(libs.kotlinx.datetime) implementation(libs.media3.exoplayer) implementation(libs.media3.session) implementation(libs.media3.datasource.okhttp) implementation(libs.coil.compose) implementation(libs.coil.network.okhttp) implementation(libs.androidx.palette) implementation(libs.icons.lucide) implementation(libs.timber) testImplementation(libs.junit.jupiter) testImplementation(libs.turbine) testImplementation(libs.mockk) testImplementation(libs.kotlinx.coroutines.test) testImplementation(libs.okhttp.mockwebserver) // kotlin.test for assertEquals/assertNull/etc. — version managed by // the applied Kotlin plugin so no explicit version pin needed. testImplementation(kotlin("test")) // Gradle 9 no longer auto-injects the JUnit Platform launcher; must // be declared explicitly on the runtime classpath for useJUnitPlatform() // to discover tests. testRuntimeOnly(libs.junit.platform.launcher) androidTestImplementation(platform(libs.compose.bom)) androidTestImplementation(libs.compose.ui.test) // androidTest dep parity with the unit-test side; needed once we have // instrumented tests that consume the same APIs. androidTestImplementation(kotlin("test")) androidTestImplementation(libs.kotlinx.coroutines.test) debugImplementation(libs.compose.ui.test.manifest) } tasks.withType { useJUnitPlatform() }