Mobile Development

Flutter App Publishing Checklist: Everything to Do Before You Submit

The Debuggers Engineering Team
5 min read

After weeks or months of intensive coding, your Flutter application is finally feature complete. It runs perfectly on your local simulator and you are eager to ship it to the world. However, the gap between a working development project and a production ready release candidate is massive. Preparing your app for the Google Play Store and the Apple App Store requires a rigorous audit.

Submitting an incomplete or unoptimized application guarantees a swift rejection from the app review teams. Even worse, it can lead to negative user reviews on launch day. To ensure a smooth, professional release, you must meticulously verify every asset, configuration file, and legal requirement. This comprehensive checklist provides everything you need to do before you compile your final release build.

Shared Checklist for Both Platforms

Before focusing on platform specific nuances, you must handle the core requirements shared across both iOS and Android ecosystems. These elements are universally required by both Apple and Google.

Version Number and Build Number

Every time you submit a new binary to the app stores, it must possess a unique version number and a unique build number. In Flutter, you configure this in your pubspec.yaml file under the version key. The format is version: x.y.z+build. For a brand new application, you should generally start with version: 1.0.0+1. The x.y.z portion represents the standard semantic versioning (Major, Minor, Patch). This is the public version number users see in the store. The +build portion is the internal build integer. Every single time you generate an archive for upload, you absolutely must increment the build integer, for example, from +1 to +2.

Complete Privacy Policy Requirement

A legally binding privacy policy is no longer optional. Both Apple and Google mandate a public, accessible privacy policy for absolutely every application, even if your app does not explicitly collect user data. You must host this policy on a live website, not a Google Doc or a local PDF. The policy must clearly state what data you collect, how you process it, and who you share it with. Ensure the URL is fully responsive, because reviewers will invariably check it on a mobile browser.

High Resolution App Store Screenshots

Your store listings demand pixel perfect screenshots to showcase your functionality. Do not submit raw emulator captures showing debug banners or overlapping navigation bars. You should use physical devices or high quality design templates to wrap your raw screenshots in appealing frames. You must provide specific resolutions for different device classes. For instance, Apple requires specific 6.5 inch and 5.5 inch display captures, while Google is slightly more forgiving with varied aspect ratios. Ensure the text in your screenshots is massive and easily readable on a small phone screen.

Release Build vs Debug Build Differences

You must never attempt to submit a debug build to a public store. Debug builds are massively bloated because they contain hot reload tooling, uncompressed assets, and dart specific developer extensions. They run slowly and consume excess memory. A release build is completely stripped of this overhead and compiled Ahead of Time (AOT) to native machine code for maximum performance. When you are ready to test the absolute final state of your app, always run flutter run --release on a physical device. This command simulates the exact performance profile your end users will experience. If your app stutters in release mode, you have a critical optimization problem you must fix before submission.

Testing on Real Physical Devices

Simulators and emulators are incredibly useful for rapid prototyping, but they are not accurate representations of constrained hardware. You must install your final release build on the oldest, weakest physical phones you can acquire. Test your application in extremely low data environments, test it in Airplane mode to ensure your error handling is robust, and test it aggressively on small screens to ensure your UI padding scales correctly. If your app crashes gracefully with a helpful user prompt, you have succeeded. If it white screens silently, you will be rejected.

Comprehensive Permissions Audit

Mobile operating systems strictly govern access to hardware APIs like the camera, microphone, and location sensors. You must perform a total audit of every permission your app requests. In Flutter, many highly complex plugins automatically inject permission requests into your compiled manifest files without you explicitly realizing it. If your app suddenly asks for background location access but only features a simple text list, Apple and Google will ban your submission instantly. You must meticulously review your AndroidManifest.xml and Info.plist files, removing absolutely any permission strings you are not actively explaining to your users.

Dedicated Android Checklist

Android is a fragmented ecosystem with thousands of unique hardware configurations. Preparing your Flutter app for the Google Play Console requires specific configurations.

Keystore Generation and Secure Storage

Unlike iOS where Apple handles the complex provisioning dynamically, Android relies heavily on a static cryptographic Keystore. Ensure your upload-keystore.jks file is generated with a highly secure password and backed up in at least three separate, secure physical locations. If your hard drive crashes and you lose this single file, you will never be able to push another update to your existing app listing. Check your android/app/build.gradle file carefully to verify it is reading your key.properties configuration correctly for the release signing block.

Adaptive App Icon Sizes

Android utilizes adaptive icons, meaning the system can crop and mask your app icon into circles, squares, or custom shapes depending on the device manufacturer's skin. You must provide a highly layered icon structure. The foreground image must have a transparent background, and the background image must be a solid color or a simple gradient. You can use community tools like flutter_launcher_icons to automatically generate the vast array of necessary mipmap directories (from mdpi up to xxxhdpi). Provide a 512x512 high resolution icon specifically for the Google Play Store listing.

Splash Screen API Migration

Starting with Android 12, Google radically completely overhauled the splash screen system. Older Android implementations using a static drawable in the styles configuration will look broken or flash abruptly on modern devices. You must implement the official androidx.core:core-splashscreen library or utilize a maintained Flutter package like flutter_native_splash to ensure your initial loading experience bridges the gap smoothly between the native OS layer and the Dart engine initialization.

Generate the App Bundle Format

Never compile a fat APK file for distribution. A fat APK contains all binary architectures compiled together, resulting in a bloated download size for the end user. You must compile your final asset using the flutter build appbundle command. This generates an .aab file containing optimized base modules. The Google Play Console reads this bundle and dynamically generates tiny, device specific APK packages. This dramatically reduces user download friction resulting in significantly lower uninstall rates.

Dedicated iOS Checklist

Publishing to the Apple App Store requires jumping through incredibly specific, stringent hoops. Keep this checklist handy before uploading to App Store Connect.

Provisioning Profiles and Certificates

Ensure your Apple Developer account is active and in good standing. You must generate a highly secure Certificate Signing Request on your Mac, upload it to the Apple Developer portal, and download the resulting Distribution Certificate into your local Keychain. Next, create a specific App Store Provisioning Profile linked explicitly to your App ID and Certificate. Inside Xcode, disable "Automatically manage signing" for release builds and manually select your custom profile to guarantee a clean, unblemished archive process.

Info.plist Clarifications for Privacy

Apple heavily penalizes apps that utilize hardware permissions without explicit, detailed justification. You must meticulously document every permission requested in your ios/Runner/Info.plist file. If your plugin requires the camera, you must include the NSCameraUsageDescription key with a highly specific value like "This app requires the camera to take profile pictures." Generic descriptions such as "Needed for app functionality" are entirely guaranteed to result in a swift rejection from the App Store review board. You must also declare exactly what data you extract in the App Privacy section of App Store Connect.

Xcode Build Validation

Before compiling, you must ensure your project builds correctly in Xcode. Even if the Flutter command works flawlessly, Xcode controls the final cryptographic packaging. Open your ios/Runner.xcworkspace file natively in Xcode. Set the build target strictly to "Any iOS Device". In the top navigation menu, gracefully select Product, then Archive. If this archive compiles successfully without throwing horrifying red linkage errors, your setup is rock solid.

Removing Simulator Architectures

Flutter plugins often contain specific compiled binaries specifically for iOS simulator environments (the x86_64 architecture). Submitting an app containing these simulator slices will result in an immediate automated failure email from Apple's backend processing system. The modern flutter build ipa command typically handles this stripping process automatically, but if you attempt to use older legacy build methods, you must ensure you are explicitly archiving only the arm64 architecture intended for real hardware devices.

Summary

Publishing a highly polished, professional mobile application is a challenging but incredibly rewarding experience. By following this exhaustive checklist, you systematically eliminate the absolute most common reasons for rejection. You protect your users by prioritizing privacy policies, you guarantee functionality by testing extensively in release mode on weak physical hardware, and you secure your developer identity using strict cryptographic processes. Once all boxes are fully checked, take a deep breath, push your compiled bundle to the stores, and prepare yourself to welcome your very first users. Good luck.

Need Help Implementing This in a Real Project?

Our team supports end-to-end development for web and mobile software, from architecture to launch.

Found this helpful?

Join thousands of developers using our tools to write better code, faster.