본문 바로가기
프로그래밍 놀이터/안드로이드, Java

[android] Gradle Tutorial #2

by 돼지왕 왕돼지 2018. 10. 5.
반응형


AAR, ABI, android archive, android libraries, android library output, android library project, androidtestcompile, applicationvariants, apply plugin, ARTIFACT, buid type + product flavor, build customization, build type, build type config, build variant, build.gradle, buildconfig.java, buildtypeCompile, CHECK, classes task, com.android.library, compile classpath, compile configuration, compileoptions, compilesdkversion, debugcompile, defaultpublishconfig, dependency, disable, domainobjectcollection, Enable, external library.jar, flavor build type, flavor config, flavordimensions, getdefaultproguardfile, gradle, gradle tutorial, gradle 기초, Ivy, ivy repo, jar output, java project, javaversion, jcenter, language level, libraryvariants, lintoptions, Main, manifest merge, maven, maven repo, minifyenabled, module, multi project, multi-project setup, product flavor, product flavor source set, productflavors, proguard-android-optimize.txt, proguard-android.txt, proguardfile, project.tasks.classes, publishnondefault, r class, releasecompile, repositories, res shrink, resource overlay, settings.gradle, single manifest, sourcecompatibility, targetcompatibility, testvariants, transitive, variant.ignore, variantfilter, Version, version_1_6, [android] Gradle Tutorial #2, 특정 variant lint


Dependency, Android Libraries and Multi-project setup


-

external library jar 를 사용하려면 compile configuration 을 사용하면 된다.


dependencies {

    compile fileTree(dir: 'libs', include: ['*.jar']) // api 와 implementation 으로 바뀌었다.

}



android {

    ...

}



-

compile 은 main app 을 compile 한다.

compile 되는 모든 것은 compile classpath 로 잡히고, final APK 에 포함이 된다.


다음과 같은 compile configuration 을 추가할 수 있고,

buildType 을 추가하면 자동으로 compile 이 추가된다.

androidTestCompile

debugCompile

releaseCompile

// <buildtype>Compile



-

Gradle 은 Maven 과 Ivy repository 에서 artifact 를 끌어올 수 있다.

repository 를 명시하고, dependency 에 artifact 를 정의해주면 된다.

repositories {

     jcenter()

}


dependencies {

    compile 'com.google.guava:guava:18.0’ // gradle 은 transitive 하기에, lib 에서 다른 lib 참조하면 모두 긁어온다.

}


android {

    ...

}



-

다른 gradle project 에 의존하여 multi-project setup 이 가능하다.

root project 의 sub folder 로 만들어 진행 가능하다. 

MyProject/

 + app/

 + libraries/

    + lib1/

    + lib2/


위에는 3개의 project 가 있다.

각각의 project 는 각각의 build.gradle 을 가져야 한다.

multi project 의 경우 settings.gradle 을 root 에 위치시키고, project 들을 명시해주어야 한다.

include ':app', ':libraries:lib1', ':libraries:lib2'


:app project 가 lib1 에 의존한다면 dependency 에 추가해주어야 한다. (local 참조)

dependencies {

     compile project(':libraries:lib1')

}



-

Java Project 의 경우 위와 같은 설정을 하면 jar output 을 잘 이용한다.

그러나 android 와 관련된 library 의 경우에는 android library project 로 만들어주어야 한다.

project 의 build.gradle 에 아래 plugin 을 적용해주면 된다.

apply plugin: 'com.android.library'


library project 의 output 은 jar 가 아닌 aar 이다. ( Android Archive 의 약자 )

이는 code 와 resource 를 모두 조합한 녀석이다.



-

기본적으로 library 는 release build 만 제공한다.

아래와 같이 다른 형태의 variant 를 제공할 수 있다.

( 필요가 참여한 프로젝트들은 buildTypes 를 library build.gradle 에도 적용 가능했다. 아마 버전업 하면서 통일성을 갖추었나보다. )

android {

    defaultPublishConfig "debug"

}


android {

    defaultPublishConfig “flavor1Debug” // flavor 를 사용하는 경우

}



-

Library 는 default 외에는 기본으로 variant 가 enable 되어 있지 않아 아래와 같이 써주어야 한다.

android {

    publishNonDefault true

}



-

다음과 같이 조건에 따라 dependency 를 걸 수 있다.

dependencies {

    flavor1Compile project(path: ':lib1', configuration: 'flavor1Release')

    flavor2Compile project(path: ':lib1', configuration: 'flavor2Release')

}



-

testing 부분은 생략…



-

특정 variant 에 lint 를 돌릴 수 있다.

android {

    lintOptions {

        // turn off checking the given issue id's

        disable 'TypographyFractions','TypographyQuotes'


        // turn on the given issue id's

        enable 'RtlHardcoded','RtlCompat', 'RtlEnabled'


        // check *only* the given issue id's

        check 'NewApi', 'InlinedApi'

    }

}






Build Variant


-

한 app 에 대해 다른 버전들을 만드는 것이 build system 의 목적 중 하나.

예를 들면 한 소스로..

    free/demo/pro version 제작

    다른 형태로 package 되어 multi-apk 로 만든다.

    둘의 조합



-

product flavor 는 customized 된 build 를 말한다.

한 project 는 여러개의 flavor 를 가질 수 있다.

android {

    ...


    defaultConfig {

        minSdkVersion 8

        versionCode 10

    }


    productFlavors {

        flavor1 { // android.defaultConfig object 이다.

            applicationId "com.example.flavor1"

            versionCode 20

         }


         flavor2 {

             applicationId "com.example.flavor2"

             minSdkVersion 14

         }

    }

}


flavor 이름은 build type 과 conflict 나면 안 된다.

물론 androidTest 나 test 등의 이름이 되어서는 안된다.



-

Build Type + Product Flavor 가 Build Variant 이다.

Flavor 가 없는 경우에는 Build Type 이 홀로 Build Variant 가 된다.



-

Build Type configuration 은 다른 config 의 overlay 가 된다.

즉 Build Type Config > Flavor Config



-

Build Type 과 마찬가지로 Product Flavor 도 기본 sourceSet 을 만든다.

android.sourceSets.flavor1

    Location src/flavor1/

android.sourceSets.flavor2

    Location src/flavor2/


이는 Build Type 의 sourceSet 과 결합하여 하나의 APK 를 만드는 데 사용된다.

    모든 source code ( src/*/java ) 가 single output 을 만드는 데 사용된다.

    Manifest 가 single manifest 로 merge 한다.

    모든 resource 는 overlay 된다. Build Type > Product Flavor > main 순의 우선순위를 갖는다.

    각각의 Build Variant 는 각각의 R class 를 갖는다. variant 간 share 되지 않는다.



-

Flavor 역시 compile 옵션이 될 수 있다.

dependencies {

    flavor1Compile "..."

}



-

BuildType 과 Flavor 가 결합된 형태도 compile 옵션이 될 수 있고, 이에 대한 SourceSet 도 가질 수 있다.

android.sourceSets.flavor1Debug

    Location src/flavor1Debug/

android.sourceSets.flavor1Release

    Location src/flavor1Release/



-

다음과 같이 flavorDimension 을 정의하면 flavor 간의 hierarchy 를 만드는 것도 가능하다.

android {

    ...


    flavorDimensions "abi", “version” // 순서가 hierarchy 를 갖는다!!!


    productFlavors {

        freeapp {

            dimension "version"

            ...

        }


        paidapp {

            dimension "version"

            ...

        }


        arm {

            dimension "abi"

            ...

        }


        mips {

            dimension "abi"

            ...

        }


        x86 {

            dimension "abi"

            ...

        }

    }

}


위와 같이 정의하면 아래와 같은 variant 가 나온다.


x86-freeapp-debug

x86-freeapp-release

arm-freeapp-debug

arm-freeapp-release

mips-freeapp-debug

mips-freeapp-release

x86-paidapp-debug

x86-paidapp-release

arm-paidapp-debug

arm-paidapp-release

mips-paidapp-debug

mips-paidapp-release


flavorDimentsions array 에서 version 이 먼저 define 되었기 때문에 abi-version-buildType 의 순으로 생기는 것이다.



-

compile time 에 Android Studio 는 상수들을 담고 있는 BuildConfig 라는 것을 자동 생성한다.

이 상수들을 이용해 무언가를 할 수 있다.

private void javaCode() {

    if (BuildConfig.FLAVOR.equals("paidapp")) {

        doIt();

    } else {

        showOnlyInPaidAppDialog();

    }

}



-

BuildConfig 가 담을 수 있는 녀석들은..

boolean DEBUG

int VERSION_CODE

String VERSION_NAME

String APPLICATION_ID

String BUILD_TYPE // release

String FLAVOR // paidapp


만약 flavor dimension 을 이용한다면 다음것들이 추가로 생성된다.

String FLAVOR // “armFreeapp”

String FLAVOR_abi //  “arm”

String FLAVOR_version // “freeapp"



-

dimension 과 flavor 를 사용하다보면, 사용하고 싶지 않은 variant 값들이 있을 수 있다. ( 자동조합되므로 )

이는 variantFilter 로 제거할 수 있다.

android {

    productFlavors {

        realData

        fakeData

    }


    variantFilter { variant ->

        def names = variant.flavors*.name


        if (names.contains("fakeData") && variant.buildType.name == "release") {

            variant.ignore = true

        }

    }

}


위와 같이 하면 다음의 3개만 생성된다.

realDataDebug

realDataRelease

fakeDataDebug

// fakeDataRelease 가 생성되지 않는다.




Advanced Build Customization


-

proguard 를 돌리기 위해서는 아래와 같이 minifyEnabled 와 proguardFile property 를 이용하면 된다.

android {

    buildTypes {

        release {

            minifyEnabled true

            proguardFile getDefaultProguardFile('proguard-android.txt')

        }

    }


    productFlavors {

        flavor1 {

        }

        flavor2 {

            proguardFile 'some-other-rules.txt'

        }

    }

}



proguard 에는 2가지 rule file 이 있다.

    proguard-android.txt

    proguard-android-optimize.txt


getDefaultProguardFile() 은 파일들의 full path 를 가져온다.



-

사용하지 않는 res shrink 도 가능하다.



-

기본 java project 는 output 을 만들기 위한 task 들이 있다.

그 중 하나인 classes task 는 java source code 를 compile 하는 데 쓰인다.

build.gradle 에서는 project.tasks.classes 를 이용해 쉽게 접근 가능하다.



-

Android 의 경우 task 의 갯수가 훨씬 많고, Build Type 과 Product Flavor 에 이름이 depdent 하기 때문에 복잡하다.

그래서 android 는 다음을 제공한다.

applicationVariants (only for the app plugin)

libraryVariants (only for the library plugin)

testVariants (for both plugins)


이 녀석들은 DomainObjectCollection 을 retrun 한다.

이 녀석이 갖는 property table 은 최상단의 link 참조..



-

compileOptions 를 이용해 language level 도 설정 할 수 있다.

기본값은 compileSdkVersion 에 의해 선택된다.

android {

    compileOptions {

        sourceCompatibility JavaVersion.VERSION_1_6

        targetCompatibility JavaVersion.VERSION_1_6

    }

}





반응형

댓글