Skip to main content

Command Palette

Search for a command to run...

How to Publish a Flutter App on Google Play Store and Apple App Store: Step-by-Step Guide

Updated
5 min read

Building the app is the easy part. Getting it into the hands of users — navigating developer consoles, signing configurations, store policies, and review processes — is where first-time publishers tend to get stuck. This guide covers the complete publishing process for both Google Play and the Apple App Store, from a clean Flutter project to a live listing.


Part 1: Google Play Store

Prepare Your App

App identity

Update your app name in android/app/src/main/AndroidManifest.xml:

<application android:label="YourAppName">

Add a proper launcher icon using flutter_launcher_icons:

# pubspec.yaml
dev_dependencies:
  flutter_launcher_icons: ^0.13.0

flutter_icons:
  android: true
  ios: true
  image_path: "assets/icon.png"
flutter pub run flutter_launcher_icons

Set your version number in pubspec.yaml:

version: 1.0.0+1

The number before + is the user-visible version. The number after is the internal build number — increment this with every upload to the Play Store.

Signing

Google Play requires a signed AAB. Generate a keystore:

keytool -genkey -v -keystore ~/my-release-key.jks \
  -keyalg RSA -keysize 2048 -validity 10000 -alias my-key

Create a key.properties file in the android/ directory (and add it to .gitignore — never commit this):

storePassword=yourpassword
keyPassword=yourpassword
keyAlias=my-key
storeFile=../my-release-key.jks

Reference it in android/app/build.gradle:

def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(file("key.properties")))

android {
    signingConfigs {
        release {
            storeFile file(keystoreProperties['storeFile'])
            storePassword keystoreProperties['storePassword']
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}

Build the AAB:

flutter build appbundle

The output is at build/app/outputs/bundle/release/app-release.aab. This is what you upload — not an APK.


Google Play Console

Create a developer account at play.google.com/console. The one-time registration fee is $25.

Create a new app and fill in the basics — title, default language, free or paid, app or game.

Store listing — you'll need:

  • App title (50 characters max)
  • Short description (80 characters max)
  • Full description (up to 4000 characters)
  • App icon at 512x512 pixels
  • Feature graphic at 1024x500 pixels
  • At least 2 screenshots per device type
  • A privacy policy URL

Data safety — declare what data your app collects and why. Be accurate. Google cross-checks this against your app's behavior.

Content rating — complete the questionnaire. It takes about 5 minutes.

App access — if your app requires login to use, provide test credentials for reviewers. Apps without this often get rejected during review.

Upload and release:

Go to Production > Create new release, upload your .aab file, add release notes, and submit for review.

Google typically reviews new apps in 1–7 days. Updates are usually faster, sometimes a few hours.


Common Rejection Reasons (Android)

  • App requires login but no test account was provided
  • Trademarked terms in the app name
  • Data safety form doesn't match actual app behavior
  • Broken functionality or crashes in the review build
  • Missing privacy policy for apps that handle personal data

Part 2: Apple App Store

Apple Developer Account

Register at developer.apple.com. The annual fee is $99 USD. Two-factor authentication is required.

Sign into Xcode with your Apple ID and accept the developer agreement before attempting any builds.


Prepare Your iOS App

Update the version in pubspec.yaml — Xcode will pull from this.

Update your app name in ios/Runner/Info.plist:

<key>CFBundleDisplayName</key>
<string>YourAppName</string>

Add permission descriptions for any sensitive APIs your app uses:

<key>NSCameraUsageDescription</key>
<string>This app uses the camera to scan barcodes.</string>

<key>NSLocationWhenInUseUsageDescription</key>
<string>Your location is used to find nearby results.</string>

Apple will reject apps that use sensitive APIs without a usage description string.

For splash screens and icons:

flutter pub add flutter_native_splash
flutter pub run flutter_native_splash:create

Build and Upload via Xcode

Open ios/Runner.xcworkspace in Xcode (not the .xcodeproj file).

Set your Bundle Identifier, Version, Build number, and Development Team under the Signing & Capabilities tab.

Then go to Product > Archive. This compiles a release build and adds it to the Xcode Organizer. From the Organizer, click Distribute App > App Store Connect and follow the prompts. Xcode handles the upload.


App Store Connect

At appstoreconnect.apple.com, create a new app with your Bundle ID and fill in:

  • App name and subtitle
  • Description and promotional text
  • Keywords (100 characters, comma-separated)
  • Screenshots — iPhone 6.5" and 5.5" are required; iPad if your app supports it
  • App icon at 1024x1024 pixels (no rounded corners — the store adds those)
  • Privacy policy URL
  • Support URL
  • App privacy labels (what data you collect and how it's used)

Select the build you uploaded via Xcode, complete all required fields, and submit for review.

Apple typically reviews within 1–3 days. Expect detailed feedback if anything is rejected — Apple's rejection messages are usually specific.


Common Rejection Reasons (iOS)

  • Placeholder content or lorem ipsum in screenshots or description
  • Broken functionality on smaller screen sizes (especially iPhone SE)
  • Missing or inaccurate privacy labels
  • Requesting permissions not actually used by the app
  • UI that doesn't follow platform conventions

Publishing Updates

Android: Increment both version name and build number, rebuild the AAB, create a new release in Play Console, upload, and submit.

iOS: Increment the build number in Xcode (the version visible to users can stay the same for minor updates), archive, upload via Xcode, and select the new build in App Store Connect.


Automation

Once you've done the manual process a few times, automation becomes worth the setup cost.

fastlane handles both platforms — it can build, sign, and upload to both stores from the command line. It has a Flutter-compatible setup.

Codemagic is a CI/CD platform built specifically for Flutter. It handles signing, building, and publishing, triggered by pushes to your repository.

GitHub Actions can run flutter build appbundle and upload to the Play Store using the r0adkll/upload-google-play action.


Before You Submit — A Quick Checklist

  • debugShowCheckedModeBanner is set to false
  • App icon and splash screen are production-quality
  • All permission usage descriptions are accurate and non-generic
  • The app has been tested on real devices, not just simulators
  • Your signing credentials are backed up securely somewhere other than your development machine
  • Privacy policy is live at a publicly accessible URL
  • Release notes are written for humans, not just "bug fixes"

Summary

Android publishing is faster and cheaper to start ($25 one-time). Apple's process is more strict and more expensive ($99/year), but the review feedback is usually actionable. Both stores reward apps that are complete, well-documented, and honest about what they do. Get the manual process right first, then automate it.

More from this blog

A

Anmol's blog

17 posts