import java.util.Properties plugins { id("com.android.application") id("org.jetbrains.kotlin.plugin.compose") id("com.google.devtools.ksp") } // ── Signature RELEASE (v1.9.8) ────────────────────────────────────────────── // keystore.properties (RACINE du dépôt, GITIGNORÉ) décrit le vrai keystore : // storeFile=release.keystore (chemin relatif à la racine du dépôt) // storePassword=… // keyAlias=… // keyPassword=… // Tant que ce fichier est ABSENT, la build release reste signée avec la clé // DEBUG (comportement historique : installation par-dessus l'APK debug sans // perte de données, cf §16.quater). Dès qu'il existe (créé par // scripts/make-release-keystore.sh), la build release l'utilise — ⚠️ signature // différente ⇒ migration obligatoire : export JSON → désinstallation → // réinstallation → réimport (documenté §16.quater). val keystorePropertiesFile = rootProject.file("keystore.properties") android { namespace = "com.hormonetrack" compileSdk = 37 defaultConfig { applicationId = "com.hormonetrack" minSdk = 26 targetSdk = 36 // ⚠️ MÉTADONNÉES DE VERSION — bump obligatoire à CHAQUE release // (checklist §16 étape 1 de docs/DEVELOPPEMENT.md), committé AVANT le // tag : v1.3.0→v1.3.2 contenaient tous versionCode 14 / "1.3.0" // (bump jamais commité) → BuildConfig.VERSION_NAME était faux dans // les APK publiés (Paramètres + titre du dialog « Nouveautés »). versionCode = 50 versionName = "1.13.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary = true } } buildTypes { release { // Optimisations R8 + shrink des ressources (le cœur du gain debug→release) isMinifyEnabled = true isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) // Signature : VRAI keystore si keystore.properties existe (racine du // dépôt, gitignoré — créé par scripts/make-release-keystore.sh) ; // sinon CLÉ DEBUG volontairement : l'APK release reste installable // PAR-DESSUS l'APK debug déjà installé (même signature), sans // désinstallation ni perte de données, tout en bénéficiant de R8. // ⚠️ Passer au vrai keystore CHANGE la signature : migration // backup→désinstall→réimport requise sur le téléphone (§16.quater). signingConfig = if (keystorePropertiesFile.exists()) { val props = Properties().apply { keystorePropertiesFile.inputStream().use { load(it) } } signingConfigs.create("release") { storeFile = rootProject.file(props.getProperty("storeFile")) storePassword = props.getProperty("storePassword") keyAlias = props.getProperty("keyAlias") keyPassword = props.getProperty("keyPassword") } signingConfigs.getByName("release") } else { signingConfigs.getByName("debug") } } } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } buildFeatures { compose = true // BuildConfig.VERSION_NAME : écran Paramètres + dialog de changelog buildConfig = true } packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" } } // Lint (v1.3.4) : les checks Compose 1.12+ (NonObservableLocale, // LocalContextGetResourceValueCall) sont rétrogradés en WARNING via // app/lint.xml (meilleure compatibilité que la DSL AGP) — cas THÉORIQUES de staleness de // configuration présents dans tout le code v1, jamais à l'origine des // crashs remontés. Les vrais problèmes de format de strings // (StringFormatMatches — aurait attrapé les bugs #47/#48, épinglés §14) // restent des ERREURS bloquantes. Re-traiter ces warnings lors d'une // refonte i18n (cf §20). } // Synchronise docs/CHANGELOG.md → src/main/assets/changelog.md (dialog // « Nouveautés » affiché après chaque mise à jour). Automatique à chaque // build ; le fichier généré est gitignoré (source de vérité = docs/). tasks.register("copyChangelog") { from(rootProject.file("docs/CHANGELOG.md")) into(file("src/main/assets")) rename { "changelog.md" } } tasks.named("preBuild") { dependsOn("copyChangelog") } dependencies { // BOM Compose : épingle toutes les versions des artefacts androidx.compose.* // (material3 >= 1.4 = Material 3 Expressive) val composeBom = platform("androidx.compose:compose-bom:2026.08.00") implementation(composeBom) // Core implementation("androidx.core:core-ktx:1.19.0") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.11.0") implementation("androidx.activity:activity-compose:1.13.0") // Compose UI implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.compose.material3:material3") implementation("androidx.compose.material:material-icons-extended") // Navigation implementation("androidx.navigation:navigation-compose:2.10.0") // AppCompat (langue par app sur API < 33) implementation("androidx.appcompat:appcompat:1.8.0") // Room implementation("androidx.room:room-runtime:2.8.4") implementation("androidx.room:room-ktx:2.8.4") ksp("androidx.room:room-compiler:2.8.4") // DataStore (préférences) implementation("androidx.datastore:datastore-preferences:1.2.1") // WorkManager (UTILISÉ v1.4.2 : worker périodique des seuils d'alerte, cf §9.bis) implementation("androidx.work:work-runtime-ktx:2.11.2") // Coroutines implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1") // Gson (backup JSON + parsing de l'asset de profils) implementation("com.google.code.gson:gson:2.14.0") // Debug debugImplementation("androidx.compose.ui:ui-tooling") debugImplementation("androidx.compose.ui:ui-test-manifest") // Tests unitaires JVM testImplementation("junit:junit:4.13.2") // ── Tests UI Compose (v1.9.8, androidTest — cf docs/DEVELOPPEMENT.md §8.ter) ── // Exécution : ./gradlew connectedDebugAndroidTest (émulateur/appareil requis). // Le BOM est réappliqué sur la configuration androidTest pour épinner les // mêmes versions que le runtime Compose de l'app. androidTestImplementation(composeBom) androidTestImplementation("androidx.compose.ui:ui-test-junit4") androidTestImplementation("androidx.test.ext:junit-ktx:1.3.0") // JUnit explicite (org.junit.Rule/@Test) — ne pas compter sur le transitif androidTestImplementation("junit:junit:4.13.2") // UiDevice (pressBack pour fermer les dialogs — v1.10.0, LogDoseRequestTest) androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0") }