import java.net.URI import org.gradle.api.tasks.compile.JavaCompile plugins { id("com.android.application") } val releaseBaseUrl = providers.gradleProperty("WNH_BASE_URL").orElse("") val debugBaseUrl = providers.gradleProperty("WNH_DEBUG_BASE_URL").orElse("") val trackingMinTimeMs = providers.gradleProperty("WNH_TRACKING_MIN_TIME_MS").orElse("0") val trackingHttpTimeoutMs = providers.gradleProperty("WNH_TRACKING_HTTP_TIMEOUT_MS").orElse("0") fun manifestOrigin(value: String): URI? = runCatching { URI(value) } .getOrNull() ?.takeIf { uri -> (uri.scheme == "http" || uri.scheme == "https") && !uri.host.isNullOrBlank() } val debugManifestOrigin = manifestOrigin(debugBaseUrl.get()) val releaseManifestOrigin = manifestOrigin(releaseBaseUrl.get()) android { namespace = "org.whoneedhelp.mobile" compileSdk = 37 buildToolsVersion = "37.0.0" defaultConfig { applicationId = "org.whoneedhelp.mobile" minSdk = 24 targetSdk = 37 versionCode = 1 versionName = "0.1.0" buildConfigField("long", "TRACKING_MIN_TIME_MS", "${trackingMinTimeMs.get()}L") buildConfigField( "long", "TRACKING_HTTP_TIMEOUT_MS", "${trackingHttpTimeoutMs.get()}L" ) testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } buildTypes { debug { applicationIdSuffix = ".debug" versionNameSuffix = "-debug" buildConfigField( "String", "BASE_URL", "\"${debugBaseUrl.get().replace("\\", "\\\\").replace("\"", "\\\"")}\"" ) manifestPlaceholders["usesCleartextTraffic"] = "true" manifestPlaceholders["deepLinkScheme"] = debugManifestOrigin?.scheme ?: "https" manifestPlaceholders["deepLinkHost"] = debugManifestOrigin?.host ?: "invalid.whoneedhelp.local" } create("staging") { initWith(getByName("debug")) applicationIdSuffix = ".staging" versionNameSuffix = "-staging" buildConfigField( "String", "BASE_URL", "\"${releaseBaseUrl.get().replace("\\", "\\\\").replace("\"", "\\\"")}\"" ) manifestPlaceholders["usesCleartextTraffic"] = "false" manifestPlaceholders["deepLinkScheme"] = releaseManifestOrigin?.scheme ?: "https" manifestPlaceholders["deepLinkHost"] = releaseManifestOrigin?.host ?: "invalid.whoneedhelp.local" matchingFallbacks += listOf("debug") } release { isMinifyEnabled = true isShrinkResources = true buildConfigField( "String", "BASE_URL", "\"${releaseBaseUrl.get().replace("\\", "\\\\").replace("\"", "\\\"")}\"" ) manifestPlaceholders["usesCleartextTraffic"] = "false" manifestPlaceholders["deepLinkScheme"] = releaseManifestOrigin?.scheme ?: "https" manifestPlaceholders["deepLinkHost"] = releaseManifestOrigin?.host ?: "invalid.whoneedhelp.local" proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) } } buildFeatures { buildConfig = true } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } testOptions { unitTests.isIncludeAndroidResources = false } } tasks.matching { it.name == "preReleaseBuild" || it.name == "preStagingBuild" }.configureEach { doFirst { val value = releaseBaseUrl.orNull.orEmpty() val uri = runCatching { URI(value) }.getOrNull() if ( uri == null || uri.scheme != "https" || uri.host.isNullOrBlank() || uri.userInfo != null || uri.query != null || uri.fragment != null ) { throw GradleException( "Staging and release builds require " + "-PWNH_BASE_URL=https://your-real-deployment.example" ) } validateTrackingConfiguration() } } tasks.matching { it.name == "preDebugBuild" }.configureEach { doFirst { val value = debugBaseUrl.orNull.orEmpty() val uri = runCatching { URI(value) }.getOrNull() if ( uri == null || (uri.scheme != "http" && uri.scheme != "https") || uri.host.isNullOrBlank() || uri.userInfo != null || uri.query != null || uri.fragment != null ) { throw GradleException( "Debug builds require -PWNH_DEBUG_BASE_URL=http(s)://your-development-host" ) } validateTrackingConfiguration() } } fun validateTrackingConfiguration() { val minTime = trackingMinTimeMs.orNull?.toLongOrNull() val httpTimeout = trackingHttpTimeoutMs.orNull?.toLongOrNull() if (minTime == null || minTime <= 0) { throw GradleException( "Builds require -PWNH_TRACKING_MIN_TIME_MS=POSITIVE_MILLISECONDS" ) } if (httpTimeout == null || httpTimeout <= 0 || httpTimeout > Int.MAX_VALUE) { throw GradleException( "Builds require -PWNH_TRACKING_HTTP_TIMEOUT_MS=POSITIVE_INT_MILLISECONDS" ) } } tasks.withType().configureEach { options.compilerArgs.add("-Xlint:deprecation") } dependencies { implementation("androidx.activity:activity:1.13.0") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test:core:1.7.0") androidTestImplementation("androidx.test:runner:1.7.0") androidTestImplementation("androidx.test:rules:1.7.0") androidTestImplementation("androidx.test.ext:junit:1.3.0") androidTestImplementation("androidx.test.espresso:espresso-core:3.7.0") androidTestImplementation("androidx.test.espresso:espresso-web:3.7.0") androidTestImplementation("androidx.test.uiautomator:uiautomator:2.4.0") }