
How to Publish Your Flutter App to the Google Play Store in 2026
Publishing a Flutter app to Google Play takes about a day of focused work the first time — and the parts that trip people up are almost never Flutter-specific. Signing configuration, Play Console policy declarations, and the testing-track requirements for new personal accounts cause far more rejections than code does. This guide walks the whole path in order, flagging the traps before you hit them.
We assume your app already runs correctly in release mode on a real device. If you're still choosing your stack, start with why Flutter in 2026.
Step 0: What You Need Before Starting
- A Google Play Developer account — one-time registration fee (US$25 historically; verify the current amount at signup) plus identity verification, which can take a few days
- A finished app with a unique application ID (e.g.
com.yourcompany.yourapp) — you cannot change it after first upload, ever - Privacy policy hosted at a public URL — required for essentially all apps now
- App icon (512×1024 assets), feature graphic, and at least two screenshots
One warning up front: new personal developer accounts must run a closed test with a minimum number of testers over a multi-week period before they can publish to production (Google has adjusted the exact numbers over time — check the current requirement in Play Console). Plan your launch timeline around this; it surprises almost everyone.
Step 1: Set the App Identity
In android/app/build.gradle.kts (or build.gradle), confirm:
defaultConfig {
applicationId = "com.yourcompany.yourapp"
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
Version numbers live in pubspec.yaml as version: 1.0.0+1 — the part before + is versionName (what users see), the part after is versionCode (what Play uses; it must increase on every upload).
Also set the user-visible app name in android/app/src/main/AndroidManifest.xml (android:label).
Step 2: Create Your Signing Key (and Never Lose It)
Play uses Play App Signing: Google holds the final signing key, and you sign uploads with an upload key. Generate one:
keytool -genkey -v -keystore ~/upload-keystore.jks \
-keyalg RSA -keysize 2048 -validity 10000 \
-alias upload
Create android/key.properties (add it to .gitignore — never commit it):
storePassword=YOUR_STORE_PASSWORD
keyPassword=YOUR_KEY_PASSWORD
keyAlias=upload
storeFile=/home/you/upload-keystore.jks
Then wire it into android/app/build.gradle.kts:
val keystoreProperties = Properties().apply {
val f = rootProject.file("key.properties")
if (f.exists()) load(f.inputStream())
}
android {
signingConfigs {
create("release") {
keyAlias = keystoreProperties["keyAlias"] as String
keyPassword = keystoreProperties["keyPassword"] as String
storeFile = file(keystoreProperties["storeFile"] as String)
storePassword = keystoreProperties["storePassword"] as String
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
}
}
}
Back the keystore up somewhere safe. Losing the upload key is recoverable (Google can reset it), but it's a support process you don't want during a launch week.
Step 3: Build the App Bundle
Play requires Android App Bundles (.aab), not APKs, for new apps:
flutter build appbundle --release
Output lands at build/app/outputs/bundle/release/app-release.aab.
Before uploading, sanity-check the release build on a device:
flutter build apk --release
flutter install --release
Test specifically: app startup, anything using permissions, and any code path touched by ProGuard/R8 shrinking (JSON serialisation via reflection is the classic silent-breakage).
Step 4: Set Up the Play Console Listing
In Play Console, create the app, then work through every item in the Set up your app checklist. The ones that actually cause rejections:
| Section | Trap |
|---|---|
| Privacy policy | Must be a live, public URL matching your data practices |
| Data safety form | Must match what your app and its SDKs actually collect — Firebase/Analytics/Ads all count |
| Content rating | Answer honestly; misdeclared ratings get apps pulled later |
| Target audience | Declaring "children" triggers Families policy — a much stricter review |
| App access | If login is required, provide a working demo account for reviewers |
| Ads declaration | Must be accurate if you show any ads, including test/AdMob |
The data safety form is the most common rejection source in practice: it must cover every SDK in your dependency tree, not just your own code. Check each SDK vendor's published data-safety documentation.
Step 5: Testing Tracks, Then Production
Upload your .aab to a track:
- Internal testing — instant availability to up to 100 testers; use this for your own smoke tests
- Closed testing — this is where new personal accounts must run their mandatory multi-week test with real testers before production unlocks
- Production — the real release; new apps typically go through a review measured in hours to a few days
Use staged rollout for production releases (start at a small percentage, watch crash rates in Play Console's Android Vitals, then ramp).
Step 6: Ship Updates Sustainably
For every update: bump version: in pubspec.yaml (the +N must increase), rebuild the bundle, upload. Two habits pay off long-term:
- Automate it. Fastlane or Codemagic can build, sign, and upload on every tagged commit — worth setting up by your third release.
- Track Google's annual target-SDK deadline. Play requires apps to target a recent Android API level each year; Flutter's tooling keeps up, so staying on a current Flutter (see our take on the ecosystem) makes this a non-event.
The Rejection Checklist
If your app gets rejected, it's almost always one of these:
- Data safety form doesn't match observed network traffic
- No demo account provided for a login-gated app
- Privacy policy URL dead or generic
- Screenshots showing device frames with debug banners, or misleading content
- Requesting permissions (location, contacts) without an in-app justification visible to the reviewer
None of these are code problems. Budget as much care for the Console forms as for the build itself.
Publishing to iOS as well? The App Store process differs enough that it deserves its own guide — and if you're weighing the whole cross-platform decision, our Flutter vs React Native comparison covers it. Questions? Get in touch.
FAQ
How long does Play Store review take for a new app? Typically hours to a few days once you submit to production — but remember the closed-testing requirement for new personal accounts adds weeks before you can submit at all. Company accounts aren't subject to that requirement.
Can I convert my personal developer account to a company account? Not directly — you create a new organisation account and transfer apps to it. If you're building for a business, register the account as an organisation from day one.
Do I need separate builds for the Play Store and other stores?
The same Flutter code works, but Play requires an .aab while most third-party stores (and direct APK distribution) take flutter build apk --release. Keep your signing config identical across both.
Why does my release build crash when the debug build works?
Almost always R8 code shrinking removing something reached by reflection — JSON serialisers are the usual victim. Add keep rules in android/app/proguard-rules.pro, or test release builds early so you catch it before launch week.