Share your Library as a dependency

Rachit Goyal
May 5, 2018 · 10 min read

Have you ever dealt with the frustration of trying to find an Android library, but anything and everything you find is either buggy, deprecated or just doesn’t fit your requirements?

It may be some kind of view, or some way to animate views, or an easier way to store data, could be anything. In that moment, you’re stuck, and so you think to yourself - why don’t I just build this myself.

Since I’ve been through this turmoil before and have somehow successfully created a custom view from scratch, I thought why not save the world some trouble!

So this brings me to the point of this article. Once you have developed a library, how do you share it with the world?

I will be discussing two methods of sharing your libraries:

  1. Maven Central - the hard way, can take upto 2 days.
  2. JitPack - the easy way, a matter of minutes.

For all those who’re looking for a quick solution, just jump to the section where I talk about JitPack. But do remember that using Maven Central makes it easier for developers to search for you library, so you make the call.

Maven Central

So this is the hard bit, takes up time, and is a difficult process to understand.

I will be working on Android Studio as my IDE, which uses the Gradle Build system.

I will take the example of my SegmentedProgressBar library to explain the process.

A pre-requisite of the process is an account on Github. If you already have one and that’s the one you want to use to publish your libraries, perfect, otherwise create one now.

On your own library project, start off by separating the library code from the sample project. It’s best if you create separate modules for these. You can learn how to create and rename your module here.

In my case, the “app” module is the sample application and the “segmented” module is the actual library. Before proceeding, I would recommend switching to the Project View in your Android Studio.

Located on the top left of your Project Explorer in Android Studio

We will have to setup some files in order to push our library to Maven Central. Follow the following steps:

Step 1 - In your sample module’s build.gradle, include the library

// This is app module's build.gradle file
apply plugin: 'com.android.application'
dependencies {
compile project(':segmented')
}

Step 2 - In the library module’s build.gradle file, add this line

// This is segmented module's build.gradle file
apply plugin: 'com.android.library'
apply from: 'maven-push.gradle' // Add this line to the top

Step 3 - In the library module create 2 new files - gradle.properties and maven-push.gradle

This is the library module - with 2 files added

Add this code to the gradle.properties file that you just created:

POM_NAME=SegmentedProgressBar \\ Your Library Name
POM_ARTIFACT_ID=segmentedProgressBar \\ Your Library Name
POM_PACKAGING=aar

In the maven-push.gradle file that you created, add these lines (replace <YEAR> with current year and <YOUR_NAME> with your name.

/*
* Copyright <YEAR> <YOUR_NAME>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

apply plugin: 'maven'
apply plugin: 'signing'

def isReleaseBuild() {
return VERSION_NAME.contains("SNAPSHOT") == false
}

def getReleaseRepositoryUrl() {
return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL
: "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
}

def getSnapshotRepositoryUrl() {
return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL
: "https://oss.sonatype.org/content/repositories/snapshots/"
}

def getRepositoryUsername() {
return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : ""
}

def getRepositoryPassword() {
return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : ""
}

afterEvaluate { project ->
uploadArchives {
repositories {
mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }

pom.groupId = GROUP
pom.artifactId = POM_ARTIFACT_ID
pom.version = VERSION_NAME

repository(url: getReleaseRepositoryUrl()) {
authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
}
snapshotRepository(url: getSnapshotRepositoryUrl()) {
authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
}

pom.project {
name POM_NAME
packaging POM_PACKAGING
description POM_DESCRIPTION
url POM_URL

scm {
url POM_SCM_URL
connection POM_SCM_CONNECTION
developerConnection POM_SCM_DEV_CONNECTION
}

licenses {
license {
name POM_LICENCE_NAME
url POM_LICENCE_URL
distribution POM_LICENCE_DIST
}
}

developers {
developer {
id POM_DEVELOPER_ID
name POM_DEVELOPER_NAME
}
}
}
}
}
}

signing {
required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
sign configurations.archives
}

//task androidJavadocs(type: Javadoc) {
//source = android.sourceSets.main.allJava
//}

//task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
//classifier = 'javadoc'
//from androidJavadocs.destinationDir
//}

task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.sourceFiles
}

artifacts {
archives androidSourcesJar
}
}

Step 4 - Now, go to the root level of your project and open the gradle.properties file

Add the following code to the end:

VERSION_NAME=<YOUR_VERSION_NAME>
VERSION_CODE=<VERSION_CODE>11
GROUP=com.github.<YOUR_GITHUB_USERNAME>

POM_DESCRIPTION=<PROJECT_DESCRIPTION>
POM_URL=https://github.com/<YOUR_GITHUB_USERNAME>/<PROJECT_NAME>
POM_SCM_URL=https://github.com/<YOUR_GITHUB_USERNAME>/<PROJECT_NAME>
POM_SCM_CONNECTION=scm:git@github.com:<YOUR_GITHUB_USERNAME>/<PROJECT_NAME>.git
POM_SCM_DEV_CONNECTION=scm:git@github.com:<YOUR_GITHUB_USERNAME>/<PROJECT_NAME>.git
POM_LICENCE_NAME=The Apache Software License, Version 2.0
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=<YOUR_GITHUB_USERNAME>
POM_DEVELOPER_NAME=<YOUR_FULL_NAME>

Make sure to replace the <___> values with the actual values. And do NOT put the brackets (<>).

You can give any version name - 1.0.0, 0.1, v1. Version codes, on the other hand, should preferably progress linearly, and be numeric values.

A sample of this file would look something like this:

VERSION_NAME=0.0.1
VERSION_CODE
=1
GROUP
=com.github.rayzone107

POM_DESCRIPTION
=A library that creates a Custom View
POM_URL
=https://github.com/rayzone107/SegmentedProgressBar
POM_SCM_URL
=https://github.com/rayzone107/SegmentedProgressBar
POM_SCM_CONNECTION
=scm:git@github.rayzone107/SegmentedProgressBar.git
POM_SCM_DEV_CONNECTION
=scm:git@github.rayzone107/SegmentedProgressBar.git
POM_LICENCE_NAME
=The Apache Software License, Version 2.0
POM_LICENCE_URL
=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST
=repo
POM_DEVELOPER_ID
=rayzone107
POM_DEVELOPER_NAME
=Rachit Goyal

GPG is an encryption software. It is used to encrypt our files. If you don’t have GPG installed on your laptop, you’ll need to first install it.

If you’re on a MAC, the easiest way to do so is using HomeBrew. Once you’ve Homebrew installed, setup GPG by following these commands. On a Windows, you can download GPG from here.

Next, begin by creating a GPG key. On the terminal/console:

$ gpg --gen-key

It’ll prompt you for your Real name & Email address. It’ll ask if you want to Change anything or (O)kay/(Q)uit. Press O to continue.

Then it’ll require you to create a new passphrase to protect your key. Enter a password, and make sure to remember it. Re-enter it.

Finally you’ll see an output like this:

pub rsa2048 2018–05–05 [SC] [expires: 2020–05–04]
X4EC727BA47X77E9D95060B96DE3B7EG93EA0576
uid Full Name<email_id@domain.com>
sub rsa2048 2018–05–05 [E] [expires: 2020–05–04]

In the second line is your actual key, but you don’t need the entire thing. It is an encoded field, and you just need the last 8 characters from it. In the above case, the key would be 93EA0576. Keep a note of your key.

Next publish the keys to the ubuntu and MIT servers, or any other servers if you wish to.

$ gpg --keyserver hkp://keyserver.ubuntu.com --send-keys <KEY>
$ gpg --keyserver hkp://pgp.mit.edu --send-keys <KEY>

In the above line, replace <KEY> with your key.

Once published, check to see if your key exists on the server.

$ gpg --keyserver hkp://pgp.mit.edu --search-keys <EMAIL_ID>

Replace <EMAIL_ID> with the email ID you used while creating the key.

If this command fails, don’t worry. The MIT servers do get down sometimes. You can wait for a while, and try this command again. Eventually, it will turn up on the server.

So now is the time we actually publish our project to the Maven Central servers. The easiest way to do this is by using Sonatype.

Before we begin you should upload your project on Github either through the command-line or by using a software like SourceTree.

Once you’re done uploading, follow the steps below:

STEP 1 - If you don’t have an account already, create a JIRA account on Sonatype.

STEP 2 - Create a new Issue by clicking the “Create” button on the top.

  • Select “Community Support — Open Source Project Repository Hosting” from the Project dropdown.
  • Select “New Project” as Issue type.
  • Put “Create Sonatype project for <YOUR_PROJECT>” as the Summary.
  • Put “com.github.<YOUR_GITHUB_NAME>” in groupId.
  • Put https://github.com/<GITHUB_NAME>/<PROJECT_NAME>” in ProjectURL.
  • Put https://github.com/<GITHUB_NAME>/<PROJECT_NAME>.git” in SCM url.
  • Put “<YOUR_GITHUB_USERNAME>” in Username(s).
  • Leave Already Synced to Central as No.
  • Click Create.
The complete issue might look something like this.

After you submit your issue, it can take upto 2 business days to process your issue. Usually it’s done in a few hours, but the mentioned time is 2 days. So be prepared to wait upto 2 days for it to be processed. Once it is, you’ll receive a confirmation e-mail on your mentioned email Id.

IMPORTANT - Do NOT deploy your project until your ticket above has been processed and you see RESOLVED on the project status. If you deploy before that, don’t blame me for your project never turning up.

ONLY proceed only the status is Resolved.

Ok, now go back to the root level project directory in Android Studio, and open gradle.properties. It’s the same file you’d edited earlier with the Version Name and Version Code.

Add these lines to the bottom of the file:

NEXUS_USERNAME=<SONATYPE_USERNAME>
NEXUS_PASSWORD
=<SONATYPE_PASSWORD>
signing.keyId
=<GPG_KEY>
signing.password
=<GPG_KEY_PASSWORD>
signing.secretKeyRingFile
=/Users/<SYSTEM_USERNAME>/.gnupg/secring.gpg
org.gradle.daemon
=true

Replace the above <> fields. The secretKeyRingFile is the path to the .gnupg folder in your System’s user’s root folder.

Next, Click on Gradle on the right panel in Android Studio. Expand your libraries panel (in this case :segmented).

Go to Tasks -> upload -> uploadArchives.

If you do not see upload, make sure “apply from: ‘maven-push.gradle’” is added to the build.gradle file in your library module.

The uploadArchives command will upload your library to Sonatype Staging Repositories. Login with your account and look for Staging Repositories on the left panel. Locate your staging library, it should probably be the one at the bottom of the list. Select it and press “Close” on the top. Then wait for a few minutes, and refresh the page. If it closed successfully, you should see “Release” enabled for that repository. It might take some time, so don’t panic. Press the “Release” button.

If this is your first library, go back to your JIRA on Sonatype and add a comment saying that “I’ve promoted the library”. After a while, you should get a response from Sonatype that your library will be available in about ten minutes. It will still take a few hours before the library sync’s with Maven Central. Go and check for your library on http://search.maven.org/. Just feed in your email ID or the project name.

Also, update your JIRA task on Sonatype and set Already Synced with Central to “Yes”. (Not a mandate)

Once everything is done, other developers can directly add your library to their projects by adding it as a dependency.

dependencies {
compile 'com.github.lawloretienne:trestle:0.0.3'
}

One major problem that I faced was trying to update the library once published. It was simple enough a process, but did not come intuitively to me. So in case you’re faced with the same issue, here goes.

To issue an update to the library, make the changes to the library.

Also update your root level gradle.properties file, and update the VERSION_NAME and VERSION_CODE. Then push to Github.

Next, run the Gradle -> Library -> Tasks -> upload -> uploadArchives task again.

Go to the Nexus Repository Manager and find your latest staging repository, that you just pushed. Close it and Release it like before. This time, you do not need to update anything JIRA.

Similarly, to create a new library, use the same Sonatype credentials and upload the library using the same steps. You do not need to create a new issue on JIRA. If you do, it will be marked as a Duplicate and Closed.


JitPack

I know uploading libraries to Maven Central can be exhausting, requires long waiting periods and is overall confusing. So to the rescue comes JitPack.io.

Uploading your library to JitPack is a ridiculously easy task, and will make life much easier.

JitPack is a novel package repository for JVM and Android projects. It builds Git projects on demand and provides you with ready-to-use artifacts (jar, aar).

So let’s begin.

The project creation part remains the same for both options. You should have a project with a separate module for the library.

Follow the steps:

STEP 1 - In your project’s root directory, open build.gradle

Add the following lines to the dependencies, below the build:gradle dependency.

dependencies {
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
}

STEP 2 - In your library’s directory (in this case segmented), add the following lines to the top of (below apply plugin: ‘com.android.library’) build.gradle file:

apply plugin: 'com.github.dcendents.android-maven'
group = 'com.github.<YOUR_GITHUB_NAME>'

STEP 3 - Upload your project to Github.

STEP 4 - Create a new Release Tag.

Click the “Releases” Tab

Click on “Draft a new release”

Click on “Draft a new Release”

Add a Tag Version, equivalent to VERSION_NAME in Gradle.

Set a “Tag version”

Click “Publish Release

STEP 5 - Look for your Repository on JitPack.

Enter <YOUR_GITHUB_NAME>/<PROJECT_NAME> in the search field.

STEP 6 - Click “Get It”

And that’s it.. Your library is now on JitPack.io