Что такое BuildConfig и как его применять в проекте

BuildConfig — автоматически генерируемый класс Gradle в Android, который хранит константы сборки (версии, флаги debug, URL, ключи) и позволяет менять значения для debug/release/flavors без хардкода. Ниже — как задать поля, где их хранить и как безопасно использовать в коде.

Что содержит BuildConfig и зачем он нужен

BuildConfig генерируется при сборке и содержит:

  • BuildConfig.DEBUG — автоматически true для debug‑сборок.
  • Константы из build.gradle: buildConfigField("String", "API_URL", ""https://..."").
  • Версии, флаги, фич‑флаги и значения, зависящие от buildType или flavor.

Зачем использовать:

  • Типобезопасный доступ к конфигурации (компилятор проверяет типы).
  • Разные значения для debug/release/staging без условий в коде.
  • Простая интеграция с CI/CD (подстановка переменных окружения в Gradle).

Храните секреты вне репозитория (local.properties или gradle.properties) и подставляйте их в buildConfigField через properties — так вы снижаете риск утечки.

Как задать и сгенерировать BuildConfig

В Groovy DSL (build.gradle):

android {
  defaultConfig {
    applicationId "com.example.app"
    buildConfigField "String", "API_URL", "\"https://api.example.com\""
  }
  buildTypes {
    debug {
      buildConfigField "boolean", "ENABLE_LOGGING", "true"
    }
    release {
      buildConfigField "boolean", "ENABLE_LOGGING", "false"
      minifyEnabled true
    }
  }
}

В Kotlin DSL (build.gradle.kts):

android {
  defaultConfig {
    buildConfigField("String", "APP_VERSION", "\"${versionName}\"")
    buildConfigField("String", "API_KEY", "\"${properties["apiKey"] ?: ""}\"")
  }
  buildTypes {
    debug {
      buildConfigField("boolean", "ENABLE_LOGGING", "true")
    }
    release {
      buildConfigField("boolean", "ENABLE_LOGGING", "false")
    }
  }
}

После ./gradlew clean assemble класс появится в build/generated/source/buildConfig/... Импорт: import com.yourapp.BuildConfig

Никогда не коммитьте local.properties с реальными ключами. Добавьте его в .gitignore.

Практическое использование и рекомендации

Примеры в коде:

if (BuildConfig.DEBUG) {
  Log.d("Main", "Debug mode")
}
val client = Retrofit.Builder()
  .baseUrl(BuildConfig.API_URL)
  .build()

Советы:

  • Для библиотек помните: у library‑модуля свой BuildConfig с пакетным именем модуля.
  • Не храните длинные секректы в BuildConfig — значения включаются в APK и могут быть доступны при декомпиляции.
  • Используйте local.properties/gradle.properties для хранения ключей CI: gradle.properties может храниться в CI-секретах и подтягиваться на сборке.

Сравнение способов хранения конфигурации

СпособПлюсыМинусы
BuildConfigАвтогенерация, типобезопасно, удобно для флагов и URLЗначения попадают в APK (не для секретов)
local.properties / gradle.propertiesНе в репозитории при правильной настройкеНужно вручную синхронизировать между машинами
Product FlavorsПоддержка множества окруженийУвеличивает количество APK/вариантов
Remote Config (Firebase)Меняется без пересборкиЗависимость от сети, задержка обновления

Частые ошибки

  • BuildConfig not found: проверьте applicationId, выполните Build > Clean Project > Rebuild.
  • Хранение секретов в репозитории: не коммитить local.properties.
  • Неправильно экранированные строки в Kotlin DSL: используйте ""value"" или rawString и проверяйте сборку.
  • Ожидание runtime‑обновлений: BuildConfig — значение фиксируется в момент сборки.

FAQ

  • Нужно ли использовать BuildConfig для API‑ключей?

    • Только если ключ не секретный. Для секретов используйте защищённые хранилища/серверные прокси или загружайте в runtime с защищённого бэкенда.
  • Как получать разные значения для staging и production?

    • Создайте productFlavors или отдельные buildTypes и задайте buildConfigField для каждого варианта.
  • BuildConfig в модуле A доступен в модуле B?

    • Нет: каждый модуль генерирует свой BuildConfig. Для общей конфигурации используйте общую библиотеку или ресурсно‑ориентированное решение.

Если нужно — могу привести готовые фрагменты для вашего build.gradle(.kts) с CI-подстановкой переменных.