diff --git a/app-nia-catalog/build.gradle.kts b/app-nia-catalog/build.gradle.kts index 42ffd7039..1f9ac1e2a 100644 --- a/app-nia-catalog/build.gradle.kts +++ b/app-nia-catalog/build.gradle.kts @@ -47,7 +47,7 @@ android { missingDimensionStrategy(FlavorDimension.contentType.name, NiaFlavor.demo.name) } - packagingOptions { + packaging { resources { excludes.add("/META-INF/{AL2.0,LGPL2.1}") } @@ -55,7 +55,7 @@ android { namespace = "com.google.samples.apps.niacatalog" buildTypes { - val release by getting { + release { // To publish on the Play store a private signing key is required, but to allow anyone // who clones the code to sign and run the release variant, use the debug signing key. // TODO: Abstract the signing configuration to a separate file to avoid hardcoding this. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 42dee2602..e172ed8bb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -39,7 +39,7 @@ android { } buildTypes { - val debug by getting { + debug { applicationIdSuffix = NiaBuildType.DEBUG.applicationIdSuffix } val release by getting { @@ -52,7 +52,7 @@ android { // TODO: Abstract the signing configuration to a separate file to avoid hardcoding this. signingConfig = signingConfigs.getByName("debug") } - val benchmark by creating { + create("benchmark") { // Enable all the optimizations from release build through initWith(release). initWith(release) matchingFallbacks.add("release") @@ -65,7 +65,7 @@ android { } } - packagingOptions { + packaging { resources { excludes.add("/META-INF/{AL2.0,LGPL2.1}") } diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index fa8aeefb0..fb46ae63f 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -39,7 +39,7 @@ android { // This benchmark buildType is used for benchmarking, and should function like your // release build (for example, with minification on). It's signed with a debug key // for easy local/CI testing. - val benchmark by creating { + create("benchmark") { // Keep the build type debuggable so we can attach a debugger if needed. isDebuggable = true signingConfig = signingConfigs.getByName("debug") diff --git a/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt index 5b2f76edb..275a26620 100644 --- a/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt @@ -20,6 +20,7 @@ import com.google.samples.apps.nowinandroid.configureFlavors import com.google.samples.apps.nowinandroid.configureGradleManagedDevices import com.google.samples.apps.nowinandroid.configureKotlinAndroid import com.google.samples.apps.nowinandroid.configurePrintApksTask +import com.google.samples.apps.nowinandroid.disableUnnecessaryAndroidTests import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.artifacts.VersionCatalogsExtension @@ -44,6 +45,7 @@ class AndroidLibraryConventionPlugin : Plugin { } extensions.configure { configurePrintApksTask(this) + disableUnnecessaryAndroidTests(target) } val libs = extensions.getByType().named("libs") configurations.configureEach { diff --git a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/AndroidInstrumentedTests.kt b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/AndroidInstrumentedTests.kt new file mode 100644 index 000000000..d0c26e4e6 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/AndroidInstrumentedTests.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.samples.apps.nowinandroid + +import com.android.build.api.variant.LibraryAndroidComponentsExtension +import org.gradle.api.Project + +/** + * Disable unnecessary Android instrumented tests for the [project] if there is no `androidTest` folder. + * Otherwise, these projects would be compiled, packaged, installed and ran only to end-up with the following message: + * + * > Starting 0 tests on AVD + * + * Note: this could be improved by checking other potential sourceSets based on buildTypes and flavors. + */ +internal fun LibraryAndroidComponentsExtension.disableUnnecessaryAndroidTests( + project: Project, +) = beforeVariants { + it.enableAndroidTest = it.enableAndroidTest + && project.projectDir.resolve("src/androidTest").exists() +} diff --git a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/GradleManagedDevices.kt b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/GradleManagedDevices.kt index 624afeea9..8129defeb 100644 --- a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/GradleManagedDevices.kt +++ b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/GradleManagedDevices.kt @@ -20,7 +20,6 @@ import com.android.build.api.dsl.CommonExtension import com.android.build.api.dsl.ManagedVirtualDevice import org.gradle.api.Project import org.gradle.kotlin.dsl.invoke -import java.util.Locale /** * Configure project for Gradle managed devices @@ -55,7 +54,7 @@ private data class DeviceConfig( val systemImageSource: String, ) { val taskName = buildString { - append(device.toLowerCase(Locale.ROOT).replace(" ", "")) + append(device.lowercase().replace(" ", "")) append("api") append(apiLevel.toString()) append(systemImageSource.replace("-", "")) diff --git a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Jacoco.kt b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Jacoco.kt index a34cd7c1c..d801d7b69 100644 --- a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Jacoco.kt +++ b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Jacoco.kt @@ -27,6 +27,7 @@ import org.gradle.kotlin.dsl.withType import org.gradle.testing.jacoco.plugins.JacocoPluginExtension import org.gradle.testing.jacoco.plugins.JacocoTaskExtension import org.gradle.testing.jacoco.tasks.JacocoReport +import java.util.Locale private val coverageExclusions = listOf( // Android @@ -36,6 +37,10 @@ private val coverageExclusions = listOf( "**/Manifest*.*" ) +private fun String.capitalize() = replaceFirstChar { + if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() +} + internal fun Project.configureJacoco( androidComponentsExtension: AndroidComponentsExtension<*, *, *>, ) { diff --git a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/KotlinAndroid.kt b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/KotlinAndroid.kt index e800d0570..65a734895 100644 --- a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/KotlinAndroid.kt +++ b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/KotlinAndroid.kt @@ -62,7 +62,6 @@ internal fun Project.configureKotlinAndroid( // Enable experimental coroutines APIs, including Flow "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", "-opt-in=kotlinx.coroutines.FlowPreview", - "-opt-in=kotlin.Experimental", ) } } diff --git a/core/data/src/test/java/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestTopicDao.kt b/core/data/src/test/java/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestTopicDao.kt index e891dcfdc..a52cc86f6 100644 --- a/core/data/src/test/java/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestTopicDao.kt +++ b/core/data/src/test/java/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestTopicDao.kt @@ -53,10 +53,6 @@ class TestTopicDao : TopicDao { return topicEntities.map { it.id.toLong() } } - override suspend fun updateTopics(entities: List) { - throw NotImplementedError("Unused in tests") - } - override suspend fun upsertTopics(entities: List) { // Overwrite old values with new values entitiesStateFlow.update { oldValues -> diff --git a/core/database/build.gradle.kts b/core/database/build.gradle.kts index 10eb4363c..a9c711ae3 100644 --- a/core/database/build.gradle.kts +++ b/core/database/build.gradle.kts @@ -14,8 +14,6 @@ * limitations under the License. */ -// TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed -@Suppress("DSL_SCOPE_VIOLATION") plugins { id("nowinandroid.android.library") id("nowinandroid.android.library.jacoco") diff --git a/core/database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/TopicDao.kt b/core/database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/TopicDao.kt index 693a85b77..e876458ee 100644 --- a/core/database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/TopicDao.kt +++ b/core/database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/TopicDao.kt @@ -20,7 +20,6 @@ import androidx.room.Dao import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query -import androidx.room.Update import androidx.room.Upsert import com.google.samples.apps.nowinandroid.core.database.model.TopicEntity import kotlinx.coroutines.flow.Flow @@ -58,12 +57,6 @@ interface TopicDao { @Insert(onConflict = OnConflictStrategy.IGNORE) suspend fun insertOrIgnoreTopics(topicEntities: List): List - /** - * Updates [entities] in the db that match the primary key, and no-ops if they don't - */ - @Update - suspend fun updateTopics(entities: List) - /** * Inserts or updates [entities] in the db under the specified primary keys */ diff --git a/core/datastore/build.gradle.kts b/core/datastore/build.gradle.kts index 59a3a8e32..a9ec7a78f 100644 --- a/core/datastore/build.gradle.kts +++ b/core/datastore/build.gradle.kts @@ -14,8 +14,6 @@ * limitations under the License. */ -// TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed -@Suppress("DSL_SCOPE_VIOLATION") plugins { id("nowinandroid.android.library") id("nowinandroid.android.library.jacoco") @@ -43,10 +41,10 @@ protobuf { generateProtoTasks { all().forEach { task -> task.builtins { - val java by registering { + register("java") { option("lite") } - val kotlin by registering { + register("kotlin") { option("lite") } } diff --git a/core/model/build.gradle.kts b/core/model/build.gradle.kts index edfcc4596..d49c5b3ee 100644 --- a/core/model/build.gradle.kts +++ b/core/model/build.gradle.kts @@ -13,8 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -// TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed -@Suppress("DSL_SCOPE_VIOLATION") + plugins { id("kotlin") } diff --git a/docs/ArchitectureLearningJourney.md b/docs/ArchitectureLearningJourney.md index 9d7c77e1c..925858111 100644 --- a/docs/ArchitectureLearningJourney.md +++ b/docs/ArchitectureLearningJourney.md @@ -64,7 +64,7 @@ Here's what's happening in each step. The easiest way to find the associated cod On app startup, a WorkManager job to sync all repositories is enqueued. - SyncInitializer.create + Sync.initialize diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 95b084fa7..ccfdeca99 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ androidxActivity = "1.7.0" androidxAppCompat = "1.5.1" androidxBrowser = "1.4.0" androidxComposeBom = "2023.01.00" -androidxComposeCompiler = "1.4.4" +androidxComposeCompiler = "1.4.5" androidxComposeMaterial3 = "1.1.0-alpha06" androidxComposeRuntimeTracing = "1.0.0-alpha01" androidxCore = "1.9.0" @@ -37,11 +37,11 @@ hilt = "2.44.2" hiltExt = "1.0.0" jacoco = "0.8.7" junit4 = "4.13.2" -kotlin = "1.8.10" +kotlin = "1.8.20" kotlinxCoroutines = "1.6.4" kotlinxDatetime = "0.4.0" kotlinxSerializationJson = "1.5.0" -ksp = "1.8.10-1.0.9" +ksp = "1.8.20-1.0.11" lint = "30.3.1" okhttp = "4.10.0" protobuf = "3.21.12" diff --git a/sync/work/src/main/java/com/google/samples/apps/nowinandroid/sync/services/SyncNotificationsService.kt b/sync/work/src/main/java/com/google/samples/apps/nowinandroid/sync/services/SyncNotificationsService.kt index 1d182dda1..e51e30164 100644 --- a/sync/work/src/main/java/com/google/samples/apps/nowinandroid/sync/services/SyncNotificationsService.kt +++ b/sync/work/src/main/java/com/google/samples/apps/nowinandroid/sync/services/SyncNotificationsService.kt @@ -19,10 +19,11 @@ package com.google.samples.apps.nowinandroid.sync.services import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage import com.google.samples.apps.nowinandroid.core.data.util.SyncManager -import com.google.samples.apps.nowinandroid.sync.initializers.SYNC_TOPIC import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject +private const val SYNC_TOPIC_SENDER = "/topics/sync" + @AndroidEntryPoint class SyncNotificationsService : FirebaseMessagingService() { @@ -30,7 +31,7 @@ class SyncNotificationsService : FirebaseMessagingService() { lateinit var syncManager: SyncManager override fun onMessageReceived(message: RemoteMessage) { - if (SYNC_TOPIC == message.from) { + if (SYNC_TOPIC_SENDER == message.from) { syncManager.requestSync() } }