Play Console & Shipping7 min read

How to Publish a Flutter App on Google Play in 2026 — Complete Step-by-Step Guide

Complete guide for Flutter developers to publish an Android app on Google Play. Covers AAB builds, Play Console setup, Closed Testing with 12 testers, production access, and release.

Ahmed Akash
Ahmed Akash
How to Publish a Flutter App on Google Play in 2026 — Complete Step-by-Step Guide

Need testers who stay active for all 14 days?

TesterBee matches you with 12 real Android testers in under 24 hours. Refund if Google rejects you over tester engagement.

Get 12 testers
On this page
  1. 01Step 1: Configure Your Flutter Project for Release
  2. 02Step 2: Generate a Keystore and Sign Your Build
  3. 03Step 3: Build the App Bundle (Not an APK)
  4. 04Step 4: Test on Multiple Physical Android Devices Before Uploading
  5. 05Step 5: Create Your Play Console Store Listing
  6. 06Step 6: Set Up and Run Closed Testing
  7. 07Step 7: Push at Least One Update During Testing
  8. 08Step 8: Apply for Production Access

Flutter makes cross-platform development fast. But when it comes time to publish on Google Play, you face the same 12-tester, 14-day Closed Testing requirement as every other Android developer — plus a few Flutter-specific headaches that native Android developers do not deal with. This guide covers the full process from keystore to production, with specific attention to the parts where Flutter developers commonly get stuck.

Step 1: Configure Your Flutter Project for Release

Before you build anything, your project needs production configuration that most Flutter developers skip during development. Open android/app/build.gradle and set your application ID, version code, and version name. The application ID is your app's permanent identifier on the Play Store — pick it carefully because it cannot be changed after publishing.

The version code must be an integer that increases with every Play Store upload. Flutter's default pubspec.yaml version field (like "1.0.0") does not directly map to the Android version code — you need to set android:versionCode explicitly in build.gradle or use the flutterVersionCode property. A common convention: use flutterVersionCode = flutterVersionCode.toInteger() in build.gradle and set version to "1.0.0+1" in pubspec.yaml (the number after the + becomes versionCode).

Also update android/app/src/main/AndroidManifest.xml to set your app label, any required permissions, and the internet permission if your app makes network requests (most Flutter apps do, but this is not enabled by default in debug builds).

Step 2: Generate a Keystore and Sign Your Build

This is the step that trips up the most first-time Flutter publishers. The Play Store requires all apps to be signed with a release key. The debug key that Flutter uses during development is not accepted. You need to generate a keystore:

keytool -genkey -v -keystore ~/upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload

Then reference it in android/key.properties and android/app/build.gradle. This is documented in Flutter's official deployment guide, but the common mistakes are: generating the keystore with default settings that produce a weak key, losing the keystore file (there is no recovery — if you lose it, you can never update the app), and not storing the keystore password securely. Save the keystore file, the store password, the key alias, and the key password in four separate places. Losing any one of them means losing your ability to push updates.

In android/key.properties, create a file that looks like:

storePassword=your_store_password
keyPassword=your_key_password
keyAlias=upload
storeFile=/Users/you/upload-keystore.jks

Add this file to .gitignore. Never commit your keystore or its passwords to version control.

Step 3: Build the App Bundle (Not an APK)

Google Play requires the Android App Bundle (.aab) format for new apps. APKs are rejected. Build with:

flutter build appbundle

This generates build/app/outputs/bundle/release/app-release.aab. The AAB is a publishing format — Google uses it to generate optimized APKs for each device configuration (different CPU architectures, screen densities, and language combinations). This is what makes your app smaller for end users compared to a universal APK.

If you see build errors at this stage, the most common causes are: unresolved dependencies in android/app/build.gradle (run flutter clean and flutter pub get), Kotlin/Gradle version mismatches (Flutter has specific minimum versions), or a plugin that does not support the latest Android SDK. Check each plugin's Android compatibility before updating your compileSdk.

Step 4: Test on Multiple Physical Android Devices Before Uploading

Flutter's hot reload makes development fast, but it also masks platform-specific issues. Things that work perfectly on your Pixel 7 might crash on a Samsung Galaxy A54, render incorrectly on a Xiaomi with MIUI, or have broken text input on a OnePlus with a custom keyboard. Flutter's rendering engine (Skia/Impeller) handles most UI consistency, but platform channels (for plugins like camera, location, payments) interact directly with native Android APIs and can behave differently across OEMs.

