// SPDX-FileCopyrightText: 2026 Echolot contributors // SPDX-License-Identifier: GPL-3.0-or-later plugins { // AGP 9 built-in Kotlin — no kotlin.android here (see core-probe note). alias(libs.plugins.android.application) alias(libs.plugins.kotlin.compose) alias(libs.plugins.kotlin.serialization) } // The app's version is SemVer and lives here, once. versionCode is derived from it rather than // maintained alongside: Play/F-Droid need a monotonically increasing integer, but a second number // that a human has to remember to bump is a number that eventually disagrees with the first — and // the version is now load-bearing, since the server decides whether to serve us by it. // // major*1_000_000 + minor*10_000 + patch*10 leaves room for 9 patch-level rebuilds (the trailing // digit) without disturbing the mapping, and stays inside the 2_100_000_000 ceiling until major 2100. val appVersionName = "0.2.0" fun versionCodeOf(semver: String): Int { val (major, minor, patch) = semver.substringBefore('-').split(".").map(String::toInt) return major * 1_000_000 + minor * 10_000 + patch * 10 } android { namespace = "app.echo_lot.app" compileSdk = 36 defaultConfig { applicationId = "app.echo_lot.app" minSdk = 26 targetSdk = 36 versionCode = versionCodeOf(appVersionName) versionName = appVersionName // Automation: `adb shell am start -n app.echo_lot.app/.MainActivity --ez autorun true` // runs a measurement immediately and POSTs the report here (dev collection endpoint). // Empty: the collection endpoint this pointed at was the adb-beacon receiver, which held // 0.0.0.0:443 in cleartext. That service is gone and echolot-server owns 443 with TLS, so // posting plaintext there now fails as "client sent an HTTP request to an HTTPS server" — // an alarming error for a debugging convenience that is no longer needed, since autorun // reports are read straight off the device with `run-as cat`. // // Deliberately not repointed at /v1/runs. That is the consent-gated upload, and a // debugging shortcut must not be able to satisfy it by accident. buildConfigField("String", "REPORT_UPLOAD_URL", "\"\"") buildConfigField("String", "REPORT_UPLOAD_SECRET", "\"\"") // The bare SemVer, without the debug build's "-dev" suffix stripped away by the server's // parser anyway — sent to servers so they can apply their compatibility window. buildConfigField("String", "APP_SEMVER", "\"$appVersionName\"") } buildTypes { release { isMinifyEnabled = false } debug { // The dev build is a separate app: own package (installs alongside a real // Echolot), own label and a DEV-badged icon (src/debug/res). applicationIdSuffix = ".dev" versionNameSuffix = "-dev" } } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } buildFeatures { compose = true buildConfig = true } } dependencies { implementation(project(":core-measurement")) implementation(project(":core-protocol")) implementation(project(":core-engine")) implementation(project(":core-probe")) implementation(project(":core-shizuku")) implementation(project(":core-privacy")) implementation(project(":core-archive")) implementation(libs.kotlinx.serialization.json) implementation(libs.kotlinx.coroutines.android) implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.lifecycle.viewmodel.compose) implementation(libs.androidx.activity.compose) implementation(platform(libs.androidx.compose.bom)) implementation(libs.androidx.ui) implementation(libs.androidx.ui.graphics) implementation(libs.androidx.ui.tooling.preview) implementation(libs.androidx.material3) debugImplementation(libs.androidx.ui.tooling) }