Думаю, что у многих возникала необходимость повторно использовать отдельные модули своего Android приложения в другом проекте. Для решения этой задачи есть простые пути, например, публично разместить Android библиотеку с помощью JitPack. Решение отличное, но если нужно разместить библиотеку приватно, то придется заплатить, а тариф чаще всего будет зависеть от количества размещаемых артефактов. Данное решение подойдет далеко не всем.
Ниже я предложу простой вариант решения данной проблемы с использованием Sonatype Nexus Repository OSS.
Статья не претендует на полноту и отражает лишь базовое решение. В итоге в вашем распоряжении будет установленное ПО для управления артефактами на стороне какого-либо хоста, скрипт для публикации Android библиотеки, возможность реализовать зависимости в своём приложении из локального maven репозитория. Возможно, публикации подобного рода уже есть на Хабре, но понятного туториала для Android разработчика я не нашел, что и побудило меня поделиться с вами информацией. Буду рад, если она окажется действительно полезной в работе.
Для начала необходимо определиться с тем куда устанавливать Nexus. Логично, если это будет сервер, к которому у вас всегда будет доступ при разработке. В данной статье мы будем устанавливать Nexus на тот же хост, на котором ведем разработку. Отличия при установке на сервер будут лишь в ip адресе, по которому мы будем обращаться к репозиториям.
Перед установкой Nexus, нужно скачать и установить JRE. Подойдёт только Oracle JRE и только версии 1.8 (пробовал на 10, но Nexus ругался), это явно указано в документации. Не забудьте добавить в PATH путь к исполняемым файлам JRE.
Далее нужно скачать Nexus с официального сайта. На момент написания статьи это версия 3.12
Скачанный архив достаточно распаковать там, где вам удобно. После чего можно запускать программу и начинать работать. Для долгосрочного и удобного использования нужно зарегистрировать Nexus как службу и запускать её при старте ОС. Как это сделать — достаточно понятно описано в документации. В нашем же случае достаточно перейти в папку "
В случае c Windows:
В случае с Unix:
В результате вы должны увидеть оповещение об успешном старте, выглядит оно примерно так:
Пришло время проверить работоспособность Nexus. Для этого достаточно перейти по ссылке http://localhost:8081. Как вы понимаете, в случае с сервером вместо "
Первым делом нужно авторизоваться, жмём "
На экране настроек вы увидите ссылки на
Но перед тем, как перейти к описанию репозиториев, стоит сделать основные настройки для пользователей. Перейдем в раздел "
Помимо роли администратора и анонимного пользователя я предлагаю выделить роли типа "
Жмем «Create role», затем выбираем «Nexus role», вводим данные для «Downloader» как на скрине ниже:
О том, какие привилегии за что отвечают — подробно описано в документации. Нам нужно выбрать привилегию с флагом "
По аналогии создаем роль "
Далее создадим пользователей, которым назначим настроенные роли. Заходим в раздел "
Так как наша цель — приватная работа, то стоит отключить доступ к данным репозиториев для анонимных пользователей, для этого заходим в пользователя "
Для того, чтобы запретить просматривать содержимое репозиториев через web интерфейс анонимным пользователям — перейдём в раздел "
Остался последний этап — настройка репозиториев. Переходим в раздел "
Создадим репозитории для «Release» и «Snapshot» версий артефактов. Жмем "
Второй репозиторий назовём «android_snapshot», поменяем "
Если не понятно на что это влияет — можно прочитать здесь. Фактически для репозитория «android» будет недоступна возможность загрузить повторно одну и ту же версию библиотеки, это привычное поведение при общении, например, с maven-central. Для репозитория «android_snapshot» наименование версии обязательно должно будет оканчиваться на «SNAPSHOT» и будет доступна загрузка одной и той же версии повторно.
Также обратите внимание на то, что в списке репозиториев есть колонка «URL» с кнопками «Copy», эти ссылки понадобятся нам в дальнейшем для доступа к репозиториям из проектов.
Поздравляю! Базовая настройка Nexus сделана, пора приступить к созданию и публикации библиотеки.
Создаём Android проект, назовём его «TestLibrary». Далее в «Project View» нажимаем на корень проекта правой кнопкой мыши выбираем «New» и «Module». В открывшемся окне выбираем «Android library» и называем библиотеку «HelloLibrary». В итоге вы увидите рядом с модулем «app» модуль нашей новой библиотеки.
Добавим в библиотеку класс с функцией приветствия:
Библиотека готова, пора публиковать. В «Project view» в модуль «hellolibrary» добавляем файл и называем его «publisher.gradle». В нём будет храниться скрипт для публикации библиотеки.
Далее переходим в «build.gradle» нашей библиотеки, применяем к нему наш publisher и очищаем от лишних зависимостей:
После чего переходим в список gradle заданий и выполняем "
Теперь можем публиковать, просто выполнив задание "
Библиотека опубликована, поздравляю! Проверим результат в web интерфейсе нашего Nexus. Переходим в пункт «Browse» и выбираем репозиторий «android». Увидеть вы должны следующее:
Для теста предлагаю создать ещё один пустой Android проект.
Для начала подключим репозиторий к проекту, просто добавив данные в «build.gradle» файл уровня проекта:
А теперь как и с любой другой библиотекой получим зависимость на нашу «hellolibrary» через implementation в «build.gradle» файле уровня «app».
Путь к зависимости прописывается как
Теперь вы можете вызвать функцию
Теперь у вас есть возможность повторно использовать приватные Android библиотеки в проектах. Жду замечаний!
Надеюсь вы не зря потратили своё время, спасибо!
Ниже я предложу простой вариант решения данной проблемы с использованием Sonatype Nexus Repository OSS.
Введение
Статья не претендует на полноту и отражает лишь базовое решение. В итоге в вашем распоряжении будет установленное ПО для управления артефактами на стороне какого-либо хоста, скрипт для публикации Android библиотеки, возможность реализовать зависимости в своём приложении из локального maven репозитория. Возможно, публикации подобного рода уже есть на Хабре, но понятного туториала для Android разработчика я не нашел, что и побудило меня поделиться с вами информацией. Буду рад, если она окажется действительно полезной в работе.
Шаг 1. Подготовка
Для начала необходимо определиться с тем куда устанавливать Nexus. Логично, если это будет сервер, к которому у вас всегда будет доступ при разработке. В данной статье мы будем устанавливать Nexus на тот же хост, на котором ведем разработку. Отличия при установке на сервер будут лишь в ip адресе, по которому мы будем обращаться к репозиториям.
Перед установкой Nexus, нужно скачать и установить JRE. Подойдёт только Oracle JRE и только версии 1.8 (пробовал на 10, но Nexus ругался), это явно указано в документации. Не забудьте добавить в PATH путь к исполняемым файлам JRE.
Далее нужно скачать Nexus с официального сайта. На момент написания статьи это версия 3.12
Шаг 2. Установка и настройка Nexus
Скачанный архив достаточно распаковать там, где вам удобно. После чего можно запускать программу и начинать работать. Для долгосрочного и удобного использования нужно зарегистрировать Nexus как службу и запускать её при старте ОС. Как это сделать — достаточно понятно описано в документации. В нашем же случае достаточно перейти в папку "
nexus-3.12/bin/
" и запустить из командной строки файл nexus. В случае c Windows:
nexus.exe /run
В случае с Unix:
./nexus run
В результате вы должны увидеть оповещение об успешном старте, выглядит оно примерно так:
Image
Пришло время проверить работоспособность Nexus. Для этого достаточно перейти по ссылке http://localhost:8081. Как вы понимаете, в случае с сервером вместо "
localhost
" нужно указать ip адрес вашего сервера, а Nexus для работы использует порт 8081. Вы увидите такую страницу:Image
Первым делом нужно авторизоваться, жмём "
Sign in
" справа вверху и вводим логин (admin
) и пароль (admin123
) администратора. После этого появляется иконка шестеренки, по нажатию на которую мы попадём в настройки.Image
На экране настроек вы увидите ссылки на
Blob Stores
и Repositories
. Blob Stores
— это хранилища для данных ваших репозиториев. В настройках каждого репозитория можно будет указать конкретный Blob Store
для хранения информации. Нам будет достаточно одного, созданного по умолчанию. Repositories
— это интересующие нас репозитории, в которых будут храниться библиотеки.Но перед тем, как перейти к описанию репозиториев, стоит сделать основные настройки для пользователей. Перейдем в раздел "
Roles
".Image
Помимо роли администратора и анонимного пользователя я предлагаю выделить роли типа "
Downloader
" — для загрузки зависимостей в проекты, "Contributor
" — для отправки библиотек в Nexus.Жмем «Create role», затем выбираем «Nexus role», вводим данные для «Downloader» как на скрине ниже:
Image
О том, какие привилегии за что отвечают — подробно описано в документации. Нам нужно выбрать привилегию с флагом "
repository-view
" (отвечает за работу с данными именно репозиториев), привилегия должна также давать право на чтение данных репозитория, это флаг "read
", и так как в Android мы работаем с maven репозиториями, то стоит остановиться на флаге "maven2
", чтобы не давать пользователю работать с другими типами репозиториев. Жмём "Create role
".По аналогии создаем роль "
Contributor
". Разница лишь в том, что право чтения унаследуем от роли "Downloader
" (настройка в нижней части страницы), а руками дадим привилегии на редактирование, добавление артефактов в репозитории, а также на просмотр данных репозиториев через web интерфейс.Image
Далее создадим пользователей, которым назначим настроенные роли. Заходим в раздел "
Users
" (в левой части окна) и нажимаем "Create local user
". Для проверки можно задать пароли аналогичные стандартному паролю админа, то есть "downloader123
" и "contributor123
". Образец заполнения на скрине:Image
Так как наша цель — приватная работа, то стоит отключить доступ к данным репозиториев для анонимных пользователей, для этого заходим в пользователя "
anonimous
" и меняем его статус с "Active
" на "Disabled
". В этом случае нельзя будет анонимно получить зависимости в Android проекте, а только с указанием определенного пользователя и пароля, но скачивать данные через web интерфейс всё ещё будет возможно.Для того, чтобы запретить просматривать содержимое репозиториев через web интерфейс анонимным пользователям — перейдём в раздел "
Anonimous
" и снимем флаг с опции "Allow anonymous users to access the server
". Не забудьте сохранить изменения.Остался последний этап — настройка репозиториев. Переходим в раздел "
Repositories
" и видим там созданные по умолчанию репозитории. Среди них есть репозитории "maven2
", если присмотреться, то можно увидеть разные типы: «proxy», «group», «hosted». «Proxy» репозиторий просто пробрасывает при обращении к себе пользователя на другой репозиторий, в случае с преднастроенным "maven-central
" это отсылка на https://repo1.maven.org/maven2/, «group» может включать в себя несколько репозиториев, а «hosted» — это уже конкретный репозиторий, хранящийся в Nexus. Они-то нам сейчас и пригодятся.Создадим репозитории для «Release» и «Snapshot» версий артефактов. Жмем "
Create repository
", выбираем "maven2 (hosted)
". Первый репозиторий назовём «android» и просто сохраним не меняя настройки:Image
Второй репозиторий назовём «android_snapshot», поменяем "
Version policy
" на «Spapshot» и "Deployment policy
" на «Allow redeploy». Image
Если не понятно на что это влияет — можно прочитать здесь. Фактически для репозитория «android» будет недоступна возможность загрузить повторно одну и ту же версию библиотеки, это привычное поведение при общении, например, с maven-central. Для репозитория «android_snapshot» наименование версии обязательно должно будет оканчиваться на «SNAPSHOT» и будет доступна загрузка одной и той же версии повторно.
Также обратите внимание на то, что в списке репозиториев есть колонка «URL» с кнопками «Copy», эти ссылки понадобятся нам в дальнейшем для доступа к репозиториям из проектов.
Поздравляю! Базовая настройка Nexus сделана, пора приступить к созданию и публикации библиотеки.
Шаг 3. Создание и публикация Android библиотеки
Создаём Android проект, назовём его «TestLibrary». Далее в «Project View» нажимаем на корень проекта правой кнопкой мыши выбираем «New» и «Module». В открывшемся окне выбираем «Android library» и называем библиотеку «HelloLibrary». В итоге вы увидите рядом с модулем «app» модуль нашей новой библиотеки.
Image
Добавим в библиотеку класс с функцией приветствия:
package com.example.nexus.hellolibrary
fun helloFromOurLibrary() {
println("### Hello World! This is our new Android library!")
}
Библиотека готова, пора публиковать. В «Project view» в модуль «hellolibrary» добавляем файл и называем его «publisher.gradle». В нём будет храниться скрипт для публикации библиотеки.
// Подключаем плагин для публикации
apply plugin: 'maven-publish'
ext {
// URL для Release репозитория
repositoryReleaseUrl = "http://localhost:8081/repository/android/"
// URL для Snapshot репозитория
repositorySnapshotUrl = "http://localhost:8081/repository/android_snapshot/"
// Логин пользователя, от которого будет производиться загрузка
contributorUserName = "contributor"
// Пароль пользователя, от которого будет производиться загрузка
contributorPassword = "contributor123"
// Группа для артефакта
libraryGroupId = "com.example.nexus"
// Имя артефакта
libraryArtifact = "hellolibrary"
// Текущая версия
libraryVersion = "0.0.1"
}
// Публикуем
publishing {
// В список репозиториев
repositories {
// Подключаем наш репозиторий
maven {
// Указываем данные для авторизации
credentials {
username contributorUserName
password contributorPassword
}
// И ссылку на репозиторий в зависимости от того Snapshot это версия или нет
url libraryVersion.endsWith("SNAPSHOT") ? repositorySnapshotUrl : repositoryReleaseUrl
}
}
// Настраиваем задание публикации для maven-publish плагина
publications {
// AndroidLibrary - это просто имя, на основании которого
// сформируется задание, оно может быть любым
AndroidLibrary(MavenPublication) {
// Настраиваем параметры публикации артефакта
groupId libraryGroupId
artifactId libraryArtifact
version libraryVersion
// Указываем универсальный путь к артефакту
artifact "$buildDir/outputs/aar/${project.getName()}-release.aar"
pom {
// Добавляем все зависимости первого уровня в публикацию для того,
// чтобы избежать ClassNotFoundException при использовании
// библиотеки.
withXml {
def dependencies = asNode().appendNode("dependencies")
configurations.getByName("releaseCompileClasspath")
.getResolvedConfiguration()
.getFirstLevelModuleDependencies()
.each {
def dependency = dependencies.appendNode("dependency")
dependency.appendNode("groupId", it.moduleGroup)
dependency.appendNode("artifactId", it.moduleName)
dependency.appendNode("version", it.moduleVersion)
}
} // withXml
} // pom
} // AndroidLibrary
} // publications
} //publishing
Далее переходим в «build.gradle» нашей библиотеки, применяем к нему наш publisher и очищаем от лишних зависимостей:
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
// Подключаем publisher
apply from: "publisher.gradle"
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 18
targetSdkVersion 28
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
repositories {
mavenCentral()
}
После чего переходим в список gradle заданий и выполняем "
assemble
" для нашей библиотеки, это необходимо делать перед публикацией для того, чтобы собрать aar файл библиотеки.Image
Теперь можем публиковать, просто выполнив задание "
publishAndroidLibraryPublicationToMavenRepository
".Библиотека опубликована, поздравляю! Проверим результат в web интерфейсе нашего Nexus. Переходим в пункт «Browse» и выбираем репозиторий «android». Увидеть вы должны следующее:
Image
Шаг 4. Использование зависимостей из Nexus
Для теста предлагаю создать ещё один пустой Android проект.
Для начала подключим репозиторий к проекту, просто добавив данные в «build.gradle» файл уровня проекта:
buildscript {
ext.kotlin_version = '1.2.50'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
// Подключаем локальный репозиторий
maven {
credentials {
username "downloader"
password "downloader123"
}
url "http://localhost:8081/repository/android"
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
А теперь как и с любой другой библиотекой получим зависимость на нашу «hellolibrary» через implementation в «build.gradle» файле уровня «app».
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.nexus.fff"
minSdkVersion 18
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:28.0.0-alpha3'
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
// Получаем зависимость
implementation "com.example.nexus:hellolibrary:0.0.1"
}
Путь к зависимости прописывается как
groupId:artifactId:version
.Теперь вы можете вызвать функцию
helloFromOurLibrary()
в своём Android проекте и протестировать работоспособность всей схемы. Поздравляю!Резюме
Теперь у вас есть возможность повторно использовать приватные Android библиотеки в проектах. Жду замечаний!
Надеюсь вы не зря потратили своё время, спасибо!
Комментарии (9)
Telmah
12.07.2018 01:04maven install умеет складировать библиотеки и метаданные в локальный репозиторий — директорию на диске… в вашем случае по моему тоже должен быть некий способ
tehreh1uneh Автор
12.07.2018 08:18Локально, к сожалению, не выход, так как использовать библиотеки нужно нескольким разработчикам и как с рабочего места, так и, например, из дома. Поэтому и была вся эта морока с Nexus. В итоге поставили на сервер и пока нареканий нет.
ser-mk
Сказать честно слишком много действий для повторного использования кода, ну прям чересчур)
Для гита можно использовать, субмодули, а саму библиотеку выделить в отдельный репозиторий, пусть даже локальный.
tehreh1uneh Автор
Не работал с подмодулями, поэтому внятно ответить не смогу пока не разберусь. При использовании подмодулей возможность версионирования библиотеки присутствует? Буду благодарен за ссылки на статьи по этой теме, кроме документации.
ser-mk
об субмодулях кто только не писал)
habr.com/post/60860
habr.com/post/75964
О каком версионировании вы говорите? Через гит или gradle?
tehreh1uneh Автор
В maven репозиторий можно выгружать библиотеки под разными версиями и загружать в свой проект тоже любую версию по усмотрению. Интересует наличие аналогии при использовании подмодулей git. И спасибо за ссылки.
ser-mk
В гите все аналогично, checkout делаешь на любой тег или ветку и вот нужная версия. все отличие в том что все это делает гит а не система сборки.
maven в этом плане наверно удобнее будет, все в одном месте через одну систему. Только жаль что под андройд используется gradle по умолчанию.
Alexei38
Для одного разработчика может и чересчур, но когда работает группа разработки, зависимостей очень много. Да и если есть переиспользование другими приложениями во время сборки. То этот способ просто необходим