diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 26d3352..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/.idea/androidTestResultsUserPreferences.xml b/.idea/androidTestResultsUserPreferences.xml deleted file mode 100644 index f9e941b..0000000 --- a/.idea/androidTestResultsUserPreferences.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index 7643783..0000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123..0000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index b589d56..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index 0e37b49..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 6195b36..0000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml deleted file mode 100644 index d64a02e..0000000 --- a/.idea/jarRepositories.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml deleted file mode 100644 index c22b6fa..0000000 --- a/.idea/kotlinc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 0ad17cb..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ffdfd69..c2ce438 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,4 +1,5 @@ import com.automattic.android.measure.reporters.SlowSlowTasksMetricsReporter +import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { alias(libs.plugins.android.application) @@ -57,17 +58,22 @@ android { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() + kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_17) + } } buildFeatures { viewBinding = true compose = true + buildConfig = true } packaging { resources { excludes.add("/META-INF/{AL2.0,LGPL2.1}") + excludes.add("META-INF/LICENSE.md") + excludes.add("META-INF/LICENSE-notice.md") } } applicationVariants.forEach { variant -> @@ -78,8 +84,7 @@ android { } composeCompiler { - enableStrongSkippingMode = true - reportsDestination = layout.buildDirectory.dir("compose_compiler") + reportsDestination.set(layout.buildDirectory.dir("compose_compiler")) } fun extraString(key: String): String { @@ -88,7 +93,7 @@ fun extraString(key: String): String { detekt { toolVersion = "1.22.0" - config = files("${project.rootDir}/config/detekt/detekt.yml") + config.from("${project.rootDir}/config/detekt/detekt.yml") baseline = file("$rootDir/detekt-baseline.xml") autoCorrect = true } @@ -99,6 +104,17 @@ configurations { } } +// compose-bom:2026.03.00 strictly pins monitor:1.6.0, but espresso-core:3.7.0 was compiled +// against monitor:1.8.0 (ReflectiveMethod(Class,String,Class[]) constructor added in 1.8.0). +// Force 1.8.0 across all androidTest configurations to override the BOM strict constraint +// and prevent NoSuchMethodError at runtime. +configurations.matching { it.name.contains("AndroidTest") || it.name.contains("androidTest") } + .configureEach { + resolutionStrategy { + force("androidx.test:monitor:1.8.0") + } + } + measureBuilds { enable = true diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 74f026a..1ac8810 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin) @@ -35,8 +37,10 @@ android { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() + kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_17) + } } testOptions { unitTests { diff --git a/gradle.properties b/gradle.properties index f237e40..8b245cb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,7 +20,6 @@ android.enableJetifier=true # Kotlin code style for this project: "official" or "obsolete": kotlin.code.style=official #Android -android.defaults.buildfeatures.buildconfig=true android.nonTransitiveRClass=false android.nonFinalResIds=false ## Project @@ -28,4 +27,15 @@ application_id=com.santimattius.entertainment min_sdk_version=24 target_sdk_version=36 version_code=1 -version_name=1.0 \ No newline at end of file +version_name=1.0 +##AGP MIGRATIONS +android.defaults.buildfeatures.resvalues=true +android.sdk.defaultTargetSdkToCompileSdkIfUnset=false +android.enableAppCompileTimeRClass=false +android.usesSdkInManifest.disallowed=false +android.uniquePackageNames=false +android.dependency.useConstraints=true +android.r8.strictFullModeForKeepRules=false +android.r8.optimizedResourceShrinking=false +android.builtInKotlin=false +android.newDsl=false \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8adc0f3..0ff1eab 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,35 +1,36 @@ [versions] # Plugins -androidGradlePlugin = "8.12.2" +androidGradlePlugin = "9.1.0" hamcrest = "3.0" -kotlin = "2.2.10" +kotlin = "2.3.10" detektGradlePlugin = "1.23.8" -ksp = "2.2.10-2.0.2" +ksp = "2.3.6" googleSecretsPlugin = "2.0.1" -automatticMeasureBuilds = "3.2.1" +automatticMeasureBuilds = "3.2.2" # Define the dependency versions -coreKtx = "1.17.0" +coreKtx = "1.18.0" legacySupport = "1.0.0" appCompat = "1.7.1" fragmentKtx = "1.8.9" constraintLayout = "2.2.1" recyclerView = "1.4.0" -materialVersion = "1.12.0" -lifecycle = "2.9.3" +materialVersion = "1.13.0" +lifecycle = "2.10.0" retrofit = "3.0.0" -okHttp = "5.1.0" +okHttp = "5.3.2" coroutine = "1.10.2" -gson = "2.13.1" -glide = "5.0.0-rc01" +gson = "2.13.2" +glide = "5.0.5" coil = "2.7.0" -room = "2.7.2" +room = "2.8.4" -androidxComposeBom = "2025.08.01" -activityCompose = "1.10.1" +androidxComposeBom = "2026.03.00" +activityCompose = "1.13.0" +#TODO: pending for migration koinBom = "4.1.0" koinAnnotations = "2.1.0" @@ -44,10 +45,10 @@ fragmentTesting = "1.8.9" espressoCore = "3.7.0" okhttp3IdlingResource = "1.0.0" -mockk = "1.14.5" -robolectric = "4.16" +mockk = "1.14.9" +robolectric = "4.16.1" turbine = "1.2.1" -mockitoKotlin = "6.0.0" +mockitoKotlin = "6.2.3" [libraries] # Define the libraries @@ -117,7 +118,6 @@ robolectric-httpclient = { module = "org.robolectric:shadows-httpclient", versio androidx-core-ktx = { module = "androidx.test:core-ktx", version.ref = "coreKtxVersion" } androidx-fragment-testing-manifest = { module = "androidx.fragment:fragment-testing-manifest", version.ref = "fragmentTesting" } androidx-fragment-testing = { module = "androidx.fragment:fragment-testing", version.ref = "fragmentTesting" } - # AndroidTest test-ext = { module = "androidx.test.ext:junit", version.ref = "junitExt" } test-ext-ktx = { module = "androidx.test.ext:junit-ktx", version.ref = "junitExt" } @@ -137,7 +137,7 @@ dep-google-secrets-gradle-plugin = { module = "com.google.android.libraries.maps ui = ["legacy-support", "app-compart", "fragment-ktx", "constraint-layout", "recycler-view", "material"] compose = ["compose_ui", "compose_material3", "compose_tooling_preview", "compose_icons"] compose_debug = ["compose_tooling", "compose_ui_test_manifest"] -lifecycle = [ "lifecycle-runtime-ktx", "lifecycle-viewmodel-ktx", "lifecycle-livedata-ktx"] +lifecycle = ["lifecycle-runtime-ktx", "lifecycle-viewmodel-ktx", "lifecycle-livedata-ktx"] coroutine = ["coroutine-core", "coroutine-android"] retrofit = ["retrofit-core", "retrofit-gson", "logging-interceptor"] serializable = ["gson-core"] @@ -150,7 +150,7 @@ androidTesting = ["core-testing", "mockwebserver", "okHttp3-idling-resource", "j android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" } kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } -room = { id = "androidx.room", version.ref = "room"} +room = { id = "androidx.room", version.ref = "room" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detektGradlePlugin" } diff --git a/gradle/report.gradle b/gradle/report.gradle index 5c15c09..d5946ec 100644 --- a/gradle/report.gradle +++ b/gradle/report.gradle @@ -44,7 +44,8 @@ def createVariantCoverage(variant) { def testTaskName = "test${variantName.capitalize()}UnitTest" // Add unit test coverage tasks - tasks.create(name: "${testTaskName}Coverage", type: JacocoReport, dependsOn: "$testTaskName") { + tasks.register("${testTaskName}Coverage", JacocoReport) { + dependsOn "$testTaskName" group = "Reporting" description = "Generate Jacoco coverage reports for the ${variantName.capitalize()} build." @@ -53,40 +54,37 @@ def createVariantCoverage(variant) { html.required = true } - def javaClasses = fileTree(dir: variant.javaCompileProvider.get().destinationDir, excludes: project.excludes) - def kotlinClasses = fileTree(dir: "${buildDir}/tmp/kotlin-classes/${variantName}", excludes: project.excludes) - getClassDirectories().setFrom(files([javaClasses, kotlinClasses])) + def javaClasses = fileTree(dir: variant.javaCompileProvider.get().destinationDirectory.asFile.get(), excludes: project.excludes) + def kotlinClasses = fileTree(dir: "${project.layout.buildDirectory.get().asFile}/tmp/kotlin-classes/${variantName}", excludes: project.excludes) + classDirectories.setFrom(files([javaClasses, kotlinClasses])) - getSourceDirectories().setFrom(files([ + sourceDirectories.setFrom(files([ "$project.projectDir/src/main/java", "$project.projectDir/src/${variantName}/java", "$project.projectDir/src/main/kotlin", "$project.projectDir/src/${variantName}/kotlin" ])) - getExecutionData().setFrom(files("${project.buildDir}/outputs/unit_test_code_coverage/${variantName}UnitTest/${testTaskName}.exec")) + executionData.setFrom(files("${project.layout.buildDirectory.get().asFile}/outputs/unit_test_code_coverage/${variantName}UnitTest/${testTaskName}.exec")) doLast { - def m = new File("${project.buildDir}/reports/jacoco/${testTaskName}Coverage/html/index.html") - .text =~ /Total[^%]*>(\d?\d?\d?%)/ - if (m) { - println "Test coverage: ${m[0][1]}" + def reportFile = new File("${project.layout.buildDirectory.get().asFile}/reports/jacoco/${testTaskName}Coverage/html/index.html") + if (reportFile.exists()) { + def m = reportFile.text =~ /Total[^%]*>(\d?\d?\d?%)/ + if (m) { + println "Test coverage: ${m[0][1]}" + } } } } // Add unit test coverage verification tasks - tasks.create(name: "${testTaskName}CoverageVerification", type: JacocoCoverageVerification, dependsOn: "${testTaskName}Coverage") { + tasks.register("${testTaskName}CoverageVerification", JacocoCoverageVerification) { + dependsOn "${testTaskName}Coverage" group = "Reporting" description = "Verifies Jacoco coverage for the ${variantName.capitalize()} build." violationRules { rule { - limit { - minimum = 0 - } - } - rule { - element = 'BUNDLE' limit { counter = 'LINE' value = 'COVEREDRATIO' @@ -94,15 +92,15 @@ def createVariantCoverage(variant) { } } } - def javaClasses = fileTree(dir: variant.javaCompileProvider.get().destinationDir, excludes: project.excludes) - def kotlinClasses = fileTree(dir: "${buildDir}/tmp/kotlin-classes/${variantName}", excludes: project.excludes) - getClassDirectories().setFrom(files([javaClasses, kotlinClasses])) - getSourceDirectories().setFrom(files([ + def javaClasses = fileTree(dir: variant.javaCompileProvider.get().destinationDirectory.asFile.get(), excludes: project.excludes) + def kotlinClasses = fileTree(dir: "${project.layout.buildDirectory.get().asFile}/tmp/kotlin-classes/${variantName}", excludes: project.excludes) + classDirectories.setFrom(files([javaClasses, kotlinClasses])) + sourceDirectories.setFrom(files([ "$project.projectDir/src/main/java", "$project.projectDir/src/${variantName}/java", "$project.projectDir/src/main/kotlin", "$project.projectDir/src/${variantName}/kotlin" ])) - getExecutionData().setFrom(files("${project.buildDir}/outputs/unit_test_code_coverage/${variantName}UnitTest/${testTaskName}.exec")) + executionData.setFrom(files("${project.layout.buildDirectory.get().asFile}/outputs/unit_test_code_coverage/${variantName}UnitTest/${testTaskName}.exec")) } } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 20cd8fc..3dc8617 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-all.zip diff --git a/shared-test/build.gradle.kts b/shared-test/build.gradle.kts index ef067a5..ce57452 100644 --- a/shared-test/build.gradle.kts +++ b/shared-test/build.gradle.kts @@ -1,4 +1,4 @@ -@file:Suppress("DSL_SCOPE_VIOLATION") +import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { alias(libs.plugins.android.library) @@ -29,9 +29,20 @@ android { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() + kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_17) + } } + + packaging { + resources { + excludes.add("/META-INF/{AL2.0,LGPL2.1}") + excludes.add("META-INF/LICENSE.md") + excludes.add("META-INF/LICENSE-notice.md") + } + } + libraryVariants.forEach { variant -> variant.sourceSets.forEach { it.javaDirectories += files("build/generated/ksp/${variant.name}/kotlin")