Publish an aar file to Maven Central with Gradle

In the last days I tried to publish ChangeLog Lib as aar(Android Archive) to Maven Central.
First of all, I am a newbie in Gradle and Maven.I always used repo as a final user, so there could be better solutions.

My first step was to find an approved repository.
I decided to use the Sonatype OSS Repository, which is an approved repository provided by Sonatype.

1. Register your project at Sonatype
It is easy. You can use the official guide.
You have to follow the 2nd and 3th section.
In this way you can create your user, and your project.

When you create your project, pay attention to groupId. It is very important.
Here you can find a some tips about it.
If you don't own a domain, you can choose a groupId that reflects your project hosting, something like com.github.gabrielemariotti.


You can't use it immediately; Sonatype have to prepare repo and normally it takes 1-2 business days.

Then you can write your gradle scripts to upload aar file.

2. Gradle script maven_push.gradle
I used Chris Banes code. You can read this blog post about it. Thanks Chris!

In this script you:
  • Apply the maven and signing plugins
    apply plugin: 'maven'
    apply plugin: 'signing'
    
  • Specify the group and version of your project through a gradle.properties file
  • Define tasks for source and javadoc generation, and your artifacts
  • Configure the signing task
        signing {
            required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
            sign configurations.archives
        }
    
  • Configure Repository Urls for realeases and snapshots
    if (isReleaseBuild()) {
        println 'RELEASE BUILD'
        sonatypeRepositoryUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
    } else {
        println 'DEBUG BUILD'
        sonatypeRepositoryUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
    }
    

Pay attention.
Sources and Javadoc are required! If you can't provide -sources.jar or -javadoc.jar, make fake -sources.jar or -javadoc.jar.

3. Gradle.properties
The script above uses a gradle.properties file where you can insert all info. In this way your script is clean and you can use it in other project.
VERSION_NAME=1.2.1-SNAPSHOT
VERSION_CODE=3
GROUP=com.github.gabrielemariotti.changeloglib

POM_DESCRIPTION=Android Library to display your changelog
POM_URL=https://github.com/gabrielemariotti/changeloglib
POM_SCM_URL=https://github.com/gabrielemariotti/changeloglib
POM_SCM_CONNECTION=scm:git@github.com:gabrielemariotti/changeloglib.git
POM_SCM_DEV_CONNECTION=scm:git@github.com:gabrielemariotti/changeloglib.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=gabrielemariotti
POM_DEVELOPER_NAME=Gabriele Mariotti
4. Modify your top-level build.gradle
in this file you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:0.5.+'
    }
}

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

allprojects {
    version = VERSION_NAME
    group = GROUP

    repositories {
        mavenCentral()
    }
}

apply plugin: 'android-reporting'
It is a personal choise to use SNAPSHOT word in version name to differentiate a release version from a snapshot version.
In maven_push.gradle script I used different repo url for snapshots and releases.

Don't worry about deploying too many snapshots.
From official doc:
Nexus server has a scheduled task running weekly for cleaning up old snapshots. Snapshots older than 15 days will be deleted while a 5 minimum will always be kept. If a version is released, then all snapshots of this version will be removed.

Here you can use your logic. You have to modify isReleaseBuild() function.

5. gradle.properties and build.gradle in each module
For each module or application you want to upload to central, you should:
  • provide a gradle.propeties
    where you can provide the name and the format of your artifact:
    POM_NAME=ChangeLog Library
    POM_ARTIFACT_ID=library
    POM_PACKAGING=aar
    
  • modify build.gradle to add the following line at the end:
    apply from: '../maven_push.gradle'
    

6. Signing your artifacts!
It is very important!
To be able to upload a file in repo you have to provide PGP signatures for all your artifacts (all files except checksums), and distribute your public key to a key server like http://pgp.mit.edu or hkp://pool.sks-keyservers.net .
Note: Public keys are synced among key servers, but it may take a while.
Read How to Generate PGP Signatures with Maven for more information.
Pay attention to the password. Don't forget it!

Now you have to use these keys!
The beforeDeployment line in gradle script will sign the files before the artifacts are deployed to the Sonatype OSS repository.

I used my ~/.gradle/gradle.properties file to store info about key and about username/password to login in Sonatype repo.(in Win you can find it in: C:\Users\myusername\.gradle)
signing.keyId=xxxxxxx
signing.password=YourPublicKeyPassword
signing.secretKeyRingFile=~/.gnupg/secring.gpg
 
nexusUsername=YourSonatypeJiraUsername
nexusPassword=YourSonatypeJiraPassword
This file will be used by script, to sign your artifacts and to login in Sonatype repo.
The xxxxx keyId value can be retrieve with cmd: gpg --list-keys (see this section)

7. Run the build using the uploadArchives task.
You can use a cmd line:
$ gradle uploadArchives
or you can use your Android Studio IDE to launch this command (you can find it the Gradle tasks).

8. Comment on the OSSRH JIRA
The first time you promote a release, you need to comment on the OSSRH JIRA ticket you created.


PS. You can use the VERSION_NAME and VERSION_CODE defined in gradle.properties in your build.gradle in this way:
android {

    defaultConfig {
        minSdkVersion X
        targetSdkVersion XX
        versionName project.VERSION_NAME
        versionCode Integer.parseInt(project.VERSION_CODE)
    }
}

Popular posts from this blog

Expand and collapse animation

Android-5: Card and images with rounded corners in Android 4

How to centralize the support libraries dependencies in gradle