Specifically test these on at least 3 different device brands before uploading to Closed Testing:

  • Text input and keyboard behavior. Samsung devices use a modified keyboard. Some Xiaomi devices have aggressive text prediction that can interfere with Flutter's TextField. Test that text input, autocorrect, and IME actions work correctly.
  • Permissions flows. OEMs customize permission dialogs. Test that camera, location, and storage permissions are requested correctly and that your app handles denial gracefully.
  • Background behavior. Chinese OEMs (Xiaomi, Oppo, Vivo) aggressively kill background processes. If your app uses background services or workmanager, verify they survive on these devices.
  • Impeller rendering. Flutter's Impeller engine is now the default on Android. It performs better than Skia on most devices but has compatibility gaps on older hardware. Test with Impeller first, and have a fallback to Skia if needed.

Step 5: Create Your Play Console Store Listing

Google requires a complete store listing before you can publish to any track, including Closed Testing. The minimum requirements:

  • App name: 50 characters max. This is your Play Store title.
  • Short description: 80 characters. This appears above the fold in search results.
  • Full description: 4,000 characters max. Describe what your app does in concrete terms. Google reads this for categorization and discovery.
  • Screenshots: Minimum 4 phone screenshots. These must be from your actual app — do not use mockups or placeholder images.
  • Feature graphic: 1,024 × 500 pixels. This is the hero image at the top of your listing.
  • App icon: 512 × 512 pixels, PNG with transparency.
  • Privacy policy URL: Required for all apps. Even if your app collects no data, you need a hosted privacy policy.
  • Content rating questionnaire: Complete the IARC questionnaire in Play Console. This is required before you can create a testing track.

An incomplete listing is one of the most common rejection reasons for production access. Complete every field before uploading your first AAB.

Step 6: Set Up and Run Closed Testing

Go to Testing → Closed Testing → Create Track in Play Console. Upload your signed AAB. Choose your testing method — email lists or Google Groups. Create an email list with your 12 testers' Gmail addresses, or create a Google Group and add them. Copy the opt-in URL from the Closed Testing track page and share it with your testers.

Your testers must open the opt-in URL on their Android device, sign in with the Google account you added, accept the testing invitation, and install the app through the Play Store. They cannot install from an APK — the install must go through the Play Store testing track to count.

One Flutter-specific tip: enable crash reporting before testing begins. Add Firebase Crashlytics to your Flutter app — the setup takes about 15 minutes and the SDK is free. During the 14-day testing period, monitor Crashlytics for crashes on specific device models or Android versions. Flutter's rendering engine can produce nondeterministic crashes on specific hardware that you will never see on your development device. Finding and fixing these during testing, and documenting the fixes in your production access questionnaire, significantly strengthens your application.

Step 7: Push at Least One Update During Testing

Google expects to see that testing produced feedback and that feedback produced changes. Even a small update — a bug fix, a UI tweak, an improvement suggested by a tester — demonstrates an active feedback loop. Reference the specific build version and the change in your production access questionnaire. "Testers reported that text was too small on the settings screen. Increased font size from 14sp to 16sp in build 1.0.2. All 12 testers confirmed the change was readable."

Step 8: Apply for Production Access

After 14 consecutive days with 12+ active testers, the "Apply for Production Access" button becomes available. The questionnaire asks what you learned and what you changed. Write specific answers: name devices, build numbers, exact changes, and tester feedback. Generic answers fail. The questionnaire is not a formality — it is a substantive review of whether real testing occurred.

If your production access is approved, your app moves to production. If rejected, do not immediately resubmit — diagnose the specific reason, fix it, and run another full 14-day testing cycle with the fix in place. A second rejection on the same app is much harder to recover from than a careful first resubmission.

Ahmed Akash
Ahmed Akash·Senior Full Stack Developer & Founder of TesterBee

Senior full stack developer specializing in Laravel, React, and Firebase. Helped 1,200+ Android developers pass Google Play Closed Testing and publish apps. Expert in Play Console, production access, and Android app publishing.

July 1, 2026 · 7 min readLinkedInGitHub

Get 12 testers into your closed test in 24 hours

Matched Android testers who open your app every day of the 14-day window, so your production access review has real engagement to look at.

Start your closed test