Променливите на средата са динамични стойности, които се предават на приложението при стартиране за настрояване на поведението му без промяна на кода. Те позволяват разделяне на конфигурациите за разработка, тестване и производство. Според Twelve-Factor App, 2025, конфигурацията трябва да се съхранява в променливи на средата, а не в кода. Променливите на средата осигуряват безопасно управление на API ключове, URL на backend и флагове за функционалност.
Основно
Променливите на средата са двойка ключ-стойност, достъпна за процеса на приложението чрез API на операционната система. Те се предават на процеса при неговото създаване и съществуват само през времето на работа му. За разлика от вградените в изходния код параметри за конфигурация, променливите на средата не изискват прекомпилиране за промяна на стойностите. Това е фундаментален принцип на Twelve-Factor App, който осигурява ясно разделяне между код и конфигурация.
В мобилното разработване променливите на средата решават проблема с различни конфигурации за различни среди: разработчикът използва локален сървър, тестващият използва staging, потребителите използват производство. Вместо да съхранява три URL на backend в кода с условни оператори if-else, разработчикът предава един URL чрез променлива на средата на етапа на изграждане. Това опрощава кода и елиминира риска от неволно използване на производствения сървър в тестова среда.
Основното предимство е безопасността: чувствителните данни не попадат в репозиториума за код. API ключовете, Firebase тайните, токените за достъп до backend и сертификатите се зареждат чрез CI/CD директно в средата за изграждане. Ако нападател получи достъп до репозиториума за код, той няма да намери тайни там, тъй като те се съхраняват в защитените хранилища на CI системата и се предават само на етапа на изграждане на бинарния файл.
Мобилните проекти имат най-малко три среди: development, staging и производство. Всяка среда изисква свой набор от конфигурации: URL на сървъра, име на пакета, схема за подписване и сертификати за push известия. Без променливи на средата, разработчикът трябва ръчно да променя конфигурацията преди всяко изграждане, което води до грешки: забравен производствен ключ в тестово изграждане може да причини изпращане на известия на реални потребители или консумация на платен API.
Променливите на средата позволяват преключване на backend без промяна на кода: достатъчно е да замените стойността на променливата API_BASE_URL. Флаговете за функционалност (feature flags) се управляват чрез променливи като FEATURE_CHAT_ENABLED=true, което позволява включване на нови функции в staging без влияние върху производството. За всяка среда се създава собствен .env файл, който се зарежда на етапа на изграждане.
class AppConfig {
static final String apiBaseUrl =
const String.fromEnvironment('API_BASE_URL',
defaultValue: 'http://localhost:8080');
}
Твърдо кодираните ключове са често срещана уязвимост на мобилните приложения. Нападателят декомпилира APK или IPA с инструменти като jadx или Hopper и извлича тайните от бинарния файл. Дори обфускацията не защитава стринг литералите — те се откриват лесно в кода след декомпилация. Променливите на средата решават този проблем, като предават ключовете на етапа на изграждане чрез CI/CD, където те се маскират в логовете.
object Config {
val apiKey: String =
System.getenv("API_KEY") ?: throw
IllegalStateException("API_KEY not set")
}
Променливите на средата се интегрират с pipeline за изграждане: GitHub Actions, GitLab CI, Bitrise и CircleCI подкрепят тайни променливи, които не се показват в логовете. На етапа на изграждане, CI подставя съответните стойности в зависимост от клона или етикета: за клона develop се използва staging, за етикет v* се използва производство. Това автоматизира процеса и елиминира човешкия фактор, гарантирайки че всяко изграждане получава правилния набор от конфигурации.
Файлът .env е стандартният начин за съхраняване на променливи на средата в формат KEY=VALUE. Той не се включва в репозиториума, вместо това към репозиториума се добавя .env.example с шаблон на всички променливи и празни стойности. Всякак разработчик създава свой .env файл с локални настройки, без да засяга конфигурацията на другите членове на екипа. За различни среди се използват отделни файлове: .env.dev, .env.stage, .env.prod.
# .env.example — шаблон за разработчици
API_BASE_URL=http://localhost:8080
FEATURE_CHAT_ENABLED=true
SENTRY_DSN=
За мобилни проекти съществуват специализирани библиотеки за работа с .env файлове:
Настройките на клон в CI/CD позволяват подставяне на различни .env файлове: .env.dev за тестови сървъри, .env.stage за предиздаване и .env.prod за публикуване в магазините за приложения. Файловете с тайни се зареждат от безопасно хранилище (Vault, AWS Secrets Manager) и не се съхраняват в репозиториума. Това гарантира, че дори ако системата за контрол на версиите бъде компрометирана, тайните остават защитени.
iOS екосистемата използва xcconfig файлове за управление на променливи на ниво на изграждане. Те се свързват към Xcode схеми и позволяват презаписване на стойности за конфигурациите Debug и Release. xcconfig файловете подкрепят наследяване: може да се създаде базов файл с общи настройки и специфични файлове за всяка среда.
xcconfig файловете съхраняват променливи в формат KEY = VALUE и се свързват към схемата за изграждане в Xcode чрез настройките Configuration. Променливите от xcconfig са достъпни в Info.plist чрез синтаксис $(VARIABLE_NAME), което позволява използване на различни идентификатори на пакет и имена на приложението за различни схеми. За бързо идентифициране на средата, към името на приложението се добавя надставка Dev или Staging.
# Config/Dev.xcconfig — разработна конфигурация
API_BASE_URL = http://localhost:3000
BUNDLE_ID_SUFFIX = .dev
APP_DISPLAY_NAME = MyApp Dev
За достъп по време на изпълнение до променливи в iOS се използва файлът Configuration.swift, който чете стойности от Info.plist чрез Bundle.main.object(forInfoDictionaryKey:). Този подход гарантира, че променливите се определят на етапа на изграждане и са налични за приложението веднага след стартиране. Стойностите се четат веднъж при инициализирането на модула и се кешират за бърз достъп през жизнения цикъл на приложението.
enum AppEnvironment {
static var apiBaseURL: URL {
guard let urlString = Bundle.main
.object(forInfoDictionaryKey: "API_BASE_URL"),
let url = URL(string: urlString as! String)
else { fatalError("API_BASE_URL is not configured") }
return url
}
static var isChatEnabled: Bool {
Bundle.main.object(
forInfoDictionaryKey: "FEATURE_CHAT_ENABLED"
) as? Bool ?? false
}
}
Android подкрепя променливи на средата чрез BuildConfig — автоматично генериран клас, чиито полета се определят в build.gradle файла на модула. BuildConfig се създава на етапа на компилация за всяка flavor и тип изграждане отделно. Това позволява различни стойности за debug и release без използване на условни оператори в кода, което повишава производителността и сигурността.
BuildConfig полетата се задават чрез buildConfigField в defaultConfig или в конкретни buildTypes. За всяка среда се създава отделен buildType или productFlavor. Това осигурява строга изолация на конфигурациите: debug използва локален сървър, release използва производство. BuildConfig полетата са статично типизирани, което елиминира грешките при обръщане към тях в кода.
// build.gradle (Module: app)
android {
defaultConfig {
buildConfigField "String", "API_BASE_URL",
"\"http://localhost:8080\""
}
buildTypes {
debug {
buildConfigField "String", "API_BASE_URL",
"\"http://dev.api.itsectr.com\""
}
release {
buildConfigField "String", "API_BASE_URL",
"\"https://api.itsectr.com\""
}
}
}
Файлът gradle.properties в корена на проекта съхранява глобални Gradle променливи. Те са достъпни в всички модули чрез синтаксис $variableName и се използват за посочване на версии на зависимостите, флагове за изграждане и API ключове. За разлика от BuildConfig, gradle.properties работи само на етапа на конфигурация на Gradle, а не по време на изпълнение на приложението. Поради това паролите и API ключовете, посочени в gradle.properties, не са видими в декомпилирания код, тъй като се използват само за генериране на BuildConfig на етапа на компилация.
# gradle.properties
SENTRY_DSN=https://key@sentry.io/project
MAPS_API_KEY=AIzaSy...
За безопасно предаване на тайни в Android проекти се препоръчва използването на local.properties (изключен от VCS) или зареждане на стойности от CI/CD променливи в build.gradle чрез System.getenv(). Това гарантира, че ключовете няма да попаднат в репозиториума. При публикуване в Google Play Console, убедете се, че всички debug ключове са заменени с производствени версии чрез различни buildTypes или productFlavors с съответните BuildConfig стойности.
Често задавани въпроси
Да, Flutter подкрепя променливи на средата чрез пакета flutter_dotenv за достъп по време на изпълнение или чрез нативни канали за платформени променливи. В Dart също е наличен конструкторът String.fromEnvironment за предаване на стойности на етапа на компилация чрез --dart-define, което е препоръчителният начин за Flutter проекти.
BuildConfig е Java клас с типизирани полета, генериран на етапа на компилация за всяка buildType и flavor. gradle.properties е текстов файл с двойки ключ-стойност, достъпен за всички Gradle модули на етапа на конфигурация на изграждането. BuildConfig работи по време на изпълнение на приложението, gradle.properties — само в Gradle скриптовете.
Добавете .env в .gitignore файла на вашето репозиториум. Комитвайте само .env.example с празни стойности и описание на всяка променлива в репозиториума. За CI/CD използвайте криптирани тайни в настройките на GitHub Actions, GitLab CI или Bitrise, които се маскират в логовете и са нечетими след приключване на изграждането.
Повечето CI системи подкрепят тайни променливи на средата. В GitHub Actions те са Secrets, в GitLab CI — CI/CD Variables, в Bitrise — Secrets. На етапа на изграждане, те се предават на build скрипта чрез process.env или System.getenv(). Тайните променливи не се показват в логовете за изграждане и не са достъпни в форковете на репозиториума.
Feature flags са булеви променливи, които управляват включването или изключването на функционалност без прекомпилиране на кода. Пример: FEATURE_NEW_PAYMENT=true включва новата платежна система в staging за тестване. В производство същият флаг е настроен на false до пълното развъртване на backend. Това позволява безопасно поетапно внедряване на промяните и връщане при проблеми.
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.