Skip to content

Google Play closed testing for Flutter apps

Updated

Flutter doesn't change Google's rule. If your Play Console account is a personal account created after November 13, 2023, you must run a closed test with at least 12 testers opted in for 14 continuous days before you can apply for production access (Play Console Help). What Flutter changes is how you get there: where the target SDK comes from, how version codes are set, and a few release-only bugs that testers find before you do.

This page covers the Flutter side. For the full rule and every step in Play Console, start with the Google Play closed testing guide.

Step 1: Fix the application ID before the first upload

Open android/app/build.gradle.kts (or build.gradle in older projects). The template ships with applicationId = "com.example.[project]". Replace it with your own reverse-domain ID now.

Two reasons:

  • Flutter's docs are explicit: once you upload to the Play Store, you can't change the application ID (Flutter docs). Google says the same about the package name after the first upload (Play Console Help).
  • When you create an app in Play Console, Google registers that package name to your account for Android developer verification. If another developer already uses the name, Play Console asks you to pick another (Android Developers).

If you change applicationId, also change namespace and move MainActivity.kt to the matching folder with the matching package line. Flutter's docs list this step because the build breaks without it.

Step 2: Check the target SDK (API 36)

Since August 31, 2026, new apps and app updates must target Android 16 (API level 36) or higher. Wear OS and Android Automotive OS apps need API 35, Android TV and Android XR apps API 34 (Play Console Help).

In a Flutter project, look at defaultConfig:

kotlin
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion

Values that start with flutter. come from the Flutter Gradle plugin of the SDK you build with. On the stable branch checked on November 8, 2026 (Flutter 3.47), the plugin sets targetSdkVersion = 36, compileSdkVersion = 36 and minSdkVersion = 24 (Flutter source).

Two cases to watch:

  • You see a hard-coded number. Flutter's docs say you can replace the variables with integers to lock versions. That lock survives Flutter upgrades. If it says 34 or 35, Play Console will refuse the bundle. Raise it to 36 and test.
  • You see flutter.targetSdkVersion but build with an old Flutter. Run flutter --version. The value follows your SDK, not the date. Upgrade, then rebuild.

The target API 36 guide covers the behavior changes worth testing after the bump.

Step 3: Sign with an upload key, and keep it safe

Flutter's guide walks through it (Flutter docs):

  1. Create an upload keystore with keytool (the command is in the docs; flutter doctor -v shows where Java lives if keytool isn't on your path).
  2. Create android/key.properties with the store password, key password, alias and file path.
  3. Load it in build.gradle.kts and add a release signing config. Use it in buildTypes.release.
  4. Run flutter clean if signing seems ignored.

Never commit the keystore or key.properties.

With Play App Signing, Google holds the app signing key and you hold the upload key. If you lose the upload key, Google can reset it (Play Console Help). If you manage the app signing key yourself and lose it, it can't be reset.

Developer verification raises the stakes. Registering a package can require proving you own its private signing key, and Google's FAQ says that if you lose your signing key, you won't be able to register your packages (Android Developers FAQ). Back up the keystore and both passwords somewhere other than your laptop. The developer verification guide explains what this changes for apps you also distribute outside Google Play.

Firebase and Google Sign-In. Because Google signs the final APK, you must register the Google-held app signing key fingerprint with your API providers, not only your local upload key (Play Console Help). Copy the SHA-1 or SHA-256 from Play Console (Protected with Play > Play Store protection > Manage Play app signing, section "App signing key") into Firebase. If you skip this, sign-in can work on your machine and fail for every tester who installed from Google Play.

Step 4: Version codes come from pubspec.yaml

Flutter reads version: 1.0.0+1 in pubspec.yaml. The part before + becomes versionName, the number after it becomes versionCode. You can override both with --build-name and --build-number (Flutter docs).

versionCode must increase with every release, up to a maximum of 2,100,000,000 (Play Console Help). You will ship fixes during the 14 days, which Google recommends, so bump +N every time. A simple +1, +2, +3 is enough.

Step 5: Check the manifest and permissions

Two Flutter-specific checks in android/app/src/main/AndroidManifest.xml:

  • INTERNET. Flutter's docs note the standard template doesn't include android.permission.INTERNET but allows network access during development. Add the tag if your app talks to any server. Without it, a release build can show empty lists or spinners that never stop, and your testers report a broken app.
  • Label. Set android:label to the real app name. Testers see it on their home screen.

Plugins merge their own permissions into the final manifest. If a plugin brings in a high-risk or sensitive permission (SMS, Call Log), Play Console shows a Permissions Declaration Form during the release. Google evaluates permission requests on test tracks too, and an undeclared permission on an active closed release can block you from publishing changes (Play Console Help). Check the merged manifest in Android Studio before you upload.

Step 6: Build and test the release bundle

bash
flutter build appbundle

The bundle lands in build/app/outputs/bundle/release/. By default it contains code for armeabi-v7a, arm64-v8a and x86-64 (Flutter docs).

R8 code shrinking is always on in Flutter release builds. Shrinking and obfuscation issues only appear in release, so run flutter run --release on a real phone before uploading. Test sign-in, payments, push notifications and anything that uses reflection in a plugin.

You can also check the bundle on the internal testing track. Keep that track for your own accounts: Google says a user who opts into your internal test is no longer eligible to receive your closed test (Play Console Help).

Step 7: Release on the closed testing track

In Play Console, go to Test and release > Testing > Closed testing, then Manage track. Create a release, upload the .aab, add testers in the Testers tab (email lists or a Google Group), choose countries, and send the changes for review.

The opt-in link only appears once the app status is Published, and the first time it can take several hours to work (Play Console Help). The step-by-step setup guide covers every screen.

What testers hit with Flutter builds

  • "Your device isn't compatible with this version." Flutter's default minSdk is 24 (Android 7). A plugin that raises minSdk silently cuts off older phones. Check Play Console's device catalog after the upload.
  • Login walls. If your app needs an account, give testers working credentials, and fill in App access in Play Console so Google's reviewers can get in (Play Console Help).
  • Stale builds. Google says changes after the first publish can also take several hours to reach testers (Play Console Help). Wait before you collect feedback on a fix, and bump the build number so testers can tell versions apart.

How long it really takes

  • First signed release build from a working Flutter project: plan an afternoon (keystore, Gradle, a full release run on a phone).
  • First closed release: Google's review of new accounts can take up to seven days, longer in exceptional cases (Play Console Help). Then the link can take several hours.
  • The test itself: 14 continuous days with at least 12 testers opted in.
  • Production access review: usually seven days or less, occasionally longer (Play Console Help).

Count on three to four weeks between your first closed upload and a production release. Most of that is waiting, so use the 14 days to fix what testers report and ship updates.

Frequently asked questions

Does a Flutter app need 12 testers for 14 days on Google Play?

If your Play Console account is a personal account created after November 13, 2023, yes. The framework doesn't matter: you run a closed test with at least 12 testers opted in for 14 continuous days, then apply for production access.

What target SDK does Flutter use by default?

New Flutter projects read targetSdk from flutter.targetSdkVersion. On the stable branch checked on November 8, 2026 (Flutter 3.47), that value is 36, which matches Google Play's requirement for new apps since August 31, 2026.

How do I bump the version code of a Flutter app?

Change the number after the + in pubspec.yaml (version: 1.0.0+2) or pass --build-number to flutter build appbundle. Google Play rejects an upload that reuses a version code.

My Flutter app works in debug but testers see a blank screen. Why?

Check the INTERNET permission in android/app/src/main/AndroidManifest.xml. Flutter's docs note the standard template allows network access during development without that tag, so a release build can lose network access.

Can I test my Flutter AAB on the internal track first?

Yes, but only with your own accounts. Google says a user who opts into your internal test is no longer eligible for your closed test, so keep your 12 closed testers out of the internal track.

Sources

  1. support.google.com/googleplay/android-developer/answer/14151465
  2. support.google.com/googleplay/android-developer/answer/9845334
  3. support.google.com/googleplay/android-developer/answer/11926878
  4. support.google.com/googleplay/android-developer/answer/9842756
  5. support.google.com/googleplay/android-developer/answer/17367361
  6. support.google.com/googleplay/android-developer/answer/9214102
  7. support.google.com/googleplay/android-developer/answer/9859455
  8. support.google.com/googleplay/android-developer/answer/9859751
  9. developer.android.com/developer-verification/guides/google-play-console
  10. developer.android.com/developer-verification/guides/faq
  11. docs.flutter.dev/deployment/android
  12. github.com/flutter/flutter/blob/stable/packages/flutter_tools/gradle/src/main/kotlin/FlutterExtension.kt