개발하는 두더지

[Android, Gradle] Android Studio에서 여러개의 Jar 파일을 하나의 Jar 파일로 만들기 본문

Java,Android

[Android, Gradle] Android Studio에서 여러개의 Jar 파일을 하나의 Jar 파일로 만들기

덜지 2018. 5. 15. 13:58

Jar 파일 내에서 다른 Jar 파일의 클래스를 참조해야 할 수도 있습니다. 하지만 Jar 파일 안에 또 다른 Jar 파일을 넣을 수는 없습니다. 

왜냐하면 Class-Path 는 Jar 파일 내의 Jar 파일이나 인터넷 프로토콜을 통해 액세스 할 수 있는 클래스가 아니라 로컬 네트워크의 클래스 또는 Jar 파일을 가리킵니다. Jar 내부에서는 Class-Path를 사용하여 내부의 Jar에서 클래스를 로드하는 방법을 알지 못하기 때문입니다.

Adding Classes to the JAR File's Classpath



그럼 어떻게 하나의 Jar 파일안에 모든 dependencies 를 포함시키는 것인가?

  1. Jar 를 unpackaging 하여 class 목록을 추출하고

  2. Jar 파일을 만들 때 모든 class 를 하나의 Level로 하여 packaging 하는 방법입니다.


Android Studio Gradle 로 위와 같이 만드는 방법을 알아보겠습니다.


위와 같은 방법은 이미 라이브러리들이 여러개 있습니다.

FatJar, ShadowJar


라이브러리를 사용안하고 gradle script 에서 아래와 같이 작성하면 됩니다.

안드로이드 새 프로젝트를 생성한 뒤

File -> New -> New Module -> Android Library 로 라이브러리 프로젝트를 하나 만든뒤

라이브러리 프로젝트의 build.gradle에서 아래처럼 작성합니다.


1.


android.libraryVariants.all { variant ->
def name = variant.buildType.name
if(name.equals(com.android.builder.core.BuilderConstants.DEBUG)) {
return; // Skip debug builds.
}
def task = project.tasks.create "jar${name.capitalize()}", Jar
task.dependsOn variant.javaCompile

// Include Java Classes
task.from variant.javaCompile.destinationDir

// Include dependent jars with some exceptions
task.from configurations.compile.findAll {
it.getName() != 'android.jar' && !it.getName().startsWith('junit') &&
!it.getName().startsWith('hamcrest')
}.collect {
it.isDirectory() ? it : zipTree(it)
}
artifacts.add('archives', task)
}

stackoverflow 에서 찾은 코드입니다.

터미널에서 gradlew jarRelease 를 실행하거나 오른쪽 상단 Gradle 탭에서 Gradle->:라이브러리 -> Tasks -> other -> JarRelease 를 실행합니다


variant.javaCompile.destinationDir

프로젝트명\라이브러리명\build\intermediates\classes\release 에서 Java Class를 포함시키고

configurations.compile.findAll 을 통해서 포함시킬 Jar 파일을 선택하여 zipTree로 추가할 Jar 의 계층 구조를 가져와 같은 Level에 포함시키는 방법인 것 같습니다. 하지만 R.class가 함께 포함되어 Jar 파일을 패키징하므로 다른 프로젝트에서 import를 할 경우 에러가 발생할 수도 있습니다.



2


task fatJarTest(type: Jar) {
from (zipTree('libs/추가할 라이브러리1.jar'))

from (zipTree('libs/추가할 라이브러리2.jar'))
from ('build/intermediates/classes/release/') {
exclude '**android/'
exclude '**/BuildConfig.class'
exclude '**/R$*.class'
exclude '**/R.class'
}
}

stackoverflow에서 찾은 코드인데


추가할 라이브러리를 zipTree로 계층 구조를 가져오고

build\intermediates\classes\release 에서 android 폴더 , R.class 를 제외하고 하나의 Jar 파일로 만들 수 있습니다.

fatJarTest 를 실행하면 라이브러리\build\libs에 라이브러리명.jar 파일이 생성됩니다.


포스팅 시점으로 다른 프로젝트에 import시 정상 작동되고 있습니다.


라이브러리.jar 이름 변경하기

아래의 renameJar Task를 실행하면 라이브러리명.jar -> myJar.jar 로 이름을 변경할 수 있습니다.

task renameJar(type: Copy) {
from('build/libs')
into('libs/')
include('라이브러리명.jar')
rename('라이브러리명.jar', 'myJar.jar')
}


Comments