iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

flutter build

Flutter build pipeline: dart compile to native binary, bundle assets, sign per platform, distribute. Use Flutter Build OR Codemagic/Bitrise/GitHub Actions for CI; ship via TestFlight, Play Internal, App Center, or your own URL.

flutter build apk / appbundle / ipa, signing, CI

EXAMPLE
# ===== Local builds =====

# Android APK (sideload-friendly, NOT for Play Store)
flutter build apk --release

# Android App Bundle (for Play Store)
flutter build appbundle --release
# Output: build/app/outputs/bundle/release/app-release.aab

# iOS (must run on macOS)
flutter build ios --release
# Output: build/ios/iphoneos/Runner.app -> archive in Xcode and export .ipa

# Web
flutter build web --release
# Output: build/web/ (deploy to Firebase Hosting, Netlify, S3+CloudFront)

# Windows / macOS / Linux desktop
flutter build windows --release
flutter build macos --release
flutter build linux --release

# ===== Signing — Android =====
# 1) Generate keystore ONCE
keytool -genkey -v -keystore ~/keys/app-release.jks \
  -keyalg RSA -keysize 2048 -validity 36500 -alias shop

# 2) Reference it from android/key.properties (gitignored)
# storeFile=/Users/you/keys/app-release.jks
# storePassword=...
# keyAlias=shop
# keyPassword=...

# 3) android/app/build.gradle reads key.properties:
# def keystoreProperties = new Properties()
# keystoreProperties.load(new FileInputStream(rootProject.file('key.properties')))
# android { signingConfigs { release { storeFile file(keystoreProperties['storeFile']) ... } } }

# 4) Build a signed bundle
flutter build appbundle --release

# ===== Signing — iOS =====
# 1) Apple Developer account; create App ID + bundle ID in Apple Developer
# 2) Open ios/Runner.xcworkspace in Xcode
#    Signing & Capabilities -> Team -> select; Automatic signing ON
# 3) Product -> Archive -> Distribute App -> App Store Connect
# Or use fastlane match (CI-friendly, shared signing materials in encrypted git repo)

# ===== Versioning =====
# pubspec.yaml
# version: 1.4.0+142          # 1.4.0 = userVisible; 142 = build number
flutter build apk --build-name 1.4.0 --build-number 142

# Bump via flutter_version_bump or fastlane increment_version_number

# ===== Flavours (dev/staging/prod) =====
# android/app/build.gradle
# productFlavors {
#   dev      { applicationIdSuffix '.dev'; resValue 'string', 'app_name', 'Shop Dev' }
#   staging  { applicationIdSuffix '.staging'; resValue 'string', 'app_name', 'Shop Staging' }
#   prod     { resValue 'string', 'app_name', 'Shop' }
# }
# flutter build apk --flavor dev

# iOS: Xcode schemes + xcconfig files

# ===== CI (GitHub Actions) =====
# .github/workflows/build.yml
# name: build
# on: [push]
# jobs:
#   android:
#     runs-on: ubuntu-latest
#     steps:
#       - uses: actions/checkout@v4
#       - uses: subosito/flutter-action@v2
#         with: { channel: 'stable' }
#       - run: flutter pub get
#       - run: flutter test
#       - run: flutter build appbundle --release
#       - uses: actions/upload-artifact@v4
#         with: { name: app-release-aab, path: build/app/outputs/bundle/release/app-release.aab }
#
#   ios:
#     runs-on: macos-latest
#     steps:
#       - uses: actions/checkout@v4
#       - uses: subosito/flutter-action@v2
#       - run: flutter pub get
#       - run: flutter test
#       - run: cd ios && pod install
#       - run: flutter build ipa --export-options-plist=ios/ExportOptions.plist

# ===== Distribute =====
# Internal:           Firebase App Distribution, TestFlight (iOS), Play Internal track (Android)
# External beta:      TestFlight (iOS), Play Open testing (Android)
# Production:         App Store + Play Store

# fastlane is the universal automation
# ios/Fastfile:    lane :beta do build_app(...); upload_to_testflight end
# android/Fastfile: lane :internal do gradle(task: 'bundleRelease'); upload_to_play_store(track: 'internal') end

# ===== Web deploys =====
flutter build web --release --web-renderer canvaskit
# Output: build/web/
# Deploy:
# firebase deploy --only hosting   # if using Firebase Hosting
# Or any static host

# ===== Code-push (over-the-air JS updates) =====
# Flutter has limited support; no first-class equivalent of Expo Update.
# Tools: shorebird.dev (commercial), patches via assets-only updates.
# For most teams: ship a new build for any code change.

# ===== Pitfalls =====
# - Forgetting to set versionCode in build.gradle -> Play rejects duplicate version
# - iOS provisioning profile mismatch -> Archive succeeds but Validate fails
# - Skipping minSdkVersion bump -> outdated targetSdk warnings from Play
# - Different flavour configs forgetting Firebase google-services.json per flavour
# - Forgetting to disable debug logs / API mocks in release builds

Why it matters

Use fastlane + EAS-style pipelines via GitHub Actions on macOS for iOS builds. Once signing materials live in a Match repo and CI runs `flutter build` + `fastlane`, releasing becomes "tag the repo" — and the entire team can ship instead of one person who knows Xcode.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
flutter build apk --release
flutter build appbundle --release
flutter build ios --release
flutter build web
Try it Yourself »

Discussion

Loading…