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 webTry it Yourself »
Discussion
Loading…