import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { id("com.android.application") id("org.jetbrains.kotlin.android") id("org.jetbrains.kotlin.plugin.compose") id("org.jetbrains.kotlin.plugin.serialization") id("com.google.dagger.hilt.android") kotlin("kapt") } // Only the production release uses the Firebase app registered as de.yourpart.nativeapp. // Local/staging builds have different application IDs and deliberately stay push-free. val isProductionReleaseBuild = gradle.startParameter.taskNames.any { it.contains("productionrelease", ignoreCase = true) } if (isProductionReleaseBuild && file("google-services.json").isFile) { apply(plugin = "com.google.gms.google-services") } val gitShaProvider = providers.exec { workingDir = rootDir.resolve("../..") commandLine("git", "rev-parse", "--short=12", "HEAD") }.standardOutput.asText.map { it.trim().ifBlank { "dev" } } val gitSha: String = runCatching { gitShaProvider.get() }.getOrDefault("dev") data class EnvironmentConfig( val apiBaseUrl: String, val socketIoUrl: String, val daemonSocketUrl: String, val cleartextAllowed: Boolean, ) val environmentConfigs = mapOf( "local" to EnvironmentConfig( apiBaseUrl = "http://10.0.2.2:2020", socketIoUrl = "http://10.0.2.2:2020", daemonSocketUrl = "ws://10.0.2.2:2021", cleartextAllowed = true, ), "staging" to EnvironmentConfig( apiBaseUrl = "https://staging.your-part.de", socketIoUrl = "https://staging.your-part.de", daemonSocketUrl = "wss://staging.your-part.de", cleartextAllowed = false, ), "production" to EnvironmentConfig( apiBaseUrl = "https://www.your-part.de", socketIoUrl = "https://www.your-part.de", daemonSocketUrl = "wss://www.your-part.de", cleartextAllowed = false, ), ) android { namespace = "de.yourpart.nativeapp" compileSdk = 36 defaultConfig { applicationId = "de.yourpart.nativeapp" minSdk = 26 targetSdk = 36 versionCode = 1 versionName = "0.1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" buildConfigField("String", "GIT_SHA", "\"$gitSha\"") } flavorDimensions += "environment" productFlavors { create("local") { dimension = "environment" applicationIdSuffix = ".local" versionNameSuffix = "-local" val cfg = environmentConfigs.getValue(name) buildConfigField("String", "ENVIRONMENT", "\"$name\"") buildConfigField("String", "API_BASE_URL", "\"${cfg.apiBaseUrl}\"") buildConfigField("String", "SOCKET_IO_URL", "\"${cfg.socketIoUrl}\"") buildConfigField("String", "DAEMON_SOCKET_URL", "\"${cfg.daemonSocketUrl}\"") buildConfigField("boolean", "ALLOW_CLEARTEXT", cfg.cleartextAllowed.toString()) } create("staging") { dimension = "environment" applicationIdSuffix = ".staging" versionNameSuffix = "-staging" val cfg = environmentConfigs.getValue(name) buildConfigField("String", "ENVIRONMENT", "\"$name\"") buildConfigField("String", "API_BASE_URL", "\"${cfg.apiBaseUrl}\"") buildConfigField("String", "SOCKET_IO_URL", "\"${cfg.socketIoUrl}\"") buildConfigField("String", "DAEMON_SOCKET_URL", "\"${cfg.daemonSocketUrl}\"") buildConfigField("boolean", "ALLOW_CLEARTEXT", cfg.cleartextAllowed.toString()) } create("production") { dimension = "environment" val cfg = environmentConfigs.getValue(name) buildConfigField("String", "ENVIRONMENT", "\"$name\"") buildConfigField("String", "API_BASE_URL", "\"${cfg.apiBaseUrl}\"") buildConfigField("String", "SOCKET_IO_URL", "\"${cfg.socketIoUrl}\"") buildConfigField("String", "DAEMON_SOCKET_URL", "\"${cfg.daemonSocketUrl}\"") buildConfigField("boolean", "ALLOW_CLEARTEXT", cfg.cleartextAllowed.toString()) } } buildTypes { debug { applicationIdSuffix = ".debug" versionNameSuffix = "-debug" buildConfigField("boolean", "IS_RELEASE_BUILD", "false") buildConfigField("boolean", "FEATURE_ADMIN", "false") buildConfigField("boolean", "FEATURE_ADULT", "true") buildConfigField("boolean", "FEATURE_3D", "false") buildConfigField("boolean", "FEATURE_MINIGAMES", "false") buildConfigField("boolean", "FEATURE_PUSH", "false") } release { isMinifyEnabled = false buildConfigField("boolean", "IS_RELEASE_BUILD", "true") buildConfigField("boolean", "FEATURE_ADMIN", "false") buildConfigField("boolean", "FEATURE_ADULT", "false") buildConfigField("boolean", "FEATURE_3D", "false") buildConfigField("boolean", "FEATURE_MINIGAMES", "false") buildConfigField("boolean", "FEATURE_PUSH", "true") proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro", ) } } buildFeatures { buildConfig = true compose = true } packaging { resources { excludes += "META-INF/versions/9/OSGI-INF/MANIFEST.MF" } } testOptions { managedDevices { devices { create("mediumPhone") { device = "Medium Phone" apiLevel = 34 systemImageSource = "google" } create("mediumTablet") { device = "Medium Tablet" apiLevel = 34 systemImageSource = "google" } } } } lint { abortOnError = true checkReleaseBuilds = true } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } kotlin { compilerOptions { jvmTarget.set(JvmTarget.JVM_17) } } } kapt { arguments { arg("room.schemaLocation", "$projectDir/schemas") } } val validateReleaseConfig by tasks.registering { doLast { environmentConfigs .filterKeys { it != "local" } .forEach { (name, cfg) -> require(cfg.apiBaseUrl.startsWith("https://")) { "Release flavor '$name' must use HTTPS API URL, got ${cfg.apiBaseUrl}" } require(cfg.socketIoUrl.startsWith("https://")) { "Release flavor '$name' must use HTTPS Socket.IO URL, got ${cfg.socketIoUrl}" } require(cfg.daemonSocketUrl.startsWith("wss://")) { "Release flavor '$name' must use WSS daemon URL, got ${cfg.daemonSocketUrl}" } require(!cfg.apiBaseUrl.contains("10.0.2.2") && !cfg.apiBaseUrl.contains("localhost")) { "Release flavor '$name' must not use local API URL, got ${cfg.apiBaseUrl}" } } } } tasks.matching { task -> task.name.startsWith("assemble") && task.name.endsWith("Release") }.configureEach { dependsOn(validateReleaseConfig) } dependencies { implementation("androidx.core:core-ktx:1.17.0") implementation("androidx.activity:activity-compose:1.13.0") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.10.0") implementation("androidx.lifecycle:lifecycle-runtime-compose:2.10.0") implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.10.0") implementation("androidx.security:security-crypto:1.1.0-alpha06") implementation("androidx.navigation:navigation-compose:2.9.6") implementation("androidx.browser:browser:1.9.0") implementation("androidx.hilt:hilt-navigation-compose:1.3.0") implementation("androidx.compose.material3:material3:1.4.0") implementation("androidx.compose.material:material-icons-extended:1.4.1") implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-tooling-preview") debugImplementation("androidx.compose.ui:ui-tooling") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0") implementation("com.squareup.retrofit2:retrofit:3.0.0") implementation("com.squareup.okhttp3:okhttp:5.3.2") implementation("com.squareup.okhttp3:logging-interceptor:5.3.2") implementation("io.socket:socket.io-client:2.1.0") implementation("com.google.dagger:hilt-android:2.57.2") kapt("com.google.dagger:hilt-android-compiler:2.57.2") implementation("androidx.room:room-runtime:2.8.0") implementation("androidx.room:room-ktx:2.8.0") kapt("androidx.room:room-compiler:2.8.0") implementation("androidx.datastore:datastore-preferences:1.1.7") implementation("io.coil-kt:coil-compose:2.6.0") implementation("androidx.work:work-runtime-ktx:2.8.1") implementation("com.google.firebase:firebase-messaging:24.1.2") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.10.2") testImplementation("junit:junit:4.13.2") testImplementation("com.squareup.okhttp3:mockwebserver:5.3.2") testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.10.2") androidTestImplementation("androidx.test.ext:junit:1.3.0") androidTestImplementation("androidx.test:runner:1.7.0") androidTestImplementation("androidx.test:rules:1.7.0") androidTestImplementation("androidx.test.espresso:espresso-core:3.7.0") androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.9.4") debugImplementation("androidx.compose.ui:ui-test-manifest:1.9.4") androidTestImplementation("androidx.room:room-testing:2.8.0") androidTestImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.10.2") }