Skip to main content

Building for Android

1. Understanding Android Project Structure

Directory Description Contents
android/ Root directory for Android-specific files build.gradle, gradle.properties, settings.gradle
android/app/ Flutter app's Android-specific code AndroidManifest.xml, MainActivity.kt/java
android/app/src/main/ Main Android app source directory AndroidManifest.xml, MainActivity.kt/java, res/
android/app/src/main/res/ Resources for the Android app mipmap-, drawable-, values- folders
android/app/src/main/AndroidManifest.xml App metadata and permissions Package name, app name, permissions

Example: AndroidManifest.xml snippet

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application
        android:name="io.flutter.app.FlutterApplication"
        android:label="my_flutter_app"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <meta-data
                android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
                android:value="true" />
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

2. Configuring build.gradle Files

Property Values Description
compileSdkVersion 34 SDK version to compile against
targetSdkVersion 34 SDK version to target for runtime behavior
minSdkVersion 21 Minimum Android API level supported

Example: build.gradle (Module: app)

android {
    compileSdk 34

    defaultConfig {
        applicationId "com.example.myapp"
        minSdk 21
        targetSdk 34
        versionCode 1
        versionName "1.0"
    }
}

Example: build.gradle (Project)

buildscript {
    ext.kotlin_version = "1.9.22"
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:8.1.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

3. Setting Application ID and Version

Field Value Description
applicationId com.example.myapp Unique identifier for the app on Android
versionName 1.0.0 User-facing version string
versionCode 1 Internal version number for Play Store

Example: AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <application
        android:label="MyApp"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

Example: build.gradle (Module: app)

android {
    compileSdk 34

    defaultConfig {
        applicationId "com.example.myapp"
        minSdk 21
        targetSdk 34
        versionCode 1
        versionName "1.0.0"
    }
}

4. Configuring Minimum SDK Version

Property Value Description
minSdkVersion 21 Minimum Android SDK version required to run the app
targetSdkVersion 33 Target Android SDK version for the app

Example: Setting minSdkVersion in build.gradle

android {
    compileSdk 33

    defaultConfig {
        applicationId "com.example.myapp"
        minSdkVersion 21
        targetSdkVersion 33
        versionCode 1
        versionName "1.0"
    }
}

5. Using Build Variants

Build variants in Flutter allow you to customize the app's behavior, configuration, and resources for different environments like development, staging, or production.

Variant Description Configuration File Usage
debug Used for development and debugging. Includes debug logs and enables hot reload. debug Default when running flutter run
release Optimized for production. Strips debug information and enables tree-shaking. release Used when building for distribution
profile Used for performance profiling. Includes performance metrics but not debug logs. profile Used when running flutter run --profile

Example: Setting up build variants in Gradle

android {
    defaultConfig {
        applicationId "com.example.myapp"
        minSdkVersion 21
        targetSdkVersion 33
    }

    buildTypes {
        debug {
            applicationIdSuffix ".debug"
            versionNameSuffix "-debug"
        }

        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }

        profile {
            initWith debug
            applicationIdSuffix ".profile"
        }
    }
}
Note: Build variants are managed in the build.gradle file for Android, and can be extended to support custom configurations like staging or QA environments.

6. Building APK

Example: Build APK for Release

flutter build apk --release
Option Values Description
--release true Builds a release version of the app
--build-number 1 Build number for the APK (must be incremented)
--build-name 1.0.0 Version name for the APK
--target lib/main.dart Entry point for the app
Note: Ensure that you have configured signing keys before building a release APK.
Warning: The --release flag is required for production builds.

7. Building App Bundle

Option Values Description
flutter build appbundle flutter build appbundle Builds the Android App Bundle for publishing to Google Play
--release --release Builds a release version of the app bundle
--target-platform android-arm64, android-arm Specifies the target architecture for the app bundle
--build-number 1 Sets the build number for the app bundle

Example: Building App Bundle

flutter build appbundle --release --target-platform android-arm64
Note: The app bundle is a new format for publishing Android apps that allows Google Play to generate optimized APKs for different devices.

8. Configuring ProGuard/R8

Example: Basic ProGuard Configuration

-keep class com.example.myapp.** { *; }
-keep class io.flutter.** { *; }
Option Description Default
proguard-rules.pro Path to ProGuard configuration file android/app/proguard-rules.pro
minifyEnabled Enables code shrinking and obfuscation false
shrinkResources Removes unused resources false
Note: R8 is the default code shrinker in Android Gradle Plugin 3.4.0+ and replaces ProGuard.
Warning: Incorrect ProGuard rules can break your app at runtime.

Key Considerations

  • Keep Flutter framework classes with -keep class io.flutter.** { *; }
  • Keep your application classes with -keep class com.example.myapp.** { *; }
  • Use -keepnames for debugging purposes
  • Test thoroughly after enabling minification

9. Using Build Flavors

Build flavors in Flutter allow you to customize your app for different environments or configurations, such as development, staging, and production. They are particularly useful for managing different API endpoints, app names, or branding.

Flavor Description Configuration
dev Development environment with debug features and local API endpoints. Uses dev configuration in pubspec.yaml.
staging Staging environment for testing before production. Uses staging configuration in pubspec.yaml.
prod Production environment with optimized settings. Uses prod configuration in pubspec.yaml.

Example: Defining Build Flavors in pubspec.yaml

flutter:
  uses-material-design: true

  # Define build flavors
  flavor_strings:
    dev:
      app_name: "MyApp Dev"
      api_url: "https://api.dev.example.com"
    staging:
      app_name: "MyApp Staging"
      api_url: "https://api.staging.example.com"
    prod:
      app_name: "MyApp"
      api_url: "https://api.example.com"

Example: Using Flavor Configuration in Code

class AppConfig {
  static String get appName => _getFlavorString('app_name');
  static String get apiUrl => _getFlavorString('api_url');

  static String _getFlavorString(String key) {
    // This is a simplified example; actual implementation depends on
    // how you load flavor configuration.
    return 'default_value';
  }
}
Note: Build flavors are managed via the flavor_strings in pubspec.yaml. You can define different configurations for each flavor and access them in your app code.

10. Configuring App Signing

App signing is required for publishing Flutter apps to the Google Play Store. Flutter uses the Android build system to handle app signing.

Property Description Default Value
keyAlias Alias of the signing key in the keystore flutter
keyPassword Password for the signing key None
storeFile Path to the keystore file None
storePassword Password for the keystore None

Example: Setting up app signing in gradle.properties

storePassword=your_store_password
keyPassword=your_key_password
keyAlias=your_key_alias
storeFile=../path/to/keystore.jks
Note: The keystore file should be stored securely and never committed to version control.
Warning: If you lose your keystore, you won't be able to update your app on the Play Store.

Was this article helpful?