Files
capod/app/build.gradle.kts
T
darken 43740d8b2e chore(build): Enable R8 obfuscation for the Google Play flavor
Google Play scores the obfuscation share of uploaded bundles and flags
listings below its threshold ("App optimisation is below our threshold",
fix by Feb 2027). Minify and shrink were already on; the shared
-dontobfuscate was the only thing keeping the score at 0%.

-dontobfuscate moves to a FOSS-only rule file; the Play rule file keeps
SourceFile/LineNumberTable for retracing and pins names only where they
reach users or logs: AapSetting/AapCommand subclasses (session logs),
ViewModel1 subclasses (log tag), Throwables (error dialog label). All
reflective targets (BuildConfig, ArtMirror, NeverCall, InvokeStub,
AncModeActionCallback) already carry @Keep or explicit keeps and are
identity-mapped in the gplayRelease mapping. The release workflow
archives the mapping next to the Play upload.
2026-09-06 10:41:37 +02:00

216 lines
7.2 KiB
Kotlin

plugins {
id("projectConfig")
id("com.android.application")
id("kotlin-android")
id("com.google.devtools.ksp")
id("kotlin-parcelize")
id("org.jetbrains.kotlin.plugin.compose")
id("org.jetbrains.kotlin.plugin.serialization")
id("com.android.compose.screenshot") version "0.0.1-alpha13"
}
apply(plugin = "dagger.hilt.android.plugin")
android {
compileSdk = projectConfig.compileSdk
defaultConfig {
namespace = projectConfig.packageName
minSdk = projectConfig.minSdk
targetSdk = projectConfig.targetSdk
versionCode = projectConfig.version.code.toInt()
versionName = projectConfig.version.name
testInstrumentationRunner = "eu.darken.capod.HiltTestRunner"
buildConfigField("String", "PACKAGENAME", "\"${projectConfig.packageName}\"")
buildConfigField("String", "VERSION_CODE", "\"${projectConfig.version.code}\"")
buildConfigField("String", "VERSION_NAME", "\"${projectConfig.version.name}\"")
}
// Enable automatic per-app language preferences generation
androidResources {
@Suppress("UnstableApiUsage")
generateLocaleConfig = true
}
signingConfigs {
val basePath = File(System.getProperty("user.home"), ".config/projects/${projectConfig.packageName}")
create("releaseFoss") {
setupCredentials(File(basePath, "signing-foss.properties"))
}
create("releaseGplay") {
setupCredentials(File(basePath, "signing-gplay-upload.properties"))
}
}
flavorDimensions.add("version")
productFlavors {
create("foss") {
dimension = "version"
signingConfig = signingConfigs["releaseFoss"]
// The info block is encrypted and can only be read by google
dependenciesInfo {
includeInApk = false
includeInBundle = false
}
proguardFiles("proguard-rules-foss.pro")
}
create("gplay") {
dimension = "version"
signingConfig = signingConfigs["releaseGplay"]
proguardFiles("proguard-rules-gplay.pro")
}
}
buildTypes {
val customProguardRules = fileTree(File(projectDir, "proguard")) {
include("*.pro")
}
debug {
isMinifyEnabled = false
isShrinkResources = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"))
proguardFiles(*customProguardRules.toList().toTypedArray())
proguardFiles("proguard-rules-debug.pro")
}
create("beta") {
lint {
abortOnError = true
fatal.add("StopShip")
}
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"))
proguardFiles(*customProguardRules.toList().toTypedArray())
}
release {
lint {
abortOnError = true
fatal.add("StopShip")
}
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"))
proguardFiles(*customProguardRules.toList().toTypedArray())
}
}
experimentalProperties["android.experimental.enableScreenshotTest"] = true
buildFeatures {
viewBinding = true
buildConfig = true
compose = true
}
compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
freeCompilerArgs = freeCompilerArgs + listOf(
"-opt-in=kotlin.ExperimentalStdlibApi",
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
"-opt-in=kotlinx.coroutines.FlowPreview",
"-opt-in=kotlin.time.ExperimentalTime",
"-opt-in=kotlin.RequiresOptIn",
"-opt-in=kotlin.ExperimentalUnsignedTypes",
"-opt-in=androidx.compose.material3.ExperimentalMaterial3Api",
"-Xannotation-default-target=param-property"
)
}
testOptions {
unitTests {
isIncludeAndroidResources = true
}
//noinspection WrongGradleMethod
tasks.withType<Test> {
useJUnitPlatform()
maxHeapSize = "4g"
}
}
}
androidComponents {
onVariants { variant ->
val buildType = variant.buildType ?: return@onVariants
if (buildType != "release" && buildType != "beta") return@onVariants
val formattedVariantName = variant.name
.replace(Regex("([a-z])([A-Z])"), "$1-$2")
.uppercase()
val apkFolder = variant.artifacts.get(com.android.build.api.artifact.SingleArtifact.APK)
val loader = variant.artifacts.getBuiltArtifactsLoader()
val packageName = projectConfig.packageName
val renameTask = tasks.register("rename${variant.name.replaceFirstChar { it.uppercase() }}Apk") {
inputs.files(apkFolder)
outputs.upToDateWhen { false }
doLast {
val builtArtifacts = loader.load(apkFolder.get()) ?: return@doLast
builtArtifacts.elements.forEach { element ->
val apkFile = File(element.outputFile)
val outputFileName = "$packageName-v${element.versionName}-${element.versionCode}-$formattedVariantName.apk"
if (apkFile.exists() && apkFile.name != outputFileName) {
apkFile.copyTo(File(apkFile.parentFile, outputFileName), overwrite = true)
}
}
}
}
tasks.matching { it.name == "assemble${variant.name.replaceFirstChar { it.uppercase() }}" }.configureEach {
finalizedBy(renameTask)
}
}
}
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5")
addBaseKotlin()
addDagger()
addOkio()
addBaseAndroid()
addBaseAndroidUi()
implementation("androidx.core:core-splashscreen:1.0.0-alpha02")
addNavigation()
addCompose()
addGlance()
addWorkerManager()
addDataStore()
addNavigation3()
addSerialization()
addTesting()
"gplayImplementation"("com.android.billingclient:billing:8.3.0")
"gplayImplementation"("com.android.billingclient:billing-ktx:8.3.0")
"gplayImplementation"("com.google.android.play:review:2.0.2")
"gplayImplementation"("com.google.android.play:review-ktx:2.0.2")
// Robolectric-backed Compose UI tests (run as regular unit tests via the vintage engine).
testImplementation(platform("androidx.compose:compose-bom:${Versions.Compose.bom}"))
testImplementation("androidx.compose.ui:ui-test-junit4")
testImplementation("androidx.compose.ui:ui-test-manifest")
testImplementation("org.robolectric:robolectric:4.15.1")
"screenshotTestImplementation"(platform("androidx.compose:compose-bom:${Versions.Compose.bom}"))
"screenshotTestImplementation"("com.android.tools.screenshot:screenshot-validation-api:0.0.1-alpha13")
"screenshotTestImplementation"("androidx.compose.ui:ui-tooling")
}