Reusing Android Private Libraries Using Sonatype Nexus Repository OSS

I think that many people needed to reuse individual modules of their Android application in another project. To solve this problem there are simple ways, for example, to publicly place the Android library using JitPack . The solution is excellent, but if you need to place the library in private, you will have to pay, and the tariff will often depend on the number of artifacts placed. This solution is not for everyone.

Below I will offer a simple solution to this problem using the Sonatype Nexus Repository OSS.


Introduction


The article does not claim to be complete and reflects only the basic solution. As a result, you will have installed software for managing artifacts on the side of any host, a script for publishing the Android library, the ability to implement dependencies in your application from the local maven repository. Perhaps, publications of this kind are already on Habré, but I did not find a clear tutorial for Android developer, which prompted me to share information with you. I would be glad if it will be really useful in the work.

Step 1. Preparation


First you need to figure out where to install Nexus. It is logical if this will be a server to which you will always have access during development. In this article we will install Nexus on the same host on which we are developing. Differences when installing on the server will be only in the ip address, by which we will access the repositories.

Before installing Nexus, you need to download and install the JRE. Only Oracle JRE is suitable and only version 1.8 (tried for 10, but Nexus swore), this is clearly indicated in the documentation . Do not forget to add the path to the JRE executable files in PATH.

Next you need to download Nexus from the official site . At the time of this writing, this is version 3.12.

Step 2. Installing and Configuring Nexus


The downloaded archive is enough to unpack where you are comfortable. Then you can run the program and start working. For long-term and convenient use, you need to register your Nexus as a service and launch it when the OS starts. How to do this is quite clearly described in the documentation . In our case, it is enough to go to the " nexus-3.12/bin/ " nexus-3.12/bin/ and launch the nexus file from the command line.

In the case of Windows:

 nexus.exe /run 

In the case of Unix:

 ./nexus run 

As a result, you should see an alert about a successful start, it looks like this:

Image


It's time to check the performance of Nexus. To do this, simply follow the link http: // localhost: 8081 . As you understand, in the case of the server, instead of " localhost ", you need to specify the ip address of your server, and Nexus uses port 8081 to work. You will see this page:

Image


First you need to log in, click " Sign in " at the top right and enter the login ( admin ) and password ( admin123 ) of the administrator. After that, a gear icon appears, by clicking on which we will get into the settings.

Image


On the settings screen you will see links to Blob Stores and Repositories . Blob Stores is the repository for your repository data. In the settings of each repository, you can specify a specific Blob Store to store information. We will only need one, created by default. Repositories are repositories of interest to us, in which libraries will be stored.

But before proceeding to the description of the repositories, it is worth making the basic settings for users. Go to the section " Roles ".

Image


In addition to the role of an administrator and anonymous user, I propose to allocate roles like " Downloader " - to download dependencies into projects, " Contributor " - to send libraries to Nexus.

Click "Create role", then select "Nexus role", enter the data for the "Downloader" as in the screenshot below:

Image


About what privileges are responsible for what - described in detail in the documentation . We need to choose the privilege with the " repository-view " flag (the repository-view is responsible for working with the data), the privilege should also give the right to read the repository data, this is the " read " flag, and since on Android we work with maven repositories, it is worth dwell on the " maven2 " flag to prevent the user from working with other types of repositories. Click " Create role ".

By analogy, create the role " Contributor ". The only difference is that the right to read is inherited from the role of " Downloader " (setting at the bottom of the page), and with hands we give privileges to edit, add artifacts to the repositories, and also to view these repositories through the web interface.

Image


Next, create users who will assign customized roles. Go to the section " Users " (in the left part of the window) and click " Create local user ". For verification, you can set passwords similar to the standard admin password, that is, " downloader123 " and " contributor123 ". Sample filling on the screen:

Image


Since our goal is private work, you should disable access to repository data for anonymous users, to do this, go to the " anonimous " user and change its status from " Active " to " Disabled ". In this case, it will not be possible to anonymously get dependencies in the Android project, but only with a specific user and password, but downloading the data through the web interface will still be possible.

In order to prohibit viewing the contents of the repositories through the web interface to anonymous users, go to the " Anonimous " section and uncheck the " Allow anonymous users to access the server " option. Remember to save your changes.

The last step remains - setting up repositories. Go to the " Repositories " section and see the repositories created by default there. Among them there are repositories " maven2 ", if you look closely, you can see different types: "proxy", "group", "hosted". The “Proxy” repository simply sends the user to another repository when accessing itself; in the case of the pre-configured " maven-central ", this can be sent to https://repo1.maven.org/maven2/ , the "group" can include several repositories, and "hosted" is already a specific repository stored in Nexus. They are now useful to us.

Create a repository for the "Release" and "Snapshot" versions of artifacts. Click " Create repository ", select " maven2 (hosted) ". The first repository is called "android" and just save without changing the settings:

Image


The second repository is called “android_snapshot”, change “ Version policy ” to “Spapshot” and “ Deployment policy ” to “Allow redeploy”.

Image


If it is not clear what it affects - you can read here . In fact, the “android” repository will not be able to reload the same version of the library, this is the usual behavior when communicating, for example, with maven-central. For the “android_snapshot” repository, the version name must necessarily end in “SNAPSHOT” and the download of the same version will be available again.

Also note that in the list of repositories there is a column “URL” with the buttons “Copy”; we will need these links later to access the repositories from the projects.

Congratulations! The basic Nexus setup is done, it's time to start creating and publishing a library.

Step 3. Creating and publishing the Android library


Create an Android project, call it "TestLibrary". Further in the “Project View” we click on the project root with the right mouse button and select “New” and “Module”. In the opened window, select the “Android library” and call the library “HelloLibrary”. As a result, you will see the module of our new library next to the “app” module.

Image


Add a class with the greeting function to the library:

 package com.example.nexus.hellolibrary fun helloFromOurLibrary() { println("### Hello World! This is our new Android library!") } 

The library is ready, it's time to publish. In the "Project view" in the module "hellolibrary" add the file and call it "publisher.gradle". It will store the script for publishing the library.

 //     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 //  assembleRelease   model { tasks.publishAndroidLibraryPublicationToMavenRepository { dependsOn project.tasks.assembleRelease } } } //publishing 

Next, go to the “build.gradle” of our library, apply our publisher to it and clean up of unnecessary dependencies:
 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() } 

Now we can publish, simply by completing the task " publishAndroidLibraryPublicationToMavenRepository ".
Image


Library published, congratulations! Check the result in the web interface of our Nexus. Go to the “Browse” item and select the “android” repository. You should see the following:
Image


Step 4. Using dependencies from Nexus


For the test, I propose to create another empty Android project.

First, let's connect the repository to the project by simply adding the data to the “build.gradle” project level file:

 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 } 

And now, like with any other library, we will get a dependency on our “hellolibrary” through the implementation in the “build.gradle” file of the “app” level.

 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" } 

The path to the dependency is prescribed as groupId:artifactId:version .

Now you can call the helloFromOurLibrary() function in your Android project and test the performance of the entire circuit. Congratulations!

Summary


Now you have the opportunity to reuse private Android libraries in projects. Waiting for comments!

I hope you do not waste your time, thank you!

Source: https://habr.com/ru/post/416665/


All Articles