В этой статье я расскажу как создать библиотеку, которая использует другие библиотеки и при этом уместить всё в одном jar.
Допустим мы пишем библиотеку, она использует другие библиотеки и, в частности, для примера, support library. Если бы мы использовали maven, то в pom файле просто прописали зависимости и не парились. Но что если нашу библиотеку будут использовать люди, которые не пользуются системами сборок или пользуются ant' ом?
Мы можем положить зависимости рядом с нашим jar. Но тогда неизбежны конфликты библиотек разных версий, например, если мы используем одну версию support library, а в самом приложении другая. Тогда придется руками одну из них удалять.
Можно пойти другим путем, вспомним что jar это обычный zip файл. Мы распакуем все зависимости, получим байт-код в виде .class файлов, далее компилируем код нашей библиотеки, кладем все .class файлы в одно место и собираем из них jar. Но если в приложении используются те же библиотеки что и у нас, то получим ошибку что в проекте два одинаковых класса.
Для решения этой проблемы воспользуемся утилитой jarjar. Она переименовывает все классы в jar файле. На примере support library — все классы находятся в пакете android.support.v4
Пример использования:
Создадим правило для переименования классов android.support.v4.* в inner.android.support.v4.*
Запускаем
В итоге получили jar'ку с переименованными классами. Далее мы распаковываем все наши зависимости с переименованными классами и компилируем. Получаем библиотеку, которая содержит весь код нужный для выполнения.
Наша библиотека содержит код всех зависимостей, которые могут весить немало. Чтобы уменьшить размер применим proguard для удаления неиспользуемых классов и методов.
И в заключение небольшой скрипт на gradle который всё это делает
Вои и всё, после выполнения скрипта мы получим proguard_library.jar, который можно добавлять к приложению и использовать.
В моём случае библиотека использует support library и dropbox sdk, и весит 50 кБ.
Этим же способом можно уменьшать размер вашего apk, все зависимости можно подключать не как jar файлы, а распаковывать в .classes и применять proguard, тогда он удалит неиспользуемые классы из библиотек. Так можно подключать к проекту тяжелые фреймворки не боясь увеличения размера apk
Допустим мы пишем библиотеку, она использует другие библиотеки и, в частности, для примера, support library. Если бы мы использовали maven, то в pom файле просто прописали зависимости и не парились. Но что если нашу библиотеку будут использовать люди, которые не пользуются системами сборок или пользуются ant' ом?
Мы можем положить зависимости рядом с нашим jar. Но тогда неизбежны конфликты библиотек разных версий, например, если мы используем одну версию support library, а в самом приложении другая. Тогда придется руками одну из них удалять.
Можно пойти другим путем, вспомним что jar это обычный zip файл. Мы распакуем все зависимости, получим байт-код в виде .class файлов, далее компилируем код нашей библиотеки, кладем все .class файлы в одно место и собираем из них jar. Но если в приложении используются те же библиотеки что и у нас, то получим ошибку что в проекте два одинаковых класса.
Для решения этой проблемы воспользуемся утилитой jarjar. Она переименовывает все классы в jar файле. На примере support library — все классы находятся в пакете android.support.v4
Пример использования:
java -jar jarjar.jar process <rulesFile> <inJar> <outJar> rulesFile - файл с правилами переименования inJar, outJar - тут все понятно
Создадим правило для переименования классов android.support.v4.* в inner.android.support.v4.*
и сохраним в файл rules.txtrule android.support.v4.** inner.android.support.v4.@1
Запускаем
java -jar jarjar.jar rules.txt android-support-v4.jar android-support-v4-renamed.jar
В итоге получили jar'ку с переименованными классами. Далее мы распаковываем все наши зависимости с переименованными классами и компилируем. Получаем библиотеку, которая содержит весь код нужный для выполнения.
Наша библиотека содержит код всех зависимостей, которые могут весить немало. Чтобы уменьшить размер применим proguard для удаления неиспользуемых классов и методов.
И в заключение небольшой скрипт на gradle который всё это делает
apply plugin: 'java' defaultTasks 'proguard' task unpackJars(dependsOn: compileJava) { //распаковываем классы из библиотек file('libs').listFiles().each { File file -> if (file.name.endsWith('.jar')) { copy { from(zipTree(file.path)) into('build/classes/main') } } } //собираем jar'ку tasks.jar.execute() } task proguard(type: proguard.gradle.ProGuardTask, dependsOn: unpackJars) { injars 'build/libs/library.jar' outjars 'build/libs/proguard_library.jar' libraryjars '/Applications/my/Android Studio.app/sdk/platforms/android-10/android.jar' //укажем что классы нашей библиотеки удалять не нужно keep 'class com.CasualSoftware.classloader.library.**' } dependencies { compile 'com.google.android:android:2.2.1' compile fileTree(dir: 'libs', include: ['*.jar']) }
Вои и всё, после выполнения скрипта мы получим proguard_library.jar, который можно добавлять к приложению и использовать.
В моём случае библиотека использует support library и dropbox sdk, и весит 50 кБ.
Этим же способом можно уменьшать размер вашего apk, все зависимости можно подключать не как jar файлы, а распаковывать в .classes и применять proguard, тогда он удалит неиспользуемые классы из библиотек. Так можно подключать к проекту тяжелые фреймворки не боясь увеличения размера apk