이번에는 Gradle 빌드 변형 구성에 대해 알아보겠습니다.
먼저, 현재 빌드정보를 담고있는 buildConfig
에 필드를 추가하는 방법 필드의 정보들을 불러오는 방법을 알아보겠습니다.
그리고 BuildType
, ProductFlavors
마다 BuildConfig을 변형 구성하는 방법과 Source Set을 바꿔서 구성하는 방법을 알아보겠습니다.
BuildType이란?
buildType
은 일반적으로 개발자가 새 모듈을 생성하면 debug와 release 두 가지를 생성합니다.
debug
는 빌드 유형을 선언하지 않더라도 Android Studio에서는 debuggable true를 default값으로 구성하며 이 속성 덕분에 Android 기기에서 앱을 디버깅할 수 있습니다.
release
는 출시용 buildType으로 일반적으로 proguard를 사용하여 난독화 및 앱 축소를 진행합니다.
또한, 새로운 buildType을 만들고 기존의 buildType의 값들로 초기화 하려면 initWith 속성을 사용하면 됩니다.
android {
// ...
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
applicationIdSuffix ".debug"
debuggable true
}
staging {
initWith debug
applicationIdSuffix ".debugStaging"
}
}
}
BuildConfig이란?
buildConfig
에는 현재 빌드에 대한 정보들이 들어있고 이 정보들을 통해서 코드에서도 현재 빌드에 대한 정보들을 읽어올 수 있습니다.
대부분의 정보들은 app레벨의 build.gradle의 defaultConfig
에 설정한 값으로 가져옵니다.
하지만, defaultConfig은 모든 빌드 구성에서 가져오는 기본값일 뿐, BuildConfig은 BuildType과 ProductFlavor를 변경할 경우 다르게 구성됩니다.
BuildConfig은 아래와 같이 구성됩니다.
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "com.seosh817.androidconfigs.stage.debug";
public static final String BUILD_TYPE = "debug";
public static final String FLAVOR = "stage";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "1.0-stage";
}
DEBUG
-> 현재 BuildType이 Debug인지 Release인지 Boolean값으로 return합니다.
APPLICATION_ID
-> 일반적으로 현재 빌드구성의 {applicationId}.{productFlavor}.{buildType}으로 구성됩니다.
BUILD_TYPE
-> 현재 빌드의 BuildType을 return 합니다
FLAVOR
-> 현재 빌드의 ProductFlavor를 return 합니다.
VERSION_CODE
-> 현재 빌드의 버전코드를 return 합니다.
VERSION_NAME
-> 현재 빌드의 버전네임을 reutrn 합니다.
build.gradle
android {
// ...
defaultConfig {
applicationId "com.seosh817.androidconfigs"
minSdk 23
targetSdk 31
versionCode 1
versionName "1.0"
}
// ...
}
buildConfigField로 BuildConfig에 필드 추가하기
buildConfigField
를 통해 BuildConfig에 필드를 추가할 수 있고 Type, Name, Value 순서로 입력해주면 됩니다.
build.gradle에 buildConfigField를 추가하고 빌드를 돌려주면 BuildConfig에 필드가 추가됩니다.
build.gradle
android {
// ...
defaultConfig {
buildConfigField "String", "BASE_URL", "\"https://url.com/\""
}
// ...
}
public final class BuildConfig {
// ...
// Field from default config.
public static final String BASE_URL = "https://url.com/";
}
이렇게 생성된 필드들은 모두 static으로 선언되므로 BuildConfig.name을 통해 값들을 읽어올 수 있습니다.
Log.i(TAG, "BASE_URL: ${BuildConfig.BASE_URL}")
resValue로 res > values 디렉토리의 gradleResValues.xml에 값 추가하기
resValue
를 통해 gradleResValues.xml에 값을 추가할 수 있습니다.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Automatically generated file. DO NOT MODIFY -->
<!-- Value from default config. -->
<string name="base_url" translatable="false">BASE_URL</string>
</resources>
이렇게 생성된 값들은 R.string.name을 통해 값을 읽어올 수 있습니다.
Log.i(TAG, "base_url: ${R.string.base_url}")
mainfestPlaceholders를 이용해서 manifest에서 빌드정보 가져오기
mainfestPlaceholders
에 넣어주면 AndroidManifest에서도 빌드정보를 읽을 수 있습니다.
build.gradle
android {
defaultConfig {
// ...
manifestPlaceholders = ["baseUrl": "https://url.com/"]
}
// ...
}
AndroidManifest.xml
<intent-filter ... >
<data android:scheme="https" android:host="${baseUrl}" ... />
...
</intent-filter>
그 외에도 현재 빌드의 BuildConfig의 applicationId도 가져올 수 있습니다.
<intent-filter ... >
<action android:name="${applicationId}.TRANSMOGRIFY" />
...
</intent-filter>
// product flavor dev
<intent-filter ... >
<action android:name="com.seosh817.androidconfings.dev.debug.TRANSMOGRIFY" />
...
</intent-filter>
gradle.properties와 local.properties에서 정보읽기
기본적으로 앱 코드상으로 노출시키지 않고 싶은 정보들은 gradle.properties
혹은 local.properties
에 저장합니다.
gradle.properties와 local.properties에서 정보를 가져오도록 하겠습니다.
local.properties에서 프로퍼티 가져오기
local.properties
에서 프로퍼티는 Properties를 통해서 읽을 수 있습니다.
Properties
는 HashTable을 상속하며 Properties.load()를 통해서 Inputstream을 라인별로 읽어서 HashTable에 값을 넣어주므로 객체를 통해 프로퍼티들을 가져올 수 있게 해줍니다.
def getLocalProperty(String propName) {
def propsFile = rootProject.file("local.properties")
if (propsFile.exists()) {
def props = new Properties()
props.load(new FileInputStream(propsFile))
if (props[propName] != null) {
return props[propName]
} else {
print("no such property" + propName)
}
}
}
android {
// ...
defaultConfig {
// ...
buildConfigField "String", "BASE_URL", "\"${getLocalProperty("BASE_URL")}\""
}
}
gradle.properties에서 프로퍼티 가져오기
gradle.properties
에서 프로퍼티는 project.properties를 통해 가져올 수 있습니다.
android {
// ...
defaultConfig {
// ...
buildConfigField "String", "BASE_URL", "\"${project.property("BASE_URL")}\""
}
// ...
}
ProductFlavors란?
productFlavors
를 이용하면 동일한 프로젝트에서 여러 버전의 다른 앱을 만들 수 있습니다.
android {
// Specifies one flavor dimension.
flavorDimensions "version"
productFlavors {
dev {
dimension "version"
applicationIdSuffix ".dev"
versionNameSuffix "-dev"
}
stage {
dimension "version"
applicationIdSuffix ".stage"
versionNameSuffix "-stage"
}
live {
dimension "version"
applicationIdSuffix ".live"
versionNameSuffix "-live"
}
}
}
dev, stage, live 총 3가지의 productFlavor를 만들어주었습니다.
applicationIdSuffix를 추가해주면 applicationId에 suffix가 추가됩니다.
dev로 예를들면 .dev가 추가되어 applicationId는 com.seosh817.androidconfigs.dev.debug가 되어서 applicationId가 서로 다른 앱이 만들어지게 됩니다.
versionNameSuffix도 마찬가지로 versionName에 suffix가 추가되어 1.0.0-dev와 같이 선언됩니다.
위처럼 3가지 flavor를 추가하면 buildType x productFlavors로 총 6가지 Build Varaints가 구성됩니다.
devDebug
devRelease
stageDebug
stageRelease
liveDebug
liveRelease
productFlavors에 BuildConfigField 추가하기
productFlavor
에도 값을 buildConfigField, manifestholders, resValue 모두 사용할 수 있습니다.
android {
productFlavors {
dev {
// 개발용
// ...
buildConfigField "String", "BASE_URL", "\"https://url.dev.com/\""
manifestPlaceholders = [ appLabel: "DevApp"]
resValue("string", "base_url", "BASE_URL")
}
stage {
// 사내 테스트용
// ...
buildConfigField "String", "BASE_URL", "\"https://url.stg.com/\""
manifestPlaceholders = [ appLabel: "StageApp"]
}
live {
// 실제 배포용
// ...
buildConfigField "String", "BASE_URL", "\"https://url.com/\""
manifestPlaceholders = [ appLabel: "LiveApp"]
}
}
}
Build Variant를 바꾸어 빌드해주면 BuildConfig 또한 현재 빌드에 맞춰서 바뀝니다.
public final class BuildConfig {
// ...
// Field from product flavor: dev
public static final String BASE_URL = "https://url.dev.com/";
}
applicationVariants
를 통해 Build Variant들을 가져와서 BuildConfigField를 수정할 수도 있습니다.
android {
// ...
applicationVariants.all { variant ->
def BASE_URL = ""
if (variant.getName().contains("dev")) {
BASE_URL = "https://url.dev.com/"
} else if (variant.getName().contains("stage")) {
BASE_URL = "https://url.stg.com/"
} else if (variant.getName().contains("live")) {
BASE_URL = "https://url.com/"
}
variant.buildConfigField "String", "BASE_URL", "\"${BASE_URL}\""
}
}
소스 세트 추가
Source Set
를 이용하면 Build Variants의 변경에 따라 코드와 resource를 다르게 설정할 수 있습니다.
기본적으로 안드로이드 스튜디오는 모든 Build Variants 간에 공유하는 main / source set를 생성합니다.
이렇게 공용으로 사용되는 source set 말고, 특정 BuildType, plroudctFlavor를 사용하는 BuildVariant에 사용하는 source set를 생성할 수 있습니다. 예를들면, 앱에서 기본적으로 사용하는 부분은 main / source set에 넣고 특정 flavor에서 다르게 사용하고 싶을 때 사용하면 됩니다.
예를들어, stage productFlavor에 kotlin 디렉토리를 만들고 싶다면 아래와 같이 진행하면 됩니다.
- Project 탭으로 바꿉니다.
- app/src로 마우스커서를 이동합니다.
- 오른쪽 클릭 후 New -> Directory를 선택합니다.
- Gradle SourceSets 메뉴 중 stage/kotlin을 선택해서 생성해줍니다.
감사합니다!