Code block Pro 자꾸 에러나서 짜증나네. 어쩔 수 없이 새로운 포스트로 넘어옴.
Filter variants
flavor dimension을 사용하면 모든 조합을 사용하므로 build variant가 매우 많아질 수 있는데, 필요없는 것까지 생성될 수 가 있다. 이경우, beforeVariants { } 블럭을 이용하면 된다. 예제를 보자.
android {
...
buildTypes {...}
flavorDimensions += listOf("api", "mode")
productFlavors {
create("demo") {...}
create("full") {...}
create("minApi24") {...}
create("minApi23") {...}
create("minApi21") {...}
}
}
androidComponents {
beforeVariants { variantBuilder ->
// To check for a certain build type, use variantBuilder.buildType == "<buildType>"
if (variantBuilder.productFlavors.containsAll(listOf("api" to "minApi21", "mode" to "demo"))) {
// Gradle ignores any variants that satisfy the conditions above.
variantBuilder.enable = false
}
}
}
...
위와 같이 작성하면, “minApi21″에 “demo”버전은 build variant를 생성하지 않게된다.
Source set 만들기
기본적으로 안드로이드 스튜디오는 main/ 디렉토리의 source set을 생성한다. 이건 모든 build variants들이 공유하게 된다. 이 외에도, 개발자가 직접 build type, product flavor, 또는 flavor dimension을 이용한 조합등 build variant들에 대해 별도의 소스 셋을 생성할 수 있다.
별도의 source set을 생성하면, gradle은 main/ 과 마찬가지 형태의 디렉토리 구조를 가진다고 가정한다. 예를들어 debug를 만들면, src/debug/ 로 그 밑에 src/debug/kotlin, src/debug/java등으로 다룬다.
안드로이드 스튜디오의 Gradle 탭에서 MyApplication>Tasks>android>sourceSets Task를 실행하면 다음과 같은 화면을 build 탭에서 찾아 볼 수 있다. task가 안보인다면, 다음 설정을 활성화 해야 한다. File>Settings>Experimental 에서 Configure all Gradle tasks during Gradle Sync 이게 활성화되면, 빌드 스크립트 sync시마다 task도 재형성 되는걸로 보이고, sync 시간이 길어진다고 한다.
------------------------------------------------------------
Project :app
------------------------------------------------------------
...
debug
----
Compile configuration: debugCompile
build.gradle name: android.sourceSets.debug
Java sources: [app/src/debug/java]
Kotlin sources: [app/src/debug/kotlin, app/src/debug/java]
Manifest file: app/src/debug/AndroidManifest.xml
Android resources: [app/src/debug/res]
Assets: [app/src/debug/assets]
AIDL sources: [app/src/debug/aidl]
RenderScript sources: [app/src/debug/rs]
JNI sources: [app/src/debug/jni]
JNI libraries: [app/src/debug/jniLibs]
Java-style resources: [app/src/debug/resources]
안드로이드 스튜디오가 source set의 디렉토리를 자동으로 생성하지는 않는다. 대신, 생성을 좀 도와준다. 안드로이드 스튜디오의 project 패널에서 Project view인 상태로 Myproject/app/src 디렉토리에 우클릭>New>Directory 를 선택하면, 팝업메뉴를 보여주는데 여기에 gradle source set들이 리스트업된다. 여기서 debug/java, debug/kotlin등을 선택해주면 된다.
다른 방법으로 파일을 추가시, source set을 선택하여 디렉토리를 생성하는 방법도 있다. 예를들어 Project pane에서 src디렉토리에 우클릭> New > XML > Values XML File 로 xml파일을 추가하면, 추가화면에 Target Source Set 화면이 보인다. 여기서 원하는 source set을 선택하면 된다.
기본 Source set 위치설정 바꾸기
Source set의 디렉토리위치는 안드로이드 스튜디오에서 디폴트로 다루게 되지만, 다른 위치에 있는경우 사용자가 임의로 설정이 가능하다. “main” source set 에 대해 위치를 other/ 로 설정하고 싶다면, 다음과 같이 모듈레벨의 gradle 파일을 작성하여 할 수 있다.
android {
...
// Encapsulates configurations for the main source set.
sourceSets.getByName("main") {
// Changes the directory for Java sources. The default directory is
// 'src/main/java'.
java.setSrcDirs(listOf("other/java"))
// If you list multiple directories, Gradle uses all of them to collect
// sources. Because Gradle gives these directories equal priority, if
// you define the same resource in more than one directory, you receive an
// error when merging resources. The default directory is 'src/main/res'.
res.setSrcDirs(listOf("other/res1", "other/res2"))
// Note: Avoid specifying a directory that is a parent to one
// or more other directories you specify. For example, avoid the following:
// res.srcDirs = ['other/res1', 'other/res1/layouts', 'other/res1/strings']
// Specify either only the root 'other/res1' directory or only the
// nested 'other/res1/layouts' and 'other/res1/strings' directories.
// For each source set, you can specify only one Android manifest.
// By default, Android Studio creates a manifest for your main source
// set in the src/main/ directory.
manifest.srcFile("other/AndroidManifest.xml")
...
}
// Create additional blocks to configure other source sets.
sourceSets.getByName("androidTest") {
// If all the files for a source set are located under a single root
// directory, you can specify that directory using the setRoot property.
// When gathering sources for the source set, Gradle looks only in locations
// relative to the root directory you specify. For example, after applying the
// configuration below for the androidTest source set, Gradle looks for Java
// sources only in the src/tests/java/ directory.
setRoot("src/tests")
...
}
}
...
Source set 으로 빌드하기
product flavor 가 “demo” 이고, build type이 “debug”인 build variant “demoDebug”를 빌드하게 되면, Gradle은 다음 순서로 source set을 찾게 된다.
- src/demoDebug/ : build variant source set
- src/debug/ : build type source set
- src/demo/ : product flavor source set
- src/main/ : default main source set
만약, 여러개의 product flavor를 결합한다면, 기술된 flavor dimension들의 순서에 따라 우선순위를 갖게된다.
조금 혼란스러운 부분은 이 우선순위로 무조건 덮어쓰기가 되는게 아니라는 것 같다. kotlin/ java/ 아래의 소스들은 모두 한꺼번에 컴파일 되며, main/ 에 있는 것과 동일한 클래스명을 다른 곳, 예를들어 debug/ 에서 사용할 수 없다고 한다.(컴파일 에러) 아마도 코드는 덮어쓰는게 아니라 추가하는 개념인걸로 보임.
Manifest, values/, res/, asset/ 등은 merge가 되는데, 같은 이름의 리소스가 존재한다면 위의 우선순위가 높은 것이 선택되는 것으로 보인다.