Publier une app Flutter sur l'App Store et Google Play en 2026

Publié le : 13 juillet 2026

Read in English →

Flutter vous donne une seule base de code pour iOS et Android. C'est la partie facile. Amener cette base de code sur l'App Store et Google Play — les bonnes métadonnées, des captures aux bons formats, le bon binaire pour chaque store — c'est là que la base unique se rescinde en deux de tout.


Ce que « publier sur deux stores » demande vraiment

Lancer flutter builddeux fois n'est pas le travail. Chaque store a son propre format de binaire (.ipa pour Apple, .aab pour Google), ses propres identifiants de signature (une clé API .p8 et un provisioning profile pour Apple, un JSON de compte de service pour Google), ses propres limites de métadonnées, ses propres formats de captures et son propre modèle de release. Rien de tout ça n'est spécifique à Flutter — c'est la couche de publication posée sur n'importe quelle base de code. Vous êtes sur React Native plutôt ? La version React Native de ce guide couvre le même terrain avec les commandes de build RN.


Étape 1 — Configurer le projet Flutter pour les deux plateformes

C'est la partie réellement spécifique à Flutter — et là où Flutter vous fait gagner du temps par rapport au pilotage manuel de Xcode et Gradle. On commence par une version, à un seul endroit : pubspec.yaml alimente les deux plateformes.

# pubspec.yaml
version: 1.0.0+1   # 1.0.0 = version name, +1 = build number

1.0.0 devient CFBundleShortVersionString sur iOS et versionName sur Android ; le build number +1 devient CFBundleVersion et versionCode. Surchargez au build avec --build-name et --build-numberen CI. Le build number doit augmenter à chaque upload sur l'un ou l'autre store — c'est le champ que vous incrémenterez le plus.

iOS : signature et flutter build ipa

Ouvrez ios/Runner.xcworkspaceune fois pour fixer le bundle ID (il doit correspondre à la fiche d'app dans App Store Connect) et poser le certificat de distribution plus le provisioning profile App Store sur la cible Runner. Ensuite, le build tient en une commande :

flutter build ipa --release --export-options-plist=ios/ExportOptions.plist

Le .ipa signé se retrouve dans build/ios/ipa/. Cette étape nécessite macOS — flutter build ipa encapsule xcodebuild, donc pas moyen d'éviter un Mac ou un runner CI macOS pour le binaire iOS. Il vous faut aussi une clé API App Store Connect .p8 pour l'upload lui-même (Étape 4).

Android : keystore et flutter build appbundle

Générez un keystore d'upload, puis pointez Flutter dessus avec android/key.properties (gardé hors du contrôle de version) :

# android/key.properties
storePassword=<votre-mot-de-passe-store>
keyPassword=<votre-mot-de-passe-cle>
keyAlias=upload
storeFile=upload-keystore.jks

android/app/build.gradle (ou build.gradle.kts sur les projets plus récents) lit ce fichier pour la config de signature release. Puis :

flutter build appbundle --release

Le .aab signé se retrouve dans build/app/outputs/bundle/release/app-release.aab. Contrairement au .ipa, ceci tourne sur Linux, Windows ou macOS — aucun Mac requis côté Android. Perdre le keystore veut dire ne plus jamais pouvoir mettre à jour l'app sur Google Play : sauvegardez-le quelque part de fiable.


Étape 2 — Écrire les métadonnées une fois, publier sur les deux stores

Le même texte, deux formulaires aux noms de champs et limites différents :

  • Titre — 30 caractères, sur les deux stores.
  • Sous-titre / description courte — 30 sur l'App Store, 80 sur Google Play.
  • Description longue — 4000 caractères, sur les deux.
  • Mots-clés — champ dédié de 100 caractères sur l'App Store ; Google Play n'en a pas, c'est le texte de la description qui est indexé.

Comme le titre plafonne à exactement 30 sur les deux, un seul titre fonctionne en général pour les deux — pas besoin de le raccourcir pour l'un et de le rallonger pour l'autre. La description longue, elle, diverge : Google Play l'indexe pour la recherche, l'App Store non — la version Play doit donc intégrer les mots-clés naturellement, celle de l'App Store peut se contenter de convaincre. Un doc partagé suffit pour une app et casse à deux — l'éditeur d'OneStore affiche les compteurs de caractères des deux stores pendant que vous tapez. Le détail champ par champ est dans les différences de métadonnées entre App Store Connect et Google Play Console.


Étape 3 — Préparer les captures sans Photoshop

Apple exige au moins un des trois formats iPhone — 6,5" (1242×2688), 6,7" (1290×2796) ou 6,9" (1320×2868) — pas les trois. Le 6,7" est le format de référence actuel : Apple l'agrandit automatiquement dans les emplacements 6,9", donc ne fournir que du 6,7" passe la review. L'iPad 12,9" (2048×2732) n'est requis que si l'app déclare le support iPad — beaucoup d'apps Flutter le font, vérifiez votre Info.plist. Google Play veut son propre jeu : téléphone, tablette 7", tablette 10". Concevez une fois à la plus haute résolution et redimensionnez à partir de là — automatiser le redimensionnement des captures explique comment transformer une source HD en tous les formats requis.


Étape 4 — Uploader les binaires

Deux fichiers, deux destinations. Le .ipa part vers App Store Connect via Apple Transporter (ou altool, ou l'API App Store Connect) — sans Xcode une fois le fichier généré ; uploader un .ipa sans Xcode passe en revue chaque méthode. Le .aab part vers Google Play via l'API Developer, authentifié avec votre JSON de compte de service, assigné à une track (internal/alpha/bêta/production) puis commité — uploader un .aab sans Android Studio couvre les options. OneStore fait les deux depuis un seul dashboard : le .ipa via Transporter, le .aab via l'API Developer, avec des identifiants que vous connectez une fois.


Étape 5 — Gérer le rollout

iOS et Android ne se releasent pas de la même façon, et ça piège beaucoup de premiers lancements sur deux stores.

Le phased release d'Apple est automatique et piloté par Apple : 1 %, 2 %, 5 %, 10 %, 20 %, 50 %, puis 100 % sur sept jours, et seulement à partir de la version 2 — jamais la soumission initiale. Vous pouvez le mettre en pause ou l'arrêter dans App Store Connect, mais vous ne pouvez pas fixer le pourcentage ; c'est Apple qui garde la main sur ce palier. OneStore affiche le palier en cours sur la timeline de release et renvoie vers App Store Connect pour le mettre en pause, plutôt que de prétendre contrôler un chiffre qu'Apple n'expose pas.

Le staged rollout de Google Play, c'est l'inverse — le pourcentage est à vous. Fixez-le, surveillez-le, mettez-le en pause, reprenez-le, poussez à 100 %, et promouvez un build d'une track à l'autre (internal → production) sans le re-uploader, tout depuis le dashboard.


Étape 6 — Gérer les avis sur les deux stores

Les avis arrivent sur les deux stores indépendamment ; les surveiller à la main veut dire deux consoles ouvertes toute la journée. Une inbox unifiée remonte les deux au même endroit, avec des réponses IA pré-rédigées dans la langue de l'auteur — répondre aux avis sans deux consoles détaille le workflow.


Étape 7 — Garder les fiches synchronisées après le lancement

Les fiches dérivent : quelqu'un édite une description directement dans une console et votre source de vérité devient fausse sans bruit. La détection de drift compare la fiche live de chaque store avec ce qui est dans votre outil au moment où vous ouvrez l'éditeur, et signale les écarts avant que vous n'écrasiez une vraie modification ou ne publiiez une copie périmée.


Au global

Flutter réduit le build à flutter build ipa et flutter build appbundle. Il ne réduit pas la couche de publication — métadonnées, captures, uploads, avis et rollout restent deux de tout, et c'est là que passe le temps. OneStorecouvre l'ensemble au même endroit, les deux stores, sur un plan gratuit qui inclut 3 apps sans carte bancaire. Les crédits IA ne servent qu'aux fonctions optionnelles (traduction, réponses aux avis) — connecter les stores, éditer les fiches et publier restent illimités et gratuits sur tous les plans.

L'Audit de fiche de store (sans compte, sans email) note une fiche existante sur 100.


FAQ

La version de Flutter ou du SDK Dart influence-t-elle la review App Store ou Play ?

Non. Les deux stores examinent le binaire compilé, pas votre toolchain — ils ne voient pas quelle version de Flutter l'a buildé. Ce qui compte, c'est que le .ipa soit signé avec un certificat de distribution, le .aab avec votre clé d'upload, et que le bundle ID / application ID correspondent aux fiches des stores.

Quelle est la différence entre la limite de titre App Store et Google Play ?

Aucune — les deux plafonnent le titre à 30 caractères, donc un même titre fonctionne généralement pour les deux stores. (Le chiffre de 50 caractères que citent certains guides est périmé.)

Où flutter build met-il le .ipa et le .aab ?

flutter build ipa --release écrit dans build/ios/ipa/ ; flutter build appbundle --release écrit dans build/app/outputs/bundle/release/app-release.aab. Les deux vivent sous le répertoire build/ au niveau du projet, pas dans les sous-dossiers de plateforme.

J'ai besoin d'un Mac pour builder le .ipa Flutter ?

Oui. flutter build ipa encapsule xcodebuild, qui ne tourne que sur macOS — le binaire iOS nécessite donc un Mac ou un runner CI macOS. flutter build appbundlepour le .aab Android tourne sur n'importe quel OS. L'upload, pour l'un comme pour l'autre, peut se faire de n'importe où une fois le fichier généré.

Je peux utiliser le rollout progressif pour la première version d'une app Flutter ?

Pas sur Apple — le phased release ne s'applique qu'aux mises à jour, à partir de la version 2 ; la première version approuvée part à 100 % immédiatement. Sur Google Play, vous pouvez démarrer même le premier rollout de production à un pourcentage réduit.

Comment fixer la version et le build number d'une release Flutter ?

Dans pubspec.yaml sous la forme version: 1.0.0+1 — la partie avant + est le version name (CFBundleShortVersionString / versionName), la partie après est le build number (CFBundleVersion / versionCode). Surchargez au build avec flutter build --build-name=1.0.1 --build-number=2. Le build number doit augmenter à chaque upload sur l'un ou l'autre store.

Ma clé .p8 et mon JSON de compte de service sont-ils stockés en sécurité ?

Oui : vos identifiants (clé .p8, JSON de compte de service) sont stockés dans un coffre chiffré au repos avec AES-256-GCM au niveau applicatif. Un accord de traitement des données (DPA) basé sur les clauses contractuelles types de l'UE est disponible sur onestore.so/dpa.