- 들어가기 앞서.

 안드로이드 앱을 개발하다보면, 다양한 외부라이브러리를 참조해야할 경우가 발생합니다. 이를 프로젝트에서의 dependency(의존성) 이라고 합니다. 과거 이클립스의 경우에는 라이브러리 파일을 다운로드하여 프로젝트의 libs 폴더에 복사하고 다시지정하는 과정이 매우 번거로웠습니다. 하지만 gradle 에서는 이런 문제점을 해결하였습니다. 그만큼 gradle은 이전에 문제가 되었던 많은 부분들을 보완한것을 알 수 있습니다.



- 가장 기본적 Gradle 외부라이브러리 참조 방법

 app module의 dependencies 블록에 ㅂ외부 라이브러리를 지정합니다. 외부 라이브러리를 지정할때 compile 명령을 사용합니다. 

http://fsd-jinss.tistory.com/36 앞서 생성했던 안드로이드 그래들 프로젝트에서의 app module gradle dependencies 부분을 살펴 보시겠습니다.

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar']) //1
testCompile 'junit:junit:4.12'                                     //2
compile 'com.android.support:appcompat-v7:26.0.0-alpha1'            //3
}


1. libs폴더의 JAR파일을 추가하는 방법입니다.

2. 테스트 빌드시 참조하는 라이브러리 입니다.

3. 로컬에 없는, 외부라이브러리를 참조합니다. Gradle 에서 외부 라이브러리를 참조하기 위해서는 다음 세가지 정보가 필요합니다.


- group Id : 라이브러리 패키지 이름이 필요합니다. (com.android.support)

- arifact id : 라이브러리 이름이 필요합니다. (appcompat)

- version   : 참조하는 버전명이 필요합니다. (v7:26.0.0-alpha1)




다른 모듈 소스코드 참조하기


아래는 라이브러리 모듈(library module, app module 말고요)의 소스코드 참조하는 방법입니다.

dependencies {

  compile project(':mylibrary')

}


다음은 하위폴더에 위치한 라이브러리 모듈의 소스코드를 참조하는 방법입니다.

lib_modules 폴더 하위에 mylibrary가 위치한다면 다음과 같이 기술합니다.

dependencies {

  compile project(':lib_modules:mylibrary')

}


디버그 모드와 릴리즈 모드 참조하기

 dependencies {

 debugCompile 'com.abcd.test:myTest-android:1.3'

 releaseCompile 'com.abcd.test:myTest_release-android:1.3'

}

디버그 컴파일과 릴리즈 컴파일로 구분합니다.



안드로이드 유닛 테스트 참조하기

dependencies {
androidTestCompile 'junit:junit:4.12'
}

참고로 androidTestCompile은 안드로이드 UI 테스팅할때 사용하는 명령어로, testCompile과 구별됩니다.



공개라이브러리 참조하기 - JAR 파일

HTTP 클라이언트와 웹소켓 클라이언트를 지원하는 AndroidSync 참조 예입니다. github에 Gradle에서 간편하게 추가하는 방식을 소개하고있습니다.

 dependencies{

 compile 'com.koushikdutta.async:androidasync:2.+'

}



공개라이브러리 참조하기 - AAR 파일

AAR파일을 참조해야하는 경우가 있습니다.  @aar을 끝에 붙여주면 됩니다.


dependencies{

  complie 'com.abcd:andrid-xxx:1.0.1@aar'

}



로컬에 있는 AAR파일 참조하기

로컬에 AAR을 복사하여 참조하는 경우도 있을 수 있습니다. 이럴때는 libs 폴더에 복사후 gradle을 통해 참조할 수 있습니다. 

이때 module build.gradle 파일의 dependencies 블록만 변경해서는 안되고, repositories 블록도 함께 변경해야 합니다.

repositories{
flatDirs{
dirs 'libs'
}
}


다음 예는 mylibrary 모듈의 패지 이름과 aar파일 예시이름 버전 1.0으로 로컬에 있는 경우 예입니다. 

dependencies{

  compile 'com.example.mylibray:myTest:1.0@aar'

}

.



.so(JNI)파일 참조하기

so 파일을 참조해야하는 경우도 있습니다. libs폴더 하위에 x86, armeabi-v7a 등 폴더를 만들고 그에맞는 .so파일을 복사하면 됩니다. (JNI 참고하세요)

아래와 같이 작성하시면 되겠습니다.

sourceSets는 안드로이드 앱을 gradle로 빌드하기 위해 사전에 약속된 폴더 구조입니다. 메인소스의 jniLibs.srcDirs 항목을 libs로 지정합니다.


android {

 sourceSets{

    main{

     jniLibs.srcDirs = ['libs']

    }

  }


}


그 외의 경우.

Gradle은 외부라이브러리르 가져올때, 그라이브러리가 내부적으로 참조하는 다른라이브러리도 함께 땡겨옵니다. 이럴 때exclude group 으로 특정 참조그룹을 제외시킬 수 도 있습니다. 현재 프로젝트와 의도지않게 가져오는 라이브러리의 버전 충돌문제로 사용하는 편입니다.


compile('xxx.xxx.xx:2.2.2'){

 exclude group: 'com.xxx'

}


transitive 옵션을 줄 수 있습니다. aar을 붙여 참조하게되면 transitive 옵션은 false 로 변경됩니다. (aar의 경우 그런것 같습니다.)

명시적으로 true값을 준다면, aar 파일이 필요로 하는 라이브러리를 추가로 땡겨 오게 됩니다.


compile('xxx.xxx.xx:2.2.2'){

transitive = true or false

}



'개발 Support > Gradle' 카테고리의 다른 글

안드로이드 Gradle Test  (0) 2017.07.12
안드로이드 Gradle 멀티 프로젝트 사용  (0) 2017.07.10
Gradle Task와 생명주기  (0) 2017.07.10
Android studio Gradle 프로젝트 생성  (0) 2017.07.09
Gradle 개요  (0) 2017.07.08

시작하기 앞서

 Gradle의 기본단위는 Task 입니다. Android Studio는 쉽게 빌드하는 것처럼보이지만, 내부적으로 모두 Gradle Task가 동작합니다. Gradle Task와 Task의 생명주기에 관해 알아보도록 하겠습니다.


프로젝트 빌드하고 실행

 안드로이드 스튜디오에서 기본적으로 빌드하려면 build -> make project 하면 됩니다. 

안드로이드 스튜디오 오른쪽화면을 보면 Gradle Projects가 있습니다. Sync버튼을 누르면 Gradle 관점에서 모듈별 Task목록들을 보실 수 있습니다.

저는 GradeTest라는 프로젝트를 생성했었습니다. 생성할때 처음 기본 모듈이름은 app이라고 안드로이드 스튜디오에서 기본적으로 설정됩니다.

모듈은 콜론으로 구분합니다. 그래서 :app으로 되어있는것을 보실 수 있습니다. 


app 모듈의 build그룹을 열어서, assembleDebug를 더블클릭하여 실행해봅시다. 

앞으로는 프로젝트를 직접 빌드하기보다는 Module 단위로 빌드를 진행합니다. 멀티프로젝트에서는 각 Module이 빌드의 주체가 됩니다.

빌드가 성공된것읗 확인할 수 있습니다.

또한, Project이름 > app > build > outputs > apk 폴더에 빌드된 apk 파일을 확인하실 수 있습니다.

 

 




Gradle Task 개념

 Module의 개수가 늘어나면 안드로이드 Gradle 플러그인에서 제공하는 Task 외 새로운 Task 를 추가하여 활용하게 됩니다. Task의 개념을 알고있으면 유용하게 써먹을 수 있게 됩니다.


Task 에서 Log 출력

 sayHi라는 Task를 추가해보겠습니다. 또한 Hello MyGradle 문구를 출력하는 Task를 만들도록하겠습니다. 문자열 출력할때는  ''를 사용해도되고 ""를 사용해도됩니다. "" 같은경우는 내부변수를 문자열에서 참조할때 사용하기도 합니다.



안드로이드 스튜디오 프로젝트에서, app module(프로젝트 모듈말고!)의 build.gradle을 열고 task를 추가해봅시다.


task sayHi << {

   println 'hello MyGradle'

}


그리고 오른쪽 gradle project창에서 싱크버튼을 누릅니다. Other 그룹을 펼쳐보면 sayHi Task가 생성된것을 확인할 수 있습니다. 거기서 더블클릭하면 sayHi Task 가 실행됩니다. 아래와 같이 app:sayHi task가 실행되면서, hello MyGradle이 출력되는것을 확인할 수 있습니다.


참고로 위에서 작성한코드는 아래코드와 같은 코드입니다. doLast부분이 들어가는것을 주의깊게 보세요. 뒤에서 설명합니다.

task hello {
    doLast {
        println 'Hello world!'
    }
}



Task 그룹 지정

Gradle Task는 그룹을 가질 수 있습니다. 앞서만들었던 sayHi를 help 그룹에 편입시켜 보겠습니다.

task sayHi(group: "help")<< {
println 'hello MyGradle'
}

sayHi는 help그룹에 어울리않으니 다른 그룹을 생성해서 지정해보겠습니다. insa 그룹을 생성하고 지정했습니다.

def insa = 'insa'
task sayHi(group: insa)<< {
println 'hello MyGradle'
}


sayHi Task가 insa 그룹에 편입된것을 확인하실 수 있습니다.


Task 설명 지정하기

Task가 어떤일을 하는 지 설명을 해야할 필요가 있겠죠? description을 넣고 설명을 달았습니다.

def insa = 'insa'
task sayHi(group: insa, description: "my insa is hello")<< {
println 'hello MyGradle'
}

Gradle 내장태스크 tasks를 실행하면 다음과 같이 설명글을 볼 수 있습니다.

insa 그룹의 tasks들이 출력되고, sayHi Task의 설명을 확인하실 수 있습니다.


Insa tasks

----------

sayHi - my insa is hello

.



Task에 dependency 지정하기

 어떤 task를 내 task 보다 먼저 실행되도록하려면 dependsOn 이라는 속성을 지정하면 됩니다.

meetPerson Task를 먼저 실행하고 sayHi Task를 진행하도록 하겠습니다.

def insa = 'insa'
task sayHi(group: insa, description: "my insa is hello",
dependsOn: 'meetPerson')<< {
println 'hello MyGradle'
}

task meetPerson(group: insa) << {
println "I met person"
}

동기화를 해보고 sayHi를 실행해보겠습니다.

meetPerson Task 실행되고, sayHi Task가 실행되는것을 확인하실 수 있습니다.



Gradle 생명주기

Gradle 생명주기는 초기화 단계, 설정 단계, 실행 단계로 구분됩니다.



초기화단계

 프로젝트 build.gradle에 해당하는 Project Instance를 생성합니다. 앞서 봤던 buildscript, allprojects 블록등도 포함됩니다.



설정단계

 Project객체의 detail한 값을 설정합니다. 하위 프로젝트에 공통으로 적용되는 내용은 앞선 포스팅에서 설명했던 allprojects() 을 통해 전달됩니다. 사용자 정의 task의 경우 doFirst()에 넣은 내용이 이때 실행됩니다.



실행단계

설정 단계를 마치고, 각 Task는 이제 실행되기만 하면됩니다. 사용자 정의 Task 의 경우 doLast() 또는 <<에 넣은 내용이 이때 실행되게 됩니다. 


만약 sayHi task에서 doFirst()와 doLast()를 각각 새로 정의했다면 doFirst()에 넣은 내용은 설정단계에서, doLast()에 넣은 내용은 실행단계에서 실행됩니다.

def insa = 'insa'
task sayHi(group: insa) {
doFirst{
println 'Look at me'
}
doLast{
println 'hello MyGradle'
}

}


:app:sayHi

Look at me

hello MyGradle


BUILD SUCCESSFUL



Look at me가 실행되고 Hello MyGradle이 출력되는것을 확인하실 수 있습니다.
참고로 위의 코드에 dependsOn: 'meetPerson' 을 넣으면, 

meetPerson Task가 실행되고, Look at me 다음 hellot MyGradle이 실행됩니다. 






시작하기 앞서

드디어 첫 gradle 프로젝트 생성 실습입니다. 차근차근 진행 해봅시다.


- Hello World 안드로이드 스튜디오 프로젝트 생성

안드로이드 스튜디오를 실행합니다. 그리고 File -> new -> New Project를 누릅니다. 음 API24 정도로 선택합니다. Activity 는 Blank Activity로 선택하겠습니다. 저흰 액티비티가 중요한게 아니니깐요.

 그리고 프로젝트 표시는 Android View로 하도록 하겠습니다. 왜냐하면 안드로이드 앱의 Gradle 스크립트를 잘표현해주기 때문입니다.



- Gradle 구성요소 소개

 

(1) app모듈

 안드로이드 스튜디오는 멀티프로젝트를 생성하게 됩니다. Gradle 프로젝트 하위에는 적어도 1개 이상의 모듈을 포합합니다. 최초 생성되는 모듈 이름은 app입니다. 새로운 모듈을 추가할때는 File -> New -> New Module 을 선택하면됩니다.


(2) manifest 폴더

AndroidManifest.xml 파일을 표시합니다. 앱이름과 권한 과 같은 프로젝트 메타정보를 담고 있습니다. 모듈별로 AndroidManifest.xml 파일을 포함하게 됩니다.


(3) java 폴더

소스코드와 테스트 코드가 있습니다.


(4) Gradle Scripts

안드로이드 스튜디오에서의 gradle sciprt을 포함하고있습니다.



- 프로젝트 build.gradle (여기선 Project: HelloWorld)

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

allprojects {
repositories {
jcenter()
}
}

task clean(type: Delete) {
delete rootProject.buildDir

} 

 직접 까서 보겠습니다.

프로젝트 build gradle은 다수의 모듈이 존재할떄 전체 모듈에 공통적으로 적용하는 부분을 기술하는 부분입니다.


크게 두부분으로 구성되어있습니다. 

buildscirpt은 빌드 스크립트를 구동하는 부분입니다. 외부저장소와 의존성 부분을 지정합니다. 외부저장소로 jcenter, mavenCentral 이 있습니다.

요즘은 jcenter를 많이 사용한다고 합니다. 또한 dependencies(의존성부분) 에는 안드로이드 gradle의 플로그인 버전을 기술합니다.


그외에는 전체 프로젝트 공통으로 사용할수 있는 task 를 정의합니다. 기본적으로 clean 태스크가 추가되며, 단순히 build 폴저를 제거하는 역할을 하고있습니다. app과 같은 하위 Module의 build 폴더도 모두 제거한답니다. 모듈이 다수이면 다수모듈의 build 폴더가 제거되겠지요?



- 모듈 build.gradle (여기선 Module:app)

apply plugin: 'com.android.application'

android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
defaultConfig {
applicationId "com.example.pjh.helloworld"
minSdkVersion 24
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:26.+'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'

} 

 크게 네 부분으로 구분됩니다. 


첫번째는 모듈의 plugin 부분입니다.

안드로이드 App module 은 com.android.application을 지정합니다.

안드로이드 library module은 com.android.library를 지정합니다.

동시에 플러그인을 2개 지정할수는 당연히 없습니다.


두번째는 android로 AndroidManifest.xml을 재설정 한다고 생각하시면 됩니다.

gradle에서 설정한게 manifest보다 우선시 됩니다. 


세번째는 buildTypes에는 빌드 타입에 따라 다른 동작을 지정할 수 있습니다.

빌드타입에 따라 다른 동작을 지정할 수 있습니다. debug와 release가 있습니다. debug는 개발단계에서 사용되며, release는 마켓이나 외부에 배포할때 사용합니다. 


네번째는 의존성부분(dependencies) 입니다.

libs폴더에있는 모든 jar파일 의존성에 추가합니다.

또한 compile은 module을 빌드 할 때 포함하는 외부라이브러리입니다. 로컬에 존재하지 않는 경우, 앞서 지정한 저장소였던 jcenter(프로젝트 gradle에서) appcompat 지원 라이브러리를 다운로드합니다.




Gradle은 저장소위치와 라이브러리 버전등을 지정하면 빌드 시 자동으로 해당 버전또는 최신버전을 포함하므로 개발자는 신경 쓰지 않아도 되는 엄청난 강점을 가지고 있습니다. 계속해서 Gradle 포스팅을 하도록 하겠습니다.


'개발 Support > Gradle' 카테고리의 다른 글

안드로이드 Gradle Test  (0) 2017.07.12
안드로이드 Gradle 멀티 프로젝트 사용  (0) 2017.07.10
Android Gradle 외부 라이브러리 추가  (0) 2017.07.10
Gradle Task와 생명주기  (0) 2017.07.10
Gradle 개요  (0) 2017.07.08

+ Recent posts