import java.util.Properties import java.io.FileInputStream plugins { id("com.android.application") id("kotlin-android") // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. id("dev.flutter.flutter-gradle-plugin") } // Release signing is opt-in: drop a `key.properties` (gitignored) next to this // module's android/ dir to sign release builds with your own keystore. Without // it, release builds fall back to debug keys so contributors can still run // `flutter run --release`. See docs/release.md. val keystoreProperties = Properties() val keystorePropertiesFile = rootProject.file("key.properties") val hasReleaseKeystore = keystorePropertiesFile.exists() if (hasReleaseKeystore) { keystoreProperties.load(FileInputStream(keystorePropertiesFile)) } android { namespace = "org.comunes.tane" compileSdk = flutter.compileSdkVersion ndkVersion = flutter.ndkVersion compileOptions { // Required by flutter_local_notifications (uses Java 8+ APIs on older SDKs). isCoreLibraryDesugaringEnabled = true sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } kotlinOptions { jvmTarget = JavaVersion.VERSION_17.toString() } defaultConfig { applicationId = "org.comunes.tane" // You can update the following values to match your application needs. // For more information, see: https://flutter.dev/to/review-gradle-config. minSdk = flutter.minSdkVersion targetSdk = flutter.targetSdkVersion versionCode = flutter.versionCode versionName = flutter.versionName } signingConfigs { if (hasReleaseKeystore) { create("release") { keyAlias = keystoreProperties["keyAlias"] as String keyPassword = keystoreProperties["keyPassword"] as String storeFile = keystoreProperties["storeFile"]?.let { file(it) } storePassword = keystoreProperties["storePassword"] as String } } } dependenciesInfo { // No Google-encrypted dependency-metadata block in the APK/AAB // signature: F-Droid rejects it, and Play does not require it. includeInApk = false includeInBundle = false } buildTypes { release { // Sign with the real release keystore when key.properties is present, // otherwise fall back to debug keys so `flutter run --release` works // for contributors without the signing material. signingConfig = if (hasReleaseKeystore) { signingConfigs.getByName("release") } else { signingConfigs.getByName("debug") } // R8: shrink + optimize + obfuscate the Java/Kotlin bytecode and strip // unused resources — Play's "app optimization" recommendation (smaller // download, less memory). Native .so libs are untouched, so this does // not change device/ABI compatibility. Keep rules for reflection/JNI // heavy deps (OCR, SQLCipher, notifications) live in proguard-rules.pro. isMinifyEnabled = true isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro", ) } } } flutter { source = "../.." } dependencies { // Backport of Java 8+ APIs, required by flutter_local_notifications. coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4") } // F-Droid: Flutter's embedding transitively pulls Google Play Core (deferred // components / split install — com.google.android.play.core.*), which F-Droid's // scanner rejects as a proprietary Google dependency. Tane does not use deferred // components, so drop the whole com.google.android.play group; those split-install // code paths are never reached. R8 keeps the referenced classes otherwise, so the // exclusion (not shrinking) is what removes them; -dontwarn in proguard-rules.pro // silences the now-dangling compile-time references. configurations.all { exclude(group = "com.google.android.play") } // F-Droid builds one split APK per ABI (smaller downloads than a universal // APK) and needs each split to carry a distinct versionCode so its repo can // tell them apart; `flutter build apk --split-per-abi` alone gives every // split the same versionCode. This override only touches the APK // (applicationVariants) output, not the App Bundle Google Play consumes, so // Play's per-device delivery is unaffected. val abiVersionCodes = mapOf("armeabi-v7a" to 1, "arm64-v8a" to 2, "x86_64" to 3) android.applicationVariants.all { val variant = this variant.outputs.all { val output = this as com.android.build.gradle.internal.api.ApkVariantOutputImpl val abi = output.getFilter(com.android.build.OutputFile.ABI) abiVersionCodes[abi]?.let { abiCode -> output.versionCodeOverride = variant.versionCode * 10 + abiCode } } }