Build Process
Build Process
Section titled “Build Process”This guide covers the complete build process for deploying Lumo to production, including optimization, signing, and automation.
Build Configuration
Section titled “Build Configuration”Environment Setup
Section titled “Environment Setup”Production Configuration
Section titled “Production Configuration”class AppConfig { static const bool isProduction = bool.fromEnvironment( 'PRODUCTION', defaultValue: false, );
static const bool enableAnalytics = bool.fromEnvironment( 'ENABLE_ANALYTICS', defaultValue: isProduction, );
static const bool enableCrashReporting = bool.fromEnvironment( 'ENABLE_CRASH_REPORTING', defaultValue: isProduction, );
static const String apiBaseUrl = String.fromEnvironment( 'API_BASE_URL', defaultValue: isProduction ? 'https://api.yourapp.com' : 'https://api-dev.yourapp.com', );
static const String firebaseProjectId = String.fromEnvironment( 'FIREBASE_PROJECT_ID', defaultValue: 'your-app-production', );}Build Flavors Configuration
Section titled “Build Flavors Configuration”import 'package:flutter/foundation.dart';import 'core/config/app_config.dart';
void main() { // Configure based on build mode if (kDebugMode) { // Debug configuration setupDebugMode(); } else { // Production configuration setupProductionMode(); }
runApp(const MyApp());}
void setupProductionMode() { // Disable debug prints debugPrint = (String? message, {int? wrapWidth}) {};
// Enable crash reporting if (AppConfig.enableCrashReporting) { FlutterError.onError = (details) { // Send to crash reporting service FirebaseCrashlytics.instance.recordFlutterError(details); }; }}
void setupDebugMode() { // Keep debug prints enabled // Disable analytics in debug}Android Production Build
Section titled “Android Production Build”1. Signing Configuration
Section titled “1. Signing Configuration”Generate Release Keystore
Section titled “Generate Release Keystore”# Create release keystore (keep secure!)keytool -genkey -v \ -keystore android/app/release-keystore.jks \ -keyalg RSA \ -keysize 2048 \ -validity 10000 \ -alias release-key
# Example values:# First and Last Name: Your App Name# Organizational Unit: Mobile Development# Organization: Your Company# City: Your City# State: Your State/Province# Country Code: US# Password: Use a strong password!Configure Signing
Section titled “Configure Signing”Create android/key.properties:
storePassword=your_store_passwordkeyPassword=your_key_passwordkeyAlias=release-keystoreFile=release-keystore.jksUpdate android/app/build.gradle.kts:
import java.util.Propertiesimport java.io.FileInputStream
// Load keystore propertiesval keystoreProperties = Properties()val keystorePropertiesFile = rootProject.file("key.properties")if (keystorePropertiesFile.exists()) { keystoreProperties.load(FileInputStream(keystorePropertiesFile))}
android { namespace = "com.yourcompany.yourapp" compileSdk = 34
defaultConfig { applicationId = "com.yourcompany.yourapp" minSdk = 23 targetSdk = 34 versionCode = flutter.versionCode versionName = flutter.versionName
// ProGuard configuration for release builds proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) }
signingConfigs { create("release") { keyAlias = keystoreProperties["keyAlias"] as String keyPassword = keystoreProperties["keyPassword"] as String storeFile = file(keystoreProperties["storeFile"] as String) storePassword = keystoreProperties["storePassword"] as String } }
buildTypes { release { isMinifyEnabled = true isShrinkResources = true signingConfig = signingConfigs.getByName("release")
// Add build config fields buildConfigField("boolean", "ENABLE_LOGGING", "false") buildConfigField("String", "BUILD_TIME", "\"${System.currentTimeMillis()}\"") }
debug { applicationIdSuffix = ".debug" versionNameSuffix = "-debug" buildConfigField("boolean", "ENABLE_LOGGING", "true") } }}2. ProGuard Configuration
Section titled “2. ProGuard Configuration”Create android/app/proguard-rules.pro:
# Keep Flutter wrapper-keep class io.flutter.app.** { *; }-keep class io.flutter.plugin.** { *; }-keep class io.flutter.util.** { *; }-keep class io.flutter.view.** { *; }-keep class io.flutter.** { *; }-keep class io.flutter.plugins.** { *; }
# Keep Firebase-keep class com.google.firebase.** { *; }-keep class com.google.android.gms.** { *; }
# Keep Realm-keep class io.realm.** { *; }-dontwarn io.realm.**
# Keep crypto libraries-keep class javax.crypto.** { *; }-keep class java.security.** { *; }
# Keep app-specific classes-keep class com.yourcompany.yourapp.** { *; }
# Remove logging in release-assumenosideeffects class android.util.Log { public static *** d(...); public static *** v(...); public static *** i(...);}3. Build Commands
Section titled “3. Build Commands”App Bundle (Recommended for Play Store)
Section titled “App Bundle (Recommended for Play Store)”# Clean previous buildsflutter cleanflutter pub get
# Build optimized app bundleflutter build appbundle \ --release \ --obfuscate \ --split-debug-info=build/debug-info \ --dart-define=PRODUCTION=true \ --dart-define=ENABLE_ANALYTICS=true \ --dart-define=FIREBASE_PROJECT_ID=your-production-project
# Output: build/app/outputs/bundle/release/app-release.aabAPK Build
Section titled “APK Build”# Build release APKflutter build apk \ --release \ --obfuscate \ --split-debug-info=build/debug-info \ --dart-define=PRODUCTION=true
# Build split APKs by ABI (smaller downloads)flutter build apk \ --release \ --split-per-abi \ --obfuscate \ --split-debug-info=build/debug-info4. Verify Android Build
Section titled “4. Verify Android Build”# Check APK/AAB contentsaapt dump badging build/app/outputs/bundle/release/app-release.aab
# Test installationadb install build/app/outputs/flutter-apk/app-release.apk
# Check app sizels -lh build/app/outputs/flutter-apk/app-release.apkiOS Production Build
Section titled “iOS Production Build”1. Xcode Configuration
Section titled “1. Xcode Configuration”App Store Connect Configuration
Section titled “App Store Connect Configuration”- Open
ios/Runner.xcworkspacein Xcode - Select “Runner” project
- In “Signing & Capabilities”:
- Team: Select your Apple Developer team
- Bundle Identifier:
com.yourcompany.yourapp - Provisioning Profile: App Store (automatic)
Build Settings
Section titled “Build Settings”#include "Generated.xcconfig"
// Production configurationFLUTTER_BUILD_MODE=releaseDART_DEFINES=PRODUCTION=true,ENABLE_ANALYTICS=true,FIREBASE_PROJECT_ID=your-production-project
// OptimizationENABLE_BITCODE=NOSTRIP_INSTALLED_PRODUCT=YESCOPY_PHASE_STRIP=YESDEBUG_INFORMATION_FORMAT=dwarf-with-dsym
// SecurityGCC_GENERATE_DEBUGGING_SYMBOLS=YESGCC_OPTIMIZATION_LEVEL=sSWIFT_OPTIMIZATION_LEVEL=-O2. Build Commands
Section titled “2. Build Commands”Build for App Store
Section titled “Build for App Store”# Clean previous buildsflutter cleanflutter pub get
# Build iOS releaseflutter build ios \ --release \ --obfuscate \ --split-debug-info=build/debug-info \ --dart-define=PRODUCTION=true \ --dart-define=ENABLE_ANALYTICS=trueArchive in Xcode
Section titled “Archive in Xcode”- Open
ios/Runner.xcworkspace - Select “Any iOS Device (arm64)” or connected device
- Product → Archive
- When archive completes, select “Distribute App”
- Choose “App Store Connect”
- Upload to TestFlight/App Store
3. Automated iOS Build (CI/CD)
Section titled “3. Automated iOS Build (CI/CD)”name: iOS Buildon: push: tags: - 'v*'
jobs: build: runs-on: macos-latest steps: - uses: actions/checkout@v3
- name: Setup Flutter uses: subosito/flutter-action@v2 with: flutter-version: '3.8.1'
- name: Install dependencies run: flutter pub get
- name: Build iOS run: | flutter build ios \ --release \ --obfuscate \ --split-debug-info=build/debug-info \ --dart-define=PRODUCTION=true
- name: Archive with Xcode run: | cd ios xcodebuild -workspace Runner.xcworkspace \ -scheme Runner \ -configuration Release \ -archivePath Runner.xcarchive \ archive
- name: Export IPA run: | cd ios xcodebuild -exportArchive \ -archivePath Runner.xcarchive \ -exportPath ../build/ios \ -exportOptionsPlist ExportOptions.plistBuild Optimization
Section titled “Build Optimization”1. Code Optimization
Section titled “1. Code Optimization”Remove Debug Code
Section titled “Remove Debug Code”// Use kDebugMode for debug-only codeif (kDebugMode) { print('Debug information'); // Debug-only widgets}
// Use assertions for development checksassert(() { // Development-only validation return true;}());Asset Optimization
Section titled “Asset Optimization”# Optimize images before buildingfind assets -name "*.png" -exec pngquant --force --ext .png {} \;
# Optimize SVG filesfind assets -name "*.svg" -exec svgo {} \;2. Build Size Analysis
Section titled “2. Build Size Analysis”Android APK Analysis
Section titled “Android APK Analysis”# Analyze APK size breakdownflutter build apk --analyze-size
# Use bundletool for AAB analysisbundletool build-apks \ --bundle=build/app/outputs/bundle/release/app-release.aab \ --output=app.apks
bundletool get-size total --apks=app.apksiOS Size Analysis
Section titled “iOS Size Analysis”# Build with size analysisflutter build ios --analyze-size
# Xcode size report# Product → Archive → Distribute App → App Store Connect → Upload# View size report in App Store Connect3. Performance Optimization
Section titled “3. Performance Optimization”Dart/Flutter Optimizations
Section titled “Dart/Flutter Optimizations”# pubspec.yaml - Remove unused dependenciesdependencies: flutter: sdk: flutter # Only include necessary packages
dev_dependencies: # Only development toolsPlatform-Specific Optimizations
Section titled “Platform-Specific Optimizations”Android:
android { buildTypes { release { // Enable R8 full mode isMinifyEnabled = true isShrinkResources = true
// Optimize DEX files multiDexEnabled = false } }}iOS:
// Optimize Swift compilationSWIFT_OPTIMIZATION_LEVEL = -OSWIFT_COMPILATION_MODE = wholemodule
// Enable app thinningENABLE_APP_SLICING = YESAutomated Build Pipeline
Section titled “Automated Build Pipeline”1. GitHub Actions Workflow
Section titled “1. GitHub Actions Workflow”name: Build and Release
on: push: tags: - 'v*'
env: FLUTTER_VERSION: '3.8.1'
jobs: build-android: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v3
- name: Setup Java uses: actions/setup-java@v3 with: distribution: 'zulu' java-version: '11'
- name: Setup Flutter uses: subosito/flutter-action@v2 with: flutter-version: ${{ env.FLUTTER_VERSION }} cache: true
- name: Get dependencies run: flutter pub get
- name: Run tests run: flutter test
- name: Decode keystore run: | echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > android/app/keystore.jks echo "storeFile=keystore.jks" >> android/key.properties echo "storePassword=${{ secrets.KEYSTORE_PASSWORD }}" >> android/key.properties echo "keyPassword=${{ secrets.KEY_PASSWORD }}" >> android/key.properties echo "keyAlias=${{ secrets.KEY_ALIAS }}" >> android/key.properties
- name: Build AAB run: | flutter build appbundle \ --release \ --obfuscate \ --split-debug-info=build/debug-info \ --dart-define=PRODUCTION=true \ --dart-define=ENABLE_ANALYTICS=true
- name: Upload AAB artifact uses: actions/upload-artifact@v3 with: name: app-release.aab path: build/app/outputs/bundle/release/app-release.aab
build-ios: runs-on: macos-latest steps: - name: Checkout code uses: actions/checkout@v3
- name: Setup Flutter uses: subosito/flutter-action@v2 with: flutter-version: ${{ env.FLUTTER_VERSION }} cache: true
- name: Get dependencies run: flutter pub get
- name: Install CocoaPods run: cd ios && pod install
- name: Build iOS run: | flutter build ios \ --release \ --obfuscate \ --split-debug-info=build/debug-info \ --dart-define=PRODUCTION=true2. Build Scripts
Section titled “2. Build Scripts”Android Build Script
Section titled “Android Build Script”#!/bin/bashset -e
echo "Building Android release..."
# Clean previous buildsflutter cleanflutter pub get
# Run testsflutter test
# Build app bundleflutter build appbundle \ --release \ --obfuscate \ --split-debug-info=build/debug-info \ --dart-define=PRODUCTION=true \ --dart-define=ENABLE_ANALYTICS=true \ --dart-define=FIREBASE_PROJECT_ID=$FIREBASE_PROJECT_ID
echo "Android build complete!"echo "Output: build/app/outputs/bundle/release/app-release.aab"
# Optional: Upload to Play Consoleif [ "$UPLOAD_TO_PLAY_CONSOLE" = "true" ]; then echo "Uploading to Play Console..." # Use Google Play Developer API or fastlanefiiOS Build Script
Section titled “iOS Build Script”#!/bin/bashset -e
echo "Building iOS release..."
# Clean previous buildsflutter cleanflutter pub get
# Install CocoaPodscd ios && pod install && cd ..
# Run testsflutter test
# Build iOSflutter build ios \ --release \ --obfuscate \ --split-debug-info=build/debug-info \ --dart-define=PRODUCTION=true \ --dart-define=ENABLE_ANALYTICS=true
echo "iOS build complete!"echo "Next: Archive in Xcode and upload to App Store Connect"Build Verification
Section titled “Build Verification”1. Pre-Release Testing
Section titled “1. Pre-Release Testing”Automated Tests
Section titled “Automated Tests”# Run all tests before buildingflutter testflutter test integration_test/
# Performance testingflutter drive --target=test_driver/app.dartManual Testing Checklist
Section titled “Manual Testing Checklist”- App launches successfully
- All core features work
- Biometric authentication functions
- QR code scanning works
- Cloud backup/restore works
- App appears correctly in launcher
- Deep links function properly
- Performance is acceptable
2. Security Validation
Section titled “2. Security Validation”Code Obfuscation Verification
Section titled “Code Obfuscation Verification”# Verify obfuscation workedunzip -l build/app/outputs/bundle/release/app-release.aab | grep classes# Should show obfuscated class namesCertificate Verification
Section titled “Certificate Verification”# Android: Verify signingjarsigner -verify -verbose -certs build/app/outputs/bundle/release/app-release.aab
# iOS: Verify provisioning profilesecurity cms -D -i ios/Runner/embedded.mobileprovisionTroubleshooting
Section titled “Troubleshooting”Common Build Issues
Section titled “Common Build Issues”Android Issues
Section titled “Android Issues”# Issue: Build fails with "execution failed for task"# Solution: Clean and rebuildflutter cleancd android && ./gradlew clean && cd ..flutter pub getflutter build appbundle --release
# Issue: ProGuard errors# Solution: Update proguard-rules.pro with keep rulesiOS Issues
Section titled “iOS Issues”# Issue: Code signing errors# Solution: Check provisioning profiles and certificates# Xcode → Preferences → Accounts → Download Manual Profiles
# Issue: Pod install fails# Solution: Update CocoaPodscd iosrm -rf Pods Podfile.lockpod install --repo-updatecd ..Next Steps
Section titled “Next Steps”- Android Deployment - Deploy to Google Play
- iOS Deployment - Deploy to App Store
- Distribution - Alternative distribution methods
Your production builds are now ready for deployment! 🚀