Flutter: Multi-Platform Publishing and Store Review

📋 Prerequisites: You should have mastered the following first

1. What You Will Learn


2. A Real Story of a Rejected Submission


3. Multi-Platform Publishing Process


4. Android Publishing


5. iOS Publishing


6. Web Publishing


7. Privacy Compliance


8. Complete Example: ShopApp Publishing Checklist


9. ShopApp Release Checklist v1.2.3

After Bob prepared using the checklist, both App Store and Google Play passed on the first submission, and the Web version went live within 1 hour.

100%
graph TD
    REL[Release Process] --> ANDROID2[Android AAB]
    REL --> IOS2[iOS IPA]
    REL --> WEB2[Web PWA]
    ANDROID2 --> PC[Play Console]
    IOS2 --> ASC[App Store Connect]
    WEB2 --> FH[Firebase Hosting / Vercel]
    PC --> REVIEW1[Google Review]
    ASC --> REVIEW2[Apple Review]
    REVIEW1 --> LIVE1[Live on Google Play]
    REVIEW2 --> LIVE2[Live on App Store]
    FH --> LIVE3[Live on Web]

(1) Signing and Build

▶ Example: Generate Keystore

BASH
# Generate signing keystore
keytool -genkey -v -keystore shopapp-release.jks \
  -keyalg RSA -keysize 2048 -validity 10000 \
  -alias shopapp

# Verify keystore
keytool -list -v -keystore shopapp-release.jks -alias shopapp

build.gradle Signing Configuration

GROOVY
// android/app/build.gradle
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}

android {
    defaultConfig {
        applicationId "com.shopapp.app"
        minSdkVersion 21
        targetSdkVersion 34
        versionCode 42
        versionName "1.2.3"
    }
    signingConfigs {
        release {
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile keystoreProperties['keyFile'] ? file(keystoreProperties['keyFile']) : null
            storePassword keystoreProperties['keyPassword']
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

Build and Publish

BASH
# Build release AAB (Android App Bundle)
flutter build appbundle --release
# Output: build/app/outputs/bundle/release/app-release.aab

# Build release APK (for testing)
flutter build apk --release

# Upload to Play Console manually or via CI/CD

(2) Play Console Launch Checklist

Item Requirement
Application ID Unique package name com.shopapp.app
AAB file Signed release bundle
Icon 512x512 PNG
Screenshots 2-8 each for phone + 7-inch tablet
Privacy Policy URL Must be accessible
Content rating Complete IARC questionnaire
Target audience Select age range

(1) Apple Developer Configuration

Step Action
1. Register Apple Developer Program ($99/year)
2. Certificate Create Distribution Certificate
3. Profile Create App Store Provisioning Profile
4. App ID Register Bundle Identifier
5. App Record Create app in App Store Connect

Xcode Build Configuration

XML
<!-- ios/Runner/Info.plist -->
`<key>`CFBundleShortVersionString</key>
`<string>`1.2.3</string>
`<key>`CFBundleVersion</key>
`<string>`42</string>
`<key>`NSAppTransportSecurity</key>
`<dict>`
    `<key>`NSAllowsArbitraryLoads</key>
    `<false/>`
`</dict>`
`<key>`NSUserTrackingUsageDescription</key>
`<string>`We use tracking to personalize your shopping experience.</string>

Build and Upload

BASH
# Build IPA
flutter build ipa --release \
  --export-options-plist=ios/ExportOptions.plist
# Output: build/ios/ipa/shopapp.ipa

# Upload via Xcode or command line
xcrun altool --upload-app \
  --type ios \
  --file build/ios/ipa/shopapp.ipa \
  --apiKey YOUR_API_KEY \
  --apiIssuer YOUR_ISSUER_ID
# Or via Transporter app

(2) App Store Connect Launch Checklist

| Bundle ID | Must match Xcode project | | IPA file | Release build | | Screenshots | 6.7"/6.5"/5.5" three sizes | | Preview video | Optional, ≤30s | | Description | ≤4000 characters |

▶ Example: Apple Privacy List Compliance

DART
import 'package:flutter/material.dart';
import 'package:app_tracking_transparency/app_tracking_transparency.dart';
import 'package:firebase_analytics/firebase_analytics.dart';

// Dependencies: app_tracking_transparency: ^0.2.0, firebase_analytics: ^10.0.0 (add to dependencies)

Future<void> requestTrackingPermission() async {
  final status = await AppTrackingTransparency.requestTrackingAuthorization();
  if (status == TrackingStatus.authorized) {
    await FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(true);
  } else {
    await FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(false);
  }
}

Output:

TEXT
App Tracking Transparency dialog displayed
Status: authorized (or denied)
Analytics collection enabled/disabled accordingly

(1) Compliance Requirements Comparison

Platform Required Items
Google Play Privacy Policy / Data Safety Form / Content Rating
App Store Privacy Policy / ATT / Encryption Compliance Declaration
Web (PWA) GDPR Cookie Consent / Privacy Policy

(2) Privacy Compliance Checklist

Pre-release Checks

Three-Platform Publishing Checklist

(1) Android

(2) iOS

(3) Web

(4) Post-release

❓ FAQ

Q What's the difference between AAB and APK?
A AAB (Android App Bundle) is the upload format — Google Play automatically generates optimized APKs from it. AABs are smaller because they only include resources needed by the device.
Q How long does App Store review usually take?
A First submissions typically take 24-48 hours, updates usually 12-24 hours. Re-submissions after rejection require another wait.
Q How should I manage versionCode and versionName?
A versionCode must be an incrementing integer (+1 for each release); versionName is user-visible (e.g., 1.2.3). Use SemVer conventions.
Q Does the Web version need ICP filing?
A Servers in mainland China require ICP filing. Overseas servers (Firebase/Vercel) do not.
Q What does GDPR compliance require?
A 1) Show privacy consent on first launch; 2) Provide a data deletion option; 3) Privacy policy link; 4) Minimize data collection; 5) Users can revoke consent.
Q What should I do if the App Store rejects my submission?
A Carefully read the rejection reason, fix the issues, and resubmit. Common reasons: missing privacy policy, ATT popup not shown, crashes, content policy violations.

📖 Summary


(1) Example: Version Number Release Cadence

TEXT
1.0.0  →  MVP launch (first release)
1.0.1  →  Urgent bug fix (patch)
1.1.0  →  New feature (minor)
1.2.3  →  ShopApp release (minor + patch)
2.0.0  →  Major refactoring (major)

Output:

TEXT
SemVer: MAJOR.MINOR.PATCH
- MAJOR breaking changes
- MINOR compatible additions
- PATCH compatible fixes

(2) Example: Firebase Crashlytics Integration

DART
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'dart:ui' show PlatformDispatcher;

// Dependencies: firebase_core: ^2.0.0, firebase_crashlytics: ^3.0.0 (add to dependencies)
// ShopApp comes from project lib/app.dart

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  FlutterError.onError = (details) {
    FirebaseCrashlytics.instance.recordFlutterFatalError(details);
  };

  PlatformDispatcher.instance.onError = (error, stack) {
    FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
    return true;
  };

  runApp(const ShopApp());
}

Output:

TEXT
Crashlytics initialized
Fatal errors auto-reported
Non-fatal errors auto-reported

(3) Example: Release Monitoring Dashboard

BASH
# Firebase Crashlytics
firebase functions:log --only publishMonitor
# Expected output:
# {"status":"ok","version":"1.2.3","crashRate":"0.05%"}

Output:

TEXT
Crash rate after rollout:
- 1h: 0.05% (baseline 0.10%)
- 24h: 0.04% (healthy)
- ANR rate: 0.01% (acceptable)

📝 Exercises

  1. Basic (Difficulty ⭐): Generate an Android Keystore for ShopApp, configure build.gradle signing, and successfully build a release AAB.
  2. Intermediate (Difficulty ⭐⭐): Complete ShopApp dual-platform publishing preparation — Android AAB signing + iOS certificate configuration, and write a multi-platform publishing checklist.
  3. Challenge (Difficulty ⭐⭐⭐): Implement the full ShopApp cross-platform publishing process (Android + iOS + Web), including privacy compliance declarations, multi-channel screenshot generation, and App Store description writing.

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