Distributing an Android library

I had a my own open source library that I wanted to push out for myself and others to use. I didn’t want to go the JitPack route. I didn’t want to add Maven to my Android Studio project so that I’d have to create my own POM file and maintain that on top of the gradle file.

I went looking for a hosting location, I first chose the OSS Maven central library, Sonatype / Nexus. Items that need to be uploaded are the Maven POM, the Android archive (.aar), JavaDoc and source code. I started looking around for gradle addons to allow the push to Sonatype / Nexus. I tried many different gradle methods and didn’t get any of them to work. After around 3 weeks pounding my head trying to get various solutions to work, I gave up.

Since Android uses JCenter, I thought – hey why not me too? To get objects posted to JCenter, you need to get it into Bintray first and from there push it into JCenter; it could also be pushed into Sonatype / Nexus. I started looking for gradle addons to push to JCenter.

Here are some of the links that I looked at:

Bintray has their own gradle plugin, gradle-bintray-plugin, so I wanted to use that. If you look at the Android example, it’s version 1.5 and the current version is 1.7.x.

I had similar problems with solutions that I had while trying to upload to Sonatype / Nexus. However, I found a solution to it in my Bintray push. I was getting an error on generating Javadoc for objects that my project used, but were not created in the project. My bane was Google’s Gson. I was using this:

task sourcesJar(type: Jar) {
    from android.sourceSets.main.java.srcDirs
    classifier = 'sources'
}
task javadoc(type: Javadoc) { 
    source = android.sourceSets.main.java.srcDirs 
    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}

And found that this would fix that problem:

if (project.hasProperty("android")) { // Android libraries
    task sourcesJar(type: Jar) {
        classifier = 'sources'
        from android.sourceSets.main.java.srcDirs
    }
    task javadoc(type: Javadoc) {
        options.addBooleanOption('Xdoclint:none', true)
        source = android.sourceSets.main.java.srcDirs
        classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
    }
} else { // Java libraries
    task sourcesJar(type: Jar, dependsOn: classes) {
        classifier = 'sources'
        from sourceSets.main.allSource
    }
}

I found this article what how to do. Unfortunately, it didn’t put all of the explanations on why it did things and didn’t match up

Let me walk you through what I did, so you can use this too. From that article this statement:

Nick: Here we go, “Add New Repository”. Now the type is “Maven”. What shall I name it?

Max: How about “android”?

The problem here is that the repository name must exactly match the bintray / pkg enclosure. The example from Github:

bintray {   
.....
    pkg {
        repo = 'generic'
.....
    }
}

Here the “repo” name must be whatever you name your repository. The repository types are Debian, Docker, Maven, Npm, NuGet, OPKG, RPM and Vagrant. If you don’t get this right, it will be painful.

The general problem with the here with the gradle-bintray-plugin is that variables definitions are in hard coded in multiple places and sometimes the same thing. That means that for a change, you will have to change multiple variables with a new value. I came up with this:

In my module library gradle file, i created this, so that the version would only need to be changed in one location:

def getLibVersionName() {
    return "0.11.0"
}

To upload the items to Bintray, run the command line

./gradlew install bintrayUpload

Note: there are many errors that you can encounter if there is a configuration problem or if the files have already been uploaded.

Advertisements