Mastering Flutter App Deployment: From Dev to Play Store & App Store
The Flutter news you actually need
No spam, ever. Unsubscribe in one click.
So you’ve built your Flutter app—maybe with a visual builder, maybe with pure code—and it’s running beautifully on your device. Now comes the real challenge: getting it into users’ hands. The journey from development build to published app can feel like navigating a maze of certificates, provisioning profiles, and store listings. Let’s demystify the process.
The Core Challenge: It’s More Than Just Building
The fundamental gap many developers face isn’t writing Flutter code—it’s understanding that deployment is a separate discipline. Your app needs proper signing, configuration, and store-specific packaging. Whether you’re using FlutterFlow or writing everything from scratch, these steps remain essential.
Phase 1: Pre-Deployment Checklist
Before touching any store console, ensure your app is truly ready:
- App Configuration: Update your
pubspec.yamlwith final metadata:
name: my_production_app
description: A fantastic Flutter application
version: 1.0.0+1
The version format is versionName+versionCode for Android and version+build for iOS. The + separates semantic version from build number.
- Platform-Specific Setup:
- Android: Configure your
android/app/build.gradle:
- Android: Configure your
android {
compileSdkVersion 34
defaultConfig {
applicationId "com.yourcompany.yourapp"
minSdkVersion 21
targetSdkVersion 34
versionCode 1
versionName "1.0.0"
}
signingConfigs {
release {
storeFile file("your-upload-key.keystore")
storePassword "your_password"
keyAlias "your_key_alias"
keyPassword "your_key_password"
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
- iOS: Update
ios/Runner/Info.plistwith proper descriptions for all permission requests, and configure your project in Xcode with your team and bundle identifier.
Phase 2: Generating Release Builds
Android APK/AAB
For the Play Store, you need an Android App Bundle (AAB):
flutter build appbundle
Common Mistake: Using APK for Play Store submissions. Google now requires AAB for new apps. The AAB generates optimized APKs for different device configurations.
iOS IPA
For the App Store, build through Xcode or use:
flutter build ipa
Critical Step: You must configure code signing in Xcode. Open ios/Runner.xcworkspace, select your target, and under “Signing & Capabilities,” ensure your team is selected and provisioning profiles are correctly set.
Phase 3: App Signing Secrets
Android Keystore
If you don’t have a signing key, generate one:
keytool -genkey -v -keystore ~/upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload
Protect this file with your life! Losing it means you cannot update your app. Store passwords securely—never commit them to version control.
iOS Certificates and Profiles
This is where many developers stumble. You need:
- An Apple Developer account ($99/year)
- A production certificate from Apple Developer Portal
- A provisioning profile linking your certificate to your app ID
- The profile installed on your build machine
Phase 4: Store Listings and Submission
Play Store Preparation
- Create a Play Console account (one-time $25 fee)
- Prepare assets:
- 512x512 icon
- Feature graphic (1024x500)
- Screenshots for phone and tablet
- Write compelling description and privacy policy
App Store Preparation
- Create App Store Connect entry
- Prepare assets:
- 1024x1024 icon (no transparency)
- Screenshots for all iPhone and iPad sizes
- Complete the detailed questionnaire about data collection
Phase 5: The Submission Process
Play Store Steps:
- Create new application in Play Console
- Upload your AAB to “Production” track
- Complete content rating questionnaire
- Set pricing and distribution
- Review and publish (can take hours to days for review)
App Store Steps:
- Archive your app in Xcode
- Validate the archive
- Distribute to App Store Connect
- In App Store Connect, add build to your app version
- Submit for review (typically takes 24-48 hours)
Common Pitfalls and Solutions
“My iOS build fails with code signing errors” Double-check: Are your certificates installed in Keychain Access? Does your provisioning profile include the device you’re testing on? In Xcode, try Product → Clean Build Folder and rebuild.
“Play Store rejects my AAB”
Ensure your android/app/build.gradle has minSdkVersion set to at least 21, and you’ve declared all necessary permissions in AndroidManifest.xml.
“App crashes on launch in release mode”
Test with flutter run --release locally first. Add proper error handling and consider using flutter build apk --split-per-abi to test on physical devices before store submission.
“Missing 64-bit support” (Android)
Flutter has included 64-bit support for years, but ensure you’re not using old plugins that might lack it. Run flutter build appbundle and check the output contains both armeabi-v7a and arm64-v8a.
Post-Submission Mindset
Once submitted, don’t just wait. Prepare your first update! You’ll inevitably find small fixes needed. Set up crash reporting with firebase_crashlytics or sentry_flutter:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await SentryFlutter.init(
(options) => options.dsn = 'YOUR_DSN',
appRunner: () => runApp(MyApp()),
);
}
Deployment isn’t a one-time event but a skill you’ll refine with each release. Take detailed notes of your process, save all credentials securely, and remember: every published app started with someone figuring out these exact steps. Your app deserves to be out in the world—now you have the map to get it there.
This blog is produced with the assistance of AI by a human editor. Learn more
Related Posts
Localizing Dynamic Content in Flutter: A Guide to Backend-Driven Translations
Many Flutter apps need to display content that changes based on user locale, but also comes from a backend (like Firebase). This post will explore best practices for fetching and integrating dynamic, localized content from a backend, ensuring a seamless user experience across different languages and regions without hardcoding translations.
Unraveling Type Mismatch Errors in Flutter: A Guide to 'X can't be assigned to Y' and '_InternalLinkedHashMap' Issues
Developers frequently encounter cryptic type mismatch errors like 'The argument type X can't be assigned to the parameter type Y' or '_InternalLinkedHashMap has no instance method 'cast''. This post will demystify these common Flutter/Dart type errors, explain their root causes (e.g., conflicting imports, dynamic typing pitfalls, JSON deserialization issues), and provide practical solutions to diagnose and fix them, improving code robustness and reducing debugging time.
Solving Flutter Web Memory Leaks: A Practical Guide to Identifying and Fixing Performance Issues
Flutter Web applications can suffer from increasing memory usage over time, leading to performance degradation. This post will delve into common causes of memory leaks in Flutter Web, provide practical debugging techniques using browser developer tools and Dart DevTools, and offer actionable strategies to identify and fix these issues for a smoother user experience.