Configuration management is one of the most underestimated aspects of mobile development. According to CloudBees (2025), 47% of production incidents are related to incorrect build configurations. Proper setup of Build Variant, Scheme, and .env files is the key to stable CI/CD and predictable releases.
Key Takeaways
Build Variant — a combination of Build Type (debug/release/staging) and Product Flavor (free/paid, demo/full). Gradle automatically creates a variant for each combination: freeDebug, freeRelease, paidDebug, paidRelease. Each variant can have its own code, resources, and dependencies — this is the foundation of configuration management in mobile apps on Android.
Build Type — build settings: whether debugging is enabled, signing, ProGuard optimization. debug by default contains debuggable=true, release — minifyEnabled=true.
Product Flavor — app variant: free, paid, demo. Flavors can have different applicationId, resources, SDK dependencies.
// build.gradle — configuring Android product flavors
android {
productFlavors {
free {
applicationId "com.example.app.free"
versionName "1.0-free"
}
paid {
applicationId "com.example.app.paid"
versionName "1.0-paid"
}
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt')
}
}
}
The example creates two flavors: free and paid. A separate applicationId is set for free — this allows installing both apps on one device. BuildConfig is generated for each variant: BuildConfig.FLAVOR = "free", BuildConfig.BUILD_TYPE = "debug". Use BuildConfig in code for conditional logic.
settings.gradle — the root Gradle file that describes project modules.
Gradle KTS — an alternative to Groovy using Kotlin DSL. KTS provides autocomplete in Android Studio and type checking. Recommended for new projects.
Configuration management in iOS is built on Scheme — an Xcode configuration that defines what and how to build: Build Configuration (Debug/Release), tests, analysis, archiving. Schemes can be duplicated for different environments (Development, Staging, Production). Schemes are stored in .xcscheme files in the xcshareddata folder.
.xcconfig — an Xcode configuration file that stores build settings in text form. For mobile app configuration management, iOS uses .xcconfig: versioning in Git, reuse across projects, fewer manual settings. .xcconfig sets SWIFT_ACTIVE_COMPILATION_CONDITIONS, PRODUCT_BUNDLE_IDENTIFIER, CODE_SIGN_IDENTITY.
Info.plist — the app metadata file. It stores the version, identifier, permissions. Info.plist can differ for each Scheme — via Info.plist File in Build Settings.
AndroidManifest.xml — the Android equivalent: stores permissions, components, meta-data.
Scheme — the build scenario (what to do). Build Configuration — the settings set (how to do it). One Scheme uses one Build Configuration (Debug or Release). For CI/CD: configure the Archive action to Release and the Test action to Debug in one Scheme.
pubspec.yaml — the Flutter project configuration file. Contains dependencies, versions, resources. Supports environment variables via --dart-define.
Podfile — the CocoaPods dependency manager for iOS. Defines library versions and platform.
.env — a file with environment variables for all platforms. Flutter and React Native use a different approach to configuration management: dart-define in Flutter, react-native-config in React Native. Configuration management in cross-platform projects involves different tools depending on the stack.
.env — a text file with key=value pairs. Not committed to Git (add to .gitignore). For Flutter — flutter_dotenv, for iOS — Config.xcconfig with #include, for Android — BuildConfig. env variables: API_URL, SENTRY_DSN, APP_SECRET. In mobile development configuration management, .env is the de facto standard for storing secrets outside the repository.
Podfile describes CocoaPods dependencies and platform (platform :ios, '15.0'). pubspec.yaml for Flutter — dependencies and dev_dependencies. Both support conditional dependencies: pod 'Analytics', :configs => ['Release'] or flutter pub add --flavor free. At IT Sectr, we use .env + BuildConfig for secrets and Podfile for native dependencies in mobile projects.
| Parameter | Android | iOS | Flutter |
|---|---|---|---|
| Configuration unit | Build Variant | Scheme | Flavor (--flavor) |
| Build file | build.gradle | .xcconfig | pubspec.yaml |
| Conditional code | BuildConfig | Active Compilation Conditions | dart-define |
| Secrets | BuildConfig/NDK | .xcconfig | .env/dart-define |
| Dependency manager | Gradle (Maven) | SPM/CocoaPods | pub (dart) |
The table shows key differences in configuration management between mobile platforms. Android offers more flexibility through Build Variant. iOS is simpler but less flexible. Flutter centralizes configuration in dart-define, but native dependencies still require configuring Podfile/build.gradle.
Conditional Compilation — including or excluding code at compile time depending on flags. This is part of configuration management: it allows embedding debug tools (logging, inspector) in debug builds and removing them from release. Implementation differs across platforms.
#if DEBUG — Swift preprocessor directive. Code inside the block compiles only in Debug configuration. Other flags: #if !RELEASE, #if targetEnvironment(simulator). Active Compilation Conditions in Build Settings — add custom flags via -D FLAG_NAME. Configuration management of builds through compilation conditions is standard practice in iOS.
BuildConfig.DEBUG — boolean field, true in debug build. BuildConfig is generated automatically by Gradle. For custom flags use buildConfigField in build.gradle: buildConfigField "boolean", "REPORT_CRASHES", "true". In code: if (BuildConfig.REPORT_CRASHES) { ... }.
dart-define — Flutter compilation flags: flutter run --dart-define=ENV=staging. In code: const env = String.fromEnvironment('ENV', defaultValue: 'production'). For conditional mobile app builds, use the build_runner plugin with code generation.
Frequently Asked Questions
Build Variant = Build Type (debug/release) + Product Flavor. Flavor is the app variant (paid/free, client/server), Build Type is build settings (debug/optimization). The combination of flavor + type forms a variant: for example, paidDebug.
.xcconfig is an Xcode configuration file that stores build settings in text form. It allows moving settings from the Xcode project into Git-friendly files, simplifying CI/CD and team collaboration in mobile projects.
API keys must not be stored in code — any .apk or .ipa can be decompiled. Use .env files, a backend proxy, or obfuscation via Build Config. IT Sectr recommends storing secrets on the server and issuing them to the client after authentication.
Conditional Compilation is including/excluding code at compile time depending on flags. In Swift — #if DEBUG, in Kotlin — BuildConfig.DEBUG. Used to enable logging in debug and disable it in release. This is a key element of configuration management in mobile development.
Podfile is only used when working with CocoaPods. It is not needed for SPM or Carthage. Do not leave Podfile in a project if you have abandoned CocoaPods — it confuses the team and the CI/CD system.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.