V0.4.2
EBO <eric.bouhana@softalys.com> committé le 2026-09-12 19:08
9264de0d59b5eec2827a3ab1102f08867119bb97
1 parent(s)
3 fichiers modifiés
+72
-0
M
.gitignore
+3
-0
@@ -37,6 +37,9 @@ android/.kotlin/
| 37 | 37 | android/build/ |
| 38 | 38 | android/app/build/ |
| 39 | 39 | android/tessdata-cache/ |
| 40 | +# Signature release (à sauvegarder hors git : la même clé est requise pour toute mise à jour) | |
| 41 | +android/keystore/ | |
| 42 | +android/keystore.properties | |
| 40 | 43 | android/app/src/main/assets/tesseract/tessdata/*.traineddata |
| 41 | 44 | android/local.properties |
| 42 | 45 | android/.idea/ |
M
README.md
+37
-0
@@ -119,6 +119,43 @@ Pas de téléchargement réseau dans l’app pour les modèles OCR (hors sync op
| 119 | 119 | |
| 120 | 120 | APK debug filtré `arm64-v8a`. Pour émulateur x86, retirez temporairement `ndk.abiFilters` dans `app/build.gradle.kts`. |
| 121 | 121 | |
| 122 | +## Release signée (bêta-testeurs) | |
| 123 | + | |
| 124 | +La signature release est lue depuis `android/keystore.properties` (gitignoré), qui pointe vers le keystore `android/keystore/piclead-release.jks` (gitignoré aussi). Sans ce fichier, `assembleRelease` produit un APK **non signé**, ininstallable par les testeurs. | |
| 125 | + | |
| 126 | +> ⚠️ **Sauvegardez `keystore/piclead-release.jks` + `keystore.properties` hors git** (coffre, sauvegarde chiffrée). Toute mise à jour doit être signée avec la **même clé** : une clé perdue ou changée force les testeurs à désinstaller/réinstaller (perte des données locales). | |
| 127 | + | |
| 128 | +**Mise en place sur une nouvelle machine** (à partir du keystore sauvegardé) — format de `android/keystore.properties` : | |
| 129 | + | |
| 130 | +```properties | |
| 131 | +storeFile=keystore/piclead-release.jks | |
| 132 | +storePassword=… | |
| 133 | +keyAlias=piclead | |
| 134 | +keyPassword=… | |
| 135 | +``` | |
| 136 | + | |
| 137 | +**À chaque bêta :** | |
| 138 | + | |
| 139 | +```bash | |
| 140 | +cd android | |
| 141 | +# 1. Incrémenter versionCode (obligatoire pour qu'Android accepte la mise à jour) | |
| 142 | +# et versionName dans app/build.gradle.kts | |
| 143 | +# 2. Builder (mêmes variantes tessdata que le debug) | |
| 144 | +./gradlew :app:assembleRelease # fast (défaut) | |
| 145 | +./gradlew :app:assembleRelease -Ptessdata=full # full | |
| 146 | +# 3. Récupérer l'APK nommé d'après l'application | |
| 147 | +ls app/build/outputs/apk/release/PicLead-*-release.apk | |
| 148 | +``` | |
| 149 | + | |
| 150 | +Vérification optionnelle de la signature avant envoi : | |
| 151 | + | |
| 152 | +```bash | |
| 153 | +"$HOME"/Android/Sdk/build-tools/*/apksigner verify --print-certs \ | |
| 154 | + app/build/outputs/apk/release/PicLead-*-release.apk | |
| 155 | +``` | |
| 156 | + | |
| 157 | +Distribution : envoyez le fichier `PicLead-<version>-release.apk` tel quel (mail, lien) ; à l'installation, Android demandera d'autoriser l'installation depuis une source inconnue. | |
| 158 | + | |
| 122 | 159 | ## Build |
| 123 | 160 | |
| 124 | 161 | ```bash |
M
android/app/build.gradle.kts
+32
-0
@@ -1,4 +1,5 @@
| 1 | 1 | import java.net.URI |
| 2 | +import java.util.Properties | |
| 2 | 3 | |
| 3 | 4 | plugins { |
| 4 | 5 | id("com.android.application") |
@@ -19,6 +20,13 @@ val tessdataLanguages = listOf("fra", "deu", "eng", "spa", "por", "ita", "pol")
| 19 | 20 | val tessdataCacheDir = rootProject.layout.projectDirectory.dir("tessdata-cache/$tessdataVariant") |
| 20 | 21 | val tessdataGeneratedAssets = layout.buildDirectory.dir("generated/tessdataAssets") |
| 21 | 22 | |
| 23 | +/** Signature release : lue depuis android/keystore.properties (hors git). | |
| 24 | + * Absente → assembleRelease produit un APK non signé, comme avant. */ | |
| 25 | +val keystoreProperties = Properties().apply { | |
| 26 | + val fichier = rootProject.file("keystore.properties") | |
| 27 | + if (fichier.isFile) fichier.inputStream().use { load(it) } | |
| 28 | +} | |
| 29 | + | |
| 22 | 30 | android { |
| 23 | 31 | namespace = "fr.ebii.card2vcf" |
| 24 | 32 | compileSdk = 35 |
@@ -46,6 +54,30 @@ android {
| 46 | 54 | unitTests.isIncludeAndroidResources = true |
| 47 | 55 | } |
| 48 | 56 | sourceSets.getByName("main").assets.srcDir(tessdataGeneratedAssets) |
| 57 | + signingConfigs { | |
| 58 | + if (keystoreProperties.getProperty("storeFile") != null) { | |
| 59 | + create("release") { | |
| 60 | + storeFile = rootProject.file(keystoreProperties.getProperty("storeFile")) | |
| 61 | + storePassword = keystoreProperties.getProperty("storePassword") | |
| 62 | + keyAlias = keystoreProperties.getProperty("keyAlias") | |
| 63 | + keyPassword = keystoreProperties.getProperty("keyPassword") | |
| 64 | + } | |
| 65 | + } | |
| 66 | + } | |
| 67 | + buildTypes { | |
| 68 | + release { | |
| 69 | + isMinifyEnabled = false | |
| 70 | + signingConfig = signingConfigs.findByName("release") | |
| 71 | + } | |
| 72 | + } | |
| 73 | + // Sorties nommées d'après l'application : PicLead-<version>-<type>.apk | |
| 74 | + applicationVariants.all { | |
| 75 | + val variant = this | |
| 76 | + outputs.all { | |
| 77 | + (this as com.android.build.gradle.internal.api.BaseVariantOutputImpl).outputFileName = | |
| 78 | + "PicLead-${variant.versionName}-${variant.buildType.name}.apk" | |
| 79 | + } | |
| 80 | + } | |
| 49 | 81 | } |
| 50 | 82 | |
| 51 | 83 | val prepareTessdata by tasks.registering { |
GitRust