App Bundle (AAB)
Build Android App Bundles for Google Play Store
📦 What is an App Bundle?
Android App Bundle (AAB) is Google's publishing format for Android apps. It's smaller than APK and allows Google Play to generate optimized APKs for each device configuration, reducing download sizes significantly.
# Generate App Bundle
flutter build appbundle --release
# Output location
# build/app/outputs/bundle/release/app-release.aab
Output:
✓ Built build/app/outputs/bundle/release/app-release.aab (15.2MB)
AAB vs APK
Smaller Downloads
App Bundles enable Google Play to generate device-specific APKs, reducing download size by up to 35% compared to universal APKs by excluding unused resources.
# AAB: 15MB → APK: 10MB (per device)
Dynamic Delivery
Google Play uses AAB to deliver only the code and resources needed for each device's screen density, CPU architecture, and language, optimizing user experience.
# Only arm64 + hdpi + en delivered
Play Store Required
AAB is the required format for new apps on Google Play Store since August 2021. It cannot be installed directly on devices like APK files.
# Upload to Play Console only
App Signing
Google Play manages app signing with AAB through Play App Signing, providing additional security and allowing you to update your signing key if needed.
# Google signs final APKs
🔹 Building an App Bundle
Generate a release App Bundle for Google Play:
# Step 1: Clean project
flutter clean
# Step 2: Get dependencies
flutter pub get
# Step 3: Build App Bundle
flutter build appbundle --release
# Output location
# build/app/outputs/bundle/release/app-release.aab
Build Output:
Running Gradle task 'bundleRelease'...
✓ Built build/app/outputs/bundle/release/app-release.aab (15.2MB)
🔹 Configure App Signing
Set up signing configuration in android/app/build.gradle:
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
...
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
🔹 Play App Signing Setup
Enable Play App Signing in Google Play Console:
Steps to Enable:
- Go to Google Play Console
- Select your app
- Navigate to Release → Setup → App Signing
- Choose "Use Google-generated key" or upload your own
- Download the upload certificate
- Use upload key to sign your AAB
# Google manages the final signing key
# You sign with upload key
# Google re-signs with app signing key
🔹 Testing App Bundle Locally
Test AAB using bundletool before uploading:
# Download bundletool
# https://github.com/google/bundletool/releases
# Generate APKs from AAB
java -jar bundletool.jar build-apks \
--bundle=app-release.aab \
--output=app.apks \
--ks=my-release-key.jks \
--ks-key-alias=my-key-alias
# Install on connected device
java -jar bundletool.jar install-apks --apks=app.apks
# Get device-specific APK size
java -jar bundletool.jar get-size total \
--apks=app.apks
🔹 Upload to Play Console
Upload your App Bundle to Google Play Console:
Upload Steps:
- Open Google Play Console
- Select your app
- Go to Release → Production/Testing
- Create new release
- Upload app-release.aab
- Fill in release notes
- Review and rollout
🔹 AAB Optimization
Optimize your App Bundle for better performance:
# Build with obfuscation
flutter build appbundle --release \
--obfuscate \
--split-debug-info=./debug-info
# Analyze bundle size
flutter build appbundle --analyze-size
# Enable R8 full mode (android/gradle.properties)
android.enableR8.fullMode=true
Optimization Results:
Base AAB: 15.2MB
Optimized AAB: 12.8MB
Reduction: ~16%
🔹 Dynamic Feature Modules
Split your app into dynamic feature modules:
# pubspec.yaml
flutter:
deferred-components:
- name: feature_module
libraries:
- package:myapp/features/feature_module.dart
// Load feature dynamically
import 'features/feature_module.dart' deferred as feature;
Future loadFeature() async {
await feature.loadLibrary();
feature.showFeature();
}
🔹 Common AAB Issues
Troubleshoot common App Bundle problems:
Issue: Upload Key Mismatch
Solution: Ensure you're using the correct upload certificate from Play Console
Issue: Missing Signing Config
Solution: Verify key.properties file exists and build.gradle is configured correctly
Issue: AAB Too Large
Solution: Enable obfuscation, remove unused resources, optimize images