Développement Mobile

Build d’un Android App Bundle Flutter et publication sur Play Console pas à pas

14 دقائق للقراءة

Publier une application Flutter sur Google Play est un rituel de passage. Le format Android App Bundle (AAB) imposé par Google depuis 2021, la signature en deux niveaux via Play App Signing, les tracks de déploiement progressif et l’obligation de cibler Android 15 minimum forment un chemin que tout le monde franchit une fois et reproduit ensuite. Ce tutoriel le détaille du keystore initial au déploiement en production, sans raccourcis ni faux pas connus.

📖 Guide principal : Flutter 3 et Dart 3 pour le développement mobile cross-platform — pour le contexte distribution et signature, lisez d’abord cette page.

Prérequis

  • Flutter SDK 3.41+ installé et fonctionnel (guide d’installation).
  • Une application Flutter qui compile sans erreur en debug.
  • JDK 17 disponible (embarqué par Android Studio récent).
  • Un compte Google Play Developer actif (25 $ une fois pour la vie, paiement par carte).
  • Un nom de package unique (ex. com.votresociete.votreapp) — il sera figé après le premier upload.
  • Niveau : intermédiaire. Temps estimé : 2 à 3 heures la première fois, dont attente Google Play.

Étape 1 — Générer une upload keystore

La chaîne de signature Play se compose de deux clés : votre upload key que vous gardez localement, et l’app signing key gérée et conservée par Google sur ses serveurs. À chaque upload, vous signez l’AAB avec l’upload key ; Google vérifie cette signature, retire la sienne, puis re-signe avec l’app signing key avant distribution. Ce double système vous protège : si vous perdez votre upload key, Google peut vous en générer une nouvelle, là où une clé de signature traditionnelle perdue rendait l’application définitivement non-mettable-à-jour.

Générez l’upload keystore avec keytool (livré avec le JDK) :

# macOS / Linux
keytool -genkey -v -keystore ~/upload-keystore.jks \
        -keyalg RSA -keysize 2048 -validity 10000 \
        -alias upload -storetype JKS

# Windows (PowerShell)
keytool -genkey -v -keystore $env:USERPROFILE\upload-keystore.jks `
        -keyalg RSA -keysize 2048 -validity 10000 `
        -alias upload -storetype JKS

L’outil demande successivement : un mot de passe pour le keystore (à mémoriser), votre nom, votre organisation, etc. Validez chaque champ. À la fin, un fichier upload-keystore.jks est créé dans votre home directory.

Mettez ce fichier en sécurité : sauvegarde sur clé USB chiffrée, gestionnaire de secrets, ou coffre-fort partagé avec votre équipe. Le perdre n’est plus catastrophique grâce à Play App Signing, mais évite des démarches administratives lourdes avec Google.

Étape 2 — Créer android/key.properties

Plutôt que de hardcoder le mot de passe du keystore dans le build Gradle (et risquer de le commiter par erreur), Flutter utilise un fichier de propriétés externe. Créez android/key.properties à la racine du dossier Android :

storePassword=<mot-de-passe-keystore>
keyPassword=<mot-de-passe-cle>
keyAlias=upload
storeFile=/Users/votrenom/upload-keystore.jks

Sur Windows, le chemin doit utiliser le double backslash : storeFile=C:\\Users\\votrenom\\upload-keystore.jks.

Ajoutez immédiatement android/key.properties à votre .gitignore — c’est le réflexe à avoir avant même de sauvegarder. Sans cela, vous risquez de pousser vos credentials sur un dépôt public à la première inattention.

echo "android/key.properties" >> .gitignore

Étape 3 — Câbler la signature dans build.gradle

Les projets Flutter récents utilisent Gradle Kotlin DSL (build.gradle.kts) ; les anciens utilisent Groovy (build.gradle). Les deux syntaxes coexistent. Ouvrez android/app/build.gradle.kts et ajoutez en haut du fichier :

import java.util.Properties
import java.io.FileInputStream

val keystoreProperties = Properties()
val keystorePropertiesFile = rootProject.file("key.properties")
if (keystorePropertiesFile.exists()) {
    keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}

Puis, à l’intérieur du bloc android { ... }, ajoutez la configuration de signature et liez-la au build type release :

android {
    // ... compileSdk, ndkVersion, defaultConfig ...

    signingConfigs {
        create("release") {
            keyAlias = keystoreProperties["keyAlias"] as String
            keyPassword = keystoreProperties["keyPassword"] as String
            storeFile = keystoreProperties["storeFile"]?.let { file(it as String) }
            storePassword = keystoreProperties["storePassword"] as String
        }
    }

    buildTypes {
        release {
            signingConfig = signingConfigs.getByName("release")
        }
    }
}

Si votre projet utilise encore Groovy, l’équivalent est plus court mais la logique identique. Une fois le câblage en place, flutter build appbundle signera automatiquement le résultat avec votre keystore.

Étape 4 — Versionner avec pubspec.yaml

Google Play exige un versionCode qui s’incrémente strictement à chaque upload — vous ne pouvez jamais réutiliser un numéro déjà publié. Flutter pilote ce numéro depuis le pubspec.yaml, ce qui évite d’éditer trois fichiers à la main.

Ouvrez pubspec.yaml et trouvez la ligne version :

version: 1.0.0+1

Le format est MAJOR.MINOR.PATCH+BUILD. La partie avant le + est le versionName (visible dans le store, libre). La partie après le + est le versionCode (entier strictement croissant). Pour la première publication, 1.0.0+1 convient. Au prochain upload, passez à 1.0.0+2 ou 1.0.1+2 selon vos changements.

Tenez un convention claire au sein de votre équipe : par exemple, incrémenter le build à chaque envoi en internal, et faire passer le patch à chaque envoi en production. Cohérence = traçabilité.

Étape 5 — Vérifier compileSdk et targetSdk

Depuis le 31 août 2025, Google Play impose que toute nouvelle application ou mise à jour cible Android 15 (API level 35) minimum. Flutter récents (3.41+) règlent targetSdk à la dernière API stable automatiquement, mais vérifiez dans android/app/build.gradle.kts :

defaultConfig {
    applicationId = "com.votresociete.votreapp"
    minSdk = 23                  // Android 6.0, bonne base en 2026
    targetSdk = 35               // Android 15 — minimum Google Play
    versionCode = flutter.versionCode
    versionName = flutter.versionName
}

Si vous voyez targetSdk = flutter.targetSdkVersion en place, c’est généralement correct — la propriété est calculée à partir du SDK Flutter installé. En cas de doute, forcez la valeur à 35 explicitement.

Étape 6 — Builder l’App Bundle

Tout est en place. Lancez le build :

flutter clean
flutter pub get
flutter build appbundle

Le flutter clean élimine les artefacts précédents et garantit que les changements de build.gradle sont bien pris en compte. Le build dure 2 à 5 minutes selon la taille du projet. À la fin, vous trouvez le résultat dans :

build/app/outputs/bundle/release/app-release.aab

Le fichier pèse typiquement 15 à 40 Mo pour une application moyenne. C’est ce que vous uploadez sur Play Console.

Pour activer l’obfuscation du code Dart en plus du shrinking R8 natif Android, ajoutez deux drapeaux :

flutter build appbundle --obfuscate \
  --split-debug-info=build/app/outputs/symbols

L’obfuscation rend la rétro-ingénierie nettement plus difficile. Les symboles exportés dans --split-debug-info servent à dé-obfusquer les stack traces de crash en production — gardez-les précieusement, sans eux les rapports Firebase Crashlytics ne sont plus lisibles.

Étape 7 — Tester l’AAB localement avec bundletool

Un AAB n’est pas installable directement sur un téléphone — c’est un format que Google Play utilise pour générer des APK adaptés. Pour tester localement avant upload, utilisez l’outil bundletool :

# Télécharger bundletool depuis github.com/google/bundletool/releases
java -jar bundletool.jar build-apks \
  --bundle=app-release.aab \
  --output=app.apks \
  --mode=universal

java -jar bundletool.jar install-apks --apks=app.apks

Le mode universal génère un APK unique qui contient toutes les architectures et densités — pratique pour tester rapidement, mais 30 à 50 % plus gros que ce que Google Play distribuera vraiment. Pour mesurer la taille réelle perçue par l’utilisateur, utilisez --mode=default qui produit le split exact qu’enverra Play.

Étape 8 — Créer l’application dans Play Console

Connectez-vous à play.google.com/console. Cliquez sur Créer une application. Renseignez :

  • Nom de l’application : 30 caractères max, modifiable plus tard.
  • Langue par défaut : choisissez votre langue principale.
  • Type d’application : Application ou Jeu.
  • Gratuit ou payant : irréversible une fois publié.
  • Déclarations : politique de confidentialité, ciblage enfants, audience.

Validez. Vous arrivez sur le tableau de bord de l’application avec une checklist de tâches à compléter avant publication : description, captures d’écran, classification du contenu, etc. Ces tâches conditionnent l’autorisation de publier.

Étape 9 — Uploader sur la track Internal testing

Google Play propose plusieurs tracks de déploiement, du plus restreint au plus large :

  • Internal testing — jusqu’à 100 testeurs internes, disponible en quelques minutes après upload. Idéal pour valider qu’un build fonctionne sans review.
  • Closed testing — listes de testeurs définies par e-mail ou Google Groups, soumis à review Google.
  • Open testing — accessible à toute personne ayant le lien, public mais identifié comme beta.
  • Production — disponible sur le Play Store. Review Google obligatoire (2 à 7 jours en moyenne).

Démarrez toujours par Internal testing. Menu TestTests internes, cliquez Créer une nouvelle version, uploadez votre app-release.aab, renseignez les release notes (en français pour vos utilisateurs francophones), puis Examiner la version et Démarrer le déploiement vers les tests internes.

Côté testeurs : créez une liste sur l’onglet Testeurs, ajoutez les e-mails Google des comptes qui doivent recevoir l’app, copiez le lien d’opt-in et envoyez-le. Chaque testeur clique, accepte, et trouve l’app dans son Play Store sous quelques minutes.

Étape 10 — Promotion progressive vers la production

Une fois validée en interne, votre version peut être promue vers Closed, Open, puis Production. À chaque promotion, vous gardez la traçabilité du AAB d’origine. Pour la production, configurez en plus un rollout progressif : 5 % des utilisateurs au jour 1, puis 20 %, puis 50 %, puis 100 % sur quelques jours. Cela vous donne le temps de détecter un crash de masse via Play Console avant qu’il touche toute la base installée.

Pour activer le rollout progressif : dans la création de version production, choisissez Déploiement échelonné et fixez le pourcentage initial. Vous pouvez l’augmenter manuellement ensuite dans la page de version.

Surveillez en parallèle l’onglet Vital de Play Console qui agrège les ANR (Application Not Responding) et les crashes par version. Les seuils de mauvais comportement Android Vitals sont publiés par Google : 1,09 % de sessions avec crash et 0,47 % de sessions avec ANR, sur l’ensemble des appareils. Au-dessus, Google peut pénaliser votre fiche dans le classement Play Store. Restez largement sous ces seuils — un produit sain tourne plutôt autour de 0,2 % de crashes.

Soigner la fiche Play Store

Un AAB techniquement parfait n’est rien sans une fiche store qui convertit. Plusieurs éléments de la fiche pèsent lourd dans la décision d’installer.

Le titre tient en 30 caractères. Soyez explicite sur la fonction principale plutôt que créatif : « Gestion de stock Atelier » convertit mieux que « Stockify Pro » pour un utilisateur qui cherche un outil. Les mots-clés du titre comptent fort dans la recherche Play Store.

La description courte est limitée à 80 caractères et affichée juste sous le titre. C’est votre hook principal — la promesse qui décide du clic sur « Installer ». La description longue peut faire jusqu’à 4000 caractères, structurée en blocs : fonctionnalités principales, bénéfices, cas d’usage, points forts.

Les captures d’écran sont le levier visuel principal. Comptez 2 à 8 captures par appareil ciblé (téléphone, tablette 7″, tablette 10″). Plutôt que des screenshots bruts, créez des compositions avec un titre court qui annonce ce que montre la capture — vous gagnez 30 à 50 % de taux de clic. Outils gratuits classiques : Hotpot, Previewed, Figma avec un template store.

L’icône doit être lisible à 48×48 pixels minimum. Évitez le texte (illisible), privilégiez un symbole simple sur fond contrasté. Testez en grayscale — si elle reste reconnaissable, elle est bonne.

Conformité aux politiques Google Play

Google Play applique une politique stricte que beaucoup de développeurs découvrent à leur premier rejet. Quelques règles structurantes valent la peine d’être anticipées plutôt que subies.

Permissions sensibles — chaque autorisation déclarée (caméra, contacts, localisation, stockage externe, accessibilité) doit être justifiée par un usage visible dans l’application. Demander la caméra « au cas où » se solde par un rejet. Désactivez les permissions héritées de packages tiers que vous n’utilisez plus.

Politique de confidentialité — obligatoire dès qu’une donnée personnelle (e-mail, téléphone, identifiant publicitaire) est collectée. Doit être hébergée à une URL publique stable, accessible depuis la fiche store ET depuis l’app elle-même.

Section « Sécurité des données » — déclaration explicite, par catégorie, de chaque type de donnée que vous collectez ou partagez. Google compare cette déclaration au code de votre AAB ; les divergences déclenchent des avertissements.

Mineurs et fitness — toute app qui cible les enfants ou stocke des données médicales est soumise à des règles supplémentaires (formulaire COPPA/HIPAA selon le marché). Évitez d’y entrer sans préparation.

Et pour iOS ? Vue rapide

Vous n’échapperez pas à la question si votre app cible aussi iPhone et iPad. Le chemin parallèle pour iOS est conceptuellement similaire mais utilise d’autres outils : flutter build ipa à la place de flutter build appbundle, signature via certificat de distribution Apple plutôt que keystore, upload via Xcode ou Transporter, review App Store Connect généralement plus rapide (1 à 2 jours en moyenne mais plus stricte sur le design).

La différence pratique majeure : Apple exige un Mac physique pour le build final iOS, là où Android se compile sur n’importe quel OS. Si vous êtes seul sur Windows ou Linux, déléguez la partie iOS à un runner macOS via Codemagic ou GitHub Actions — il existe des plans gratuits jusqu’à un certain volume mensuel qui couvrent un projet en démarrage.

Erreurs fréquentes

Erreur Cause Solution
Keystore was tampered with, or password was incorrect Mauvais mot de passe dans key.properties. Vérifier storePassword et keyPassword. Les retaper sans accolades ni espaces.
You uploaded an APK or Android App Bundle which was signed with a key not previously used Vous avez changé d’upload key entre deux uploads. Conserver une seule upload key par application. En cas de perte, contacter le support Play pour reset.
Build qui échoue avec R8: Type not present R8 enlève une classe utilisée par réflexion. Ajouter une règle ProGuard -keep class com.exemple.MaClasse { *; } dans android/app/proguard-rules.pro.
Version code déjà utilisé Vous tentez d’uploader un AAB avec un versionCode ≤ à un déjà publié. Incrémenter la partie après + dans pubspec.yaml et rebuilder.
Target SDK too low Vous ciblez moins de 35. Forcer targetSdk = 35 dans build.gradle.kts.
Bundle trop volumineux (> 200 Mo) Limite Play Store (passée de 150 Mo à 200 Mo en janvier 2026). Utiliser Play Asset Delivery ou Play Feature Delivery pour les gros assets, ou supprimer les ressources inutiles.

Tutoriels associés

Foire aux questions

Peut-on encore publier un APK plutôt qu’un AAB ?

Non pour une nouvelle application. Google Play refuse les APK pour les nouvelles soumissions depuis août 2021. L’APK reste utile pour la distribution hors store (sideloading, distribution interne entreprise via MDM).

Combien de temps prend la review Google Play ?

Pour une première publication, comptez 3 à 7 jours selon la complexité et la file d’attente. Pour des mises à jour de version existante, généralement quelques heures à 1 jour. Google peut rejeter pour des raisons de politique (autorisations excessives, métadonnées trompeuses) — il faut alors corriger et resoumettre.

Comment automatiser le build et l’upload ?

Deux options dominantes : fastlane (Ruby, multi-plateforme) avec son plugin supply qui parle directement à l’API Google Play Developer ; ou Codemagic / Bitrise pour un pipeline CI complet hébergé. Les deux gèrent l’incrément du versionCode, le build et l’upload sur la track de votre choix.

Que faire si je perds mon upload keystore ?

Contactez le support Google Play Console depuis l’application concernée. Ils peuvent générer une nouvelle upload key associée à votre app signing key déjà chez Google. Vous mettez à jour key.properties avec la nouvelle clé et continuez. C’est l’un des gros bénéfices de Play App Signing par rapport au modèle ancien.

Comment gérer plusieurs environnements (dev, staging, prod) dans Play Console ?

Soit créer trois applications distinctes avec des applicationId différents (com.example.app.dev, .staging, .prod) et trois fiches Play, ce qui sépare proprement. Soit utiliser une seule app et exploiter les tracks Internal/Closed/Open pour les environnements de test, et Production pour la prod — plus économique mais moins isolé.

Combien coûte vraiment Play Console ?

25 $ une seule fois, à l’inscription du compte développeur. Aucun frais récurrent côté Google. Apple, en comparaison, facture 99 $/an pour le programme développeur — c’est l’une des différences structurelles entre les deux écosystèmes.

Ressources officielles

Sponsoriser ce contenu

Cet emplacement est à vous

Position premium en fin d'article — c'est l'instant où les lecteurs sont le plus engagés. Réservez cet espace pour votre marque, votre formation ou votre offre.

Recevoir nos tarifs
Publicité