7/20/2016 - 10:43 AM

Android Library Publishing Maven Artifacts via gradle

Android Library Publishing Maven Artifacts via gradle

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

def isReleaseBuild() {
    return !VERSION_NAME.contains("SNAPSHOT");

def getReleaseRepositoryUrl() {
    println "Reading Maven repository Release URL from 'RELEASE_REPOSITORY_URL'"
    if (hasProperty('RELEASE_REPOSITORY_URL')) {
    throw new InvalidUserDataException("RELEASE_REPOSITORY_URL is not defined");

def getSnapshotRepositoryUrl() {
    println "Reading Maven repository Snapshot URL from 'SNAPSHOT_REPOSITORY_URL'"
    if (hasProperty('SNAPSHOT_REPOSITORY_URL')) {
    throw new InvalidUserDataException("SNAPSHOT_REPOSITORY_URL is not defined");

def getRepositoryUsername() {
    println "Reading Maven repository username from 'mavenRepositoryUsername'"
    if (hasProperty('mavenRepositoryUsername')) {
        return mavenRepositoryUsername;
    throw new InvalidUserDataException("mavenRepositoryUsername is not defined, check your user ~/.gradle/ file");

def getRepositoryPassword() {
    println "Reading Maven repository password from 'mavenRepositoryPassword'"
    if (hasProperty('mavenRepositoryPassword')) {
        return mavenRepositoryPassword;
    throw new InvalidUserDataException("mavenRepositoryPassword is not defined, check your user ~/.gradle/ file");

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) {
        // execute only if I'm publishing on maven
        onlyIf { gradle.taskGraph.hasTask(uploadArchives) }

        // all the sources of the current module
        source =
        // the Android SDK classpath
        classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
        // all the dependencies classpaths
        classpath += configurations.compile

        // Honestly I do not remember why it's a good idea to exclude these
        exclude '**/BuildConfig.class'
        exclude '**/R.class'
        exclude '**/R$*.class'

        options {
            // Java reference

            // dependencies API references (I should probably move these in the project or something)

            // Android reference is not standard javadoc so I need to use offline directory
            linksOffline("", "${android.sdkDirectory}/docs/reference")

            // Java 8 javadoc is more strict, This disable that strictness
            if (JavaVersion.current().isJava8Compatible()) {
                addStringOption('Xdoclint:none', '-quiet')
        // uncomment to avoid failing the build if javadoc fails
//        failOnError false

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

    task androidSourcesJar(type: Jar) {
        classifier = 'sources'

    artifacts {
        archives androidSourcesJar
        archives androidJavadocsJar

What is this

This gitst contains a script to push Android libraries as artifacts on a maven repository using the gradle build system.

It is somewhate a fork of Chris Banes gradle push script.

This was me while trying to understand how to setup maven publishing with gradle:

Documentation is absent or very lacking and I found no script handling javadoc properly for Android. When I figured it out I decided to write this.

This script is not thought for libraries with variants.


  1. Copy the maven_push_library.gradle in your repository root.

  2. set these properties in your project file:


this assume the group and version name are the same for all your modules; feel free to override them in each module file

  1. set these properties in each module file:

  2. set these properties in your USER ~/.gradle/ file:

  3. add this to your root project build.gradle script file:

     subprojects {
         group = GROUP
         version = VERSION_NAME

this is needed for dependencies between modules. You can also set it for each module

  1. add this line at the bottom of the Android library modules you want to publish:

     apply from: '../maven_push_library.gradle'


You need to sign your artifacts if you need/want to deploy your modules in a public maven repository (mavenCentral, jCenter, ...).

I never needed it because I publish my company modules in a private repository, there are detailed instruction on how to setup for signing here.

Basically you need to create a key file using gpg, then set it up to sign your artifacts. This is a security measure to make sure no one else can release stuff on your behalf, provided you keep the key safely.

Publishing on AWS S3

I've experimented a little in using Amazon S3 as maven server.

To do so you need to add this to your maven_push_library.gradle file:

configurations {

dependencies {
    mavenWagons ''

afterEvaluate { project ->
    uploadArchives {
        repositories {
            mavenDeployer {
                configuration = configurations.mavenWagons
                // keep whats here

This tell gradle maven plugin script to use a different wagon to publish on maven, specifically the aws-maven wagon.

Then you have to change your REPO Urls to something like:


Be carefule tough: the aws-maven wagon is a bit outdated and does not know about some new AWS Regions (example: Frankfurt - eu-central-1) and will fail if your bucket is not in one of the supported regions.

To setup the S3 repository you just need to create a bucket, a IAM user that can write and read from that bucket and set the AWS Access Key as username and the AWS Secret Key as password. I'm not going into details here cause this is basic AWS knowledge you can find anywhere.

Playing with IAM Roles and Groups you can also manage to get some manual user management.

Other resources

Check out Square maven push script.

Have a look at this guide on how to publish on jcenter.

To setup AWS S3 for maven there are different guides: 1, 2. Many fail in suggesting the policy for the S3 user which is missing a non-intuitive permission.

What about the new maven-publish plugin?

At some point gradle introduced a new maven-publish plugin that is meant to replace the old maven plugin.

I found very few scripts for android using this new plugin.

None say anything about the Javadoc artifact generation or more complex behavior. Furthermore I've read there are issues with the dependencies generation in the pom.xml.

The documentation is very lacking for both maven and maven-publish plugin on Android so I'll stick on the most used one for now.