Налаштування змінних середовища для розроблення мобільного додатка
Змінні середовища в мобільній розробці працюють інакше, ніж у веб-розробці. Мобільні додатки не мають доступу до process.env серверу в рантаймі. Все, що потребує знання додаток про своє оточення, має бути скомпільовано в бінарник під час збірки. Це принципово змінює підхід: замість .env файлів на сервері використовуємо build-time injection через CI та специфічні для платформи механізми.
Android: BuildConfig та manifestPlaceholders
Найпрямолінійніший спосіб на Android — використання buildConfigField у build.gradle.kts. Після компіляції AGP генерує клас BuildConfig з потрібними константами:
buildTypes {
debug {
buildConfigField("String", "API_KEY", "\"${System.getenv("API_KEY_DEV") ?: "fallback-dev-key"}\"")
buildConfigField("String", "SENTRY_DSN", "\"${System.getenv("SENTRY_DSN_DEV") ?: ""}\"")
}
release {
buildConfigField("String", "API_KEY", "\"${System.getenv("API_KEY_PROD") ?: ""}\"")
buildConfigField("String", "SENTRY_DSN", "\"${System.getenv("SENTRY_DSN_PROD") ?: ""}\"")
}
}
System.getenv() читає змінні середовища CI під час конфігурації Gradle. У Kotlin-коді звертаємося через: BuildConfig.API_KEY.
Для AndroidManifest.xml (наприклад, для Google Maps API Key) використовуємо manifestPlaceholders:
defaultConfig {
manifestPlaceholders["MAPS_API_KEY"] = System.getenv("MAPS_API_KEY") ?: ""
}
У AndroidManifest.xml: android:value="${MAPS_API_KEY}".
iOS: xcconfig та Info.plist
На iOS змінні передаються через xcconfig-файли або прямо через аргументи xcodebuild:
xcodebuild -scheme MyApp \
-configuration Release \
SENTRY_DSN="$SENTRY_DSN_PROD" \
API_KEY="$API_KEY_PROD" \
archive ...
Додаємо ключ SENTRY_DSN зі значенням $(SENTRY_DSN) до Info.plist, потім звертаємося в коді:
let sentryDSN = Bundle.main.object(forInfoDictionaryKey: "SENTRY_DSN") as? String ?? ""
React Native: react-native-config
Пакет react-native-config дозволяє використовувати .env файли, які компілюються в нативний код:
# .env.staging
API_URL=https://api-staging.myapp.com
STRIPE_KEY=pk_test_...
# .env.production
API_URL=https://api.myapp.com
STRIPE_KEY=pk_live_...
У коді: import Config from 'react-native-config'; Config.API_URL. Для CI використовуємо плагін envfile або копіюємо потрібний .env перед збіркою: cp .env.staging .env && npx react-native run-android.
Важливо: .env.* файли з реальними ключами не повинні потрапляти в репозиторій. Тільки .env.example з шаблоном закладається в репозиторій.
Flutter: --dart-define-from-file
# config/staging.json
{
"API_URL": "https://api-staging.myapp.com",
"SENTRY_DSN": "https://..."
}
flutter build apk \
--dart-define-from-file=config/staging.json \
--flavor staging
У Dart: const apiUrl = String.fromEnvironment('API_URL');
Секрети в CI
Реальні API ключі ніколи не зберігаються в репозиторії. Користуємося GitHub Secrets для GitHub Actions, CI/CD Variables (Masked) у GitLab CI або Secrets у Bitrise. Змінні впроваджуються в оточення агента, де Gradle/xcodebuild читають їх через System.getenv().
Процес
Аудит поточних захардкодованих значень → створення структури конфігів по оточеннях → налаштування build-time injection → перенесення секретів у змінні CI → документування для команди.
Період: 1–3 дні. Вартість розраховується індивідуально.







