Настройка Environment Variables для разных окружений мобильного приложения
Переменные окружения в мобильной разработке — не то же самое, что в веб. У мобильного приложения нет runtime-доступа к 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 ...
В Info.plist добавляем ключ SENTRY_DSN со значением $(SENTRY_DSN), и в коде:
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 Actions — Secrets, в GitLab CI — CI/CD Variables (Masked), в Bitrise — Secrets. Переменные инжектируются в среду выполнения агента, Gradle/xcodebuild читают их через System.getenv().
Процесс
Аудит текущих захардкоженных значений → создание структуры конфигов по окружениям → настройка build-time injection → перенос секретов в CI variables → документация для команды.
Срок: 1–3 дня. Стоимость рассчитывается индивидуально.







