diff --git a/README.md b/README.md index 20a996b15..9712a6e8e 100644 --- a/README.md +++ b/README.md @@ -52,18 +52,26 @@ and is described in detail in the # Build -The `debug` variant of `app` uses local data to allow immediate building and exploring the UI. +The app contains the usual `debug` and `release` build variants. -The `staging` and `release` variants of `app` make real network calls to a backend server, providing -up-to-date data as new episodes of Now in Android are released. At this time, there is not a -public backend available. - -The `benchmark` variant of `app` is used to test startup performance and generate a baseline profile -(see below for more information). +In addition, the `benchmark` variant of `app` is used to test startup performance and generate a +baseline profile (see below for more information). `app-nia-catalog` is a standalone app that displays the list of components that are stylized for Now in Android. +The app also uses +[product flavors](https://developer.android.com/studio/build/build-variants#product-flavors) to +control where content for the app should be loaded from. + +The `demo` flavor uses static local data to allow immediate building and exploring the UI. + +The `prod` flavor makes real network calls to a backend server, providing up-to-date content. At +this time, there is not a public backend available. + +For normal development use the `demoDebug` variant. For UI performance testing use the +`demoRelease` variant. + # Testing To facilitate testing of components, Now in Android uses dependency injection with diff --git a/app-nia-catalog/build.gradle.kts b/app-nia-catalog/build.gradle.kts index 8ab94c29f..28edda383 100644 --- a/app-nia-catalog/build.gradle.kts +++ b/app-nia-catalog/build.gradle.kts @@ -22,6 +22,10 @@ plugins { android { defaultConfig { applicationId = "com.google.samples.apps.niacatalog" + + // The UI catalog does not depend on content from the app, however, it depends on modules + // which do, so we must specify a default value for the contentType dimension. + missingDimensionStrategy("contentType", "demo") } packagingOptions { diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 15405e118..0315806a4 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import com.google.samples.apps.nowinandroid.FlavorDimension +import com.google.samples.apps.nowinandroid.Flavor + plugins { id("nowinandroid.android.application") id("nowinandroid.android.application.compose") @@ -43,6 +46,11 @@ android { val release by getting { isMinifyEnabled = true proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + + // 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. + signingConfig = signingConfigs.getByName("debug") } val benchmark by creating { initWith(release) @@ -50,13 +58,21 @@ android { matchingFallbacks.add("release") proguardFiles("benchmark-rules.pro") } - val staging by creating { - initWith(debug) - signingConfig = signingConfigs.getByName("debug") - matchingFallbacks.add("debug") - applicationIdSuffix = ".staging" + } + + // @see Flavor for more details on the app product flavors. + flavorDimensions += FlavorDimension.contentType.name + productFlavors { + Flavor.values().forEach { + create(it.name) { + dimension = it.dimension.name + if (it.applicationIdSuffix != null) { + applicationIdSuffix = it.applicationIdSuffix + } + } } } + packagingOptions { resources { excludes.add("/META-INF/{AL2.0,LGPL2.1}") diff --git a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Flavor.kt b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Flavor.kt new file mode 100644 index 000000000..cfcfe6956 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Flavor.kt @@ -0,0 +1,31 @@ +package com.google.samples.apps.nowinandroid + +import com.android.build.api.dsl.CommonExtension +import org.gradle.api.Project + +enum class FlavorDimension { + contentType +} + +// The content for the app can either come from local static data which is useful for demo +// purposes, or from a production backend server which supplies up-to-date, real content. +// These two product flavors reflect this behaviour. +enum class Flavor (val dimension : FlavorDimension, val applicationIdSuffix : String? = null) { + demo(FlavorDimension.contentType, ".demo"), + prod(FlavorDimension.contentType) +} + +fun Project.configureFlavors( + commonExtension: CommonExtension<*, *, *, *> +) { + commonExtension.apply { + flavorDimensions += FlavorDimension.contentType.name + productFlavors { + Flavor.values().forEach{ + create(it.name) { + dimension = it.dimension.name + } + } + } + } +} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/nowinandroid.android.library.gradle.kts b/build-logic/convention/src/main/kotlin/nowinandroid.android.library.gradle.kts index 2ddc4b01a..c13e0e0c8 100644 --- a/build-logic/convention/src/main/kotlin/nowinandroid.android.library.gradle.kts +++ b/build-logic/convention/src/main/kotlin/nowinandroid.android.library.gradle.kts @@ -14,6 +14,7 @@ * limitations under the License. */ +import com.google.samples.apps.nowinandroid.configureFlavors import com.google.samples.apps.nowinandroid.configureKotlinAndroid plugins { @@ -27,6 +28,8 @@ android { defaultConfig { targetSdk = 32 } + + configureFlavors(this) } val libs = extensions.getByType().named("libs") diff --git a/core-network/build.gradle.kts b/core-network/build.gradle.kts index 9b3303f4d..b629a16e0 100644 --- a/core-network/build.gradle.kts +++ b/core-network/build.gradle.kts @@ -23,22 +23,6 @@ plugins { id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") } -android { - buildTypes { - val staging by creating { - initWith(getByName("debug")) - matchingFallbacks.add("debug") - } - } - // Force the staging variant to use the release source directory. This is necessary so that the - // staging variant uses the remote network. - sourceSets { - getByName("staging") { - java.srcDir("src/release/java") - } - } -} - secrets { defaultPropertiesFileName = "secrets.defaults.properties" } diff --git a/core-network/src/debug/java/com/google/samples/apps/nowinandroid/core/network/di/NetworkModule.kt b/core-network/src/demo/java/com/google/samples/apps/nowinandroid/core/network/di/NetworkModule.kt similarity index 100% rename from core-network/src/debug/java/com/google/samples/apps/nowinandroid/core/network/di/NetworkModule.kt rename to core-network/src/demo/java/com/google/samples/apps/nowinandroid/core/network/di/NetworkModule.kt diff --git a/core-network/src/release/java/com/google/samples/apps/nowinandroid/core/network/di/NetworkModule.kt b/core-network/src/prod/java/com/google/samples/apps/nowinandroid/core/network/di/NetworkModule.kt similarity index 100% rename from core-network/src/release/java/com/google/samples/apps/nowinandroid/core/network/di/NetworkModule.kt rename to core-network/src/prod/java/com/google/samples/apps/nowinandroid/core/network/di/NetworkModule.kt diff --git a/kokoro/build.sh b/kokoro/build.sh index 0c3fdd84b..1d21ee299 100644 --- a/kokoro/build.sh +++ b/kokoro/build.sh @@ -62,8 +62,8 @@ run_firebase_test_lab() { while [ $result != 0 -a $counter -lt $MAX_RETRY ]; do gcloud firebase test android run \ --type instrumentation \ - --app "app/build/outputs/apk/debug/app-debug.apk" \ - --test "$module/build/outputs/apk/androidTest/debug/$module-debug-androidTest.apk" \ + --app "app/build/outputs/apk/demo/debug/app-demo-debug.apk" \ + --test "$module/build/outputs/apk/androidTest/demo/debug/$module-demo-debug-androidTest.apk" \ --device-ids $deviceIds \ --os-version-ids $osVersionIds \ --locales en \