Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Gradle script for publishing Android library with sources and javadoc to Maven repository using maven-publish plugin.
// You can use maven-publish-helper.gradle script without changes and even share it between multiple
// modules. Just place the maven-publish-helper.gradle file in the root directory of your project,
// then apply it at the bottom of your module's build.gradle file like this:
// ...content of module's build.gradle file...
apply from: '../maven-publish-helper.gradle'
publishing {
publications {
release(MavenPublication) {
// Specify own groupId as package name of your library,
// otherwise it would just use project's name (=name of the root directory) by default.
groupId 'com.example'
// Specify custom artifactId if needed,
// otherwise it would use module's name by default.
//artifactId 'custom-artifact'
// You can specify custom version,
// otherwise it would use version from `android { defaultConfig { ... } }` by default.
//version = '1.0'
}
}
}
/**
* Maven Publish Helper
*
* Requires Android Gradle plugin 3.6.0 or higher (available since Android Studio 3.6).
* See also: https://developer.android.com/studio/build/maven-publish-plugin
*
* @Author Robert Pösel
* @Version 1.5
* @Date 3.3.2020
*/
apply plugin: 'maven-publish'
task androidJavadocs(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
android.libraryVariants.all { variant ->
if (variant.name == 'release') {
owner.classpath += variant.javaCompileProvider.get().classpath
}
}
exclude '**/R.html', '**/R.*.html', '**/index.html'
}
task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
archiveClassifier.set('javadoc')
from androidJavadocs.destinationDir
}
task androidSourcesJar(type: Jar) {
archiveClassifier.set('sources')
from android.sourceSets.main.java.srcDirs
}
// Because the components are created only during the afterEvaluate phase, you must
// configure your publications using the afterEvaluate() lifecycle method.
afterEvaluate {
publishing {
publications {
// Creates a Maven publication called "release".
release(MavenPublication) {
// Applies the component for the release build variant.
from components.release
// Adds javadocs and sources as separate jars.
artifact androidJavadocsJar
artifact androidSourcesJar
// You can customize attributes of the publication here or in module's build.gradle file.
//groupId = 'com.example'
//artifactId = 'custom-artifact'
version = android.defaultConfig.versionName // or just '1.0'
}
}
}
}
@gsavvid
Copy link

gsavvid commented Jun 28, 2019

WARNING: API 'variant.getJavaCompile()' is obsolete and has been replaced with 'variant.getJavaCompileProvider()'.
It will be removed at the end of 2019.
For more information, see https://d.android.com/r/tools/task-configuration-avoidance.
To determine what is calling variant.getJavaCompile(), use -Pandroid.debug.obsoleteApi=true on the command line to display a stack trace.

However, variant.getJavaCompileProvider() doesn't seem to have a property classpath.

@Robyer
Copy link
Author

Robyer commented Jun 28, 2019

I just updated the script with changes:

  1. Wrapping into publishing{} block as yanchenko suggested.
  2. Fixed use of the obsolete variant.getJavaCompile()
  3. Fixed issue with printing exclusion rules as someone mentioned on StackOverflow

@gsavvid: You can use the updated version.

@gsavvid
Copy link

gsavvid commented Jul 7, 2019

@Robyer thanks that's fixed now. Are you planning to configure the script to export Kotlin Javadoc? Eg. using Dokka?

@Robyer
Copy link
Author

Robyer commented Jul 8, 2019

@gsavvid: No, I'm not even using Kotlin myself.

@gsavvid
Copy link

gsavvid commented Jul 9, 2019

Fair enough. I forked it and updated it in order to use Dokka for generating Kotlin Javadoc (aka KDoc) and also to use com.jfrog.bintray plugin for uploading to Bintray. I'll try to keep it up-to-date with whatever changes are made to the original one, here.

If anyone wants to check out my version, it's here: https://gist.github.com/gsavvid/f7ffe00d846a50de7490c2ecbd7b4169.

Thanks a lot by the way. This has been very helpful.

@matpag
Copy link

matpag commented Aug 22, 2019

With latest AGP 3.5.0 and Gradle 5.4.1 I have a warning at line #13 indicating: Access to 'classpath' exceeds its access rights

@btdrucke
Copy link

btdrucke commented Oct 26, 2019

I am using gradle 5.6.2 and for this version, classifier = 'sources' should be archiveClassifier.set('sources').

@ellykits
Copy link

ellykits commented Dec 3, 2019

Thanks for this Script I was able to tweak it a bit and use it for publishing Android Library to GitHub Package Registry. (The dependencies were missing initially)

@Robyer
Copy link
Author

Robyer commented Feb 25, 2020

New Android Studio 3.6 with Android Gradle Plugin 3.6.0 has now support for Maven Publish Plugin. This script is probably not needed anymore.
https://developer.android.com/studio/build/maven-publish-plugin

@tprochazka
Copy link

tprochazka commented Feb 27, 2020

I already tried to use build-in support instead of https://github.com/wupdigital/android-maven-publish and it was not working for me, but maybe I did something wrong. Has anybody success with it already?

@iqorqua
Copy link

iqorqua commented Mar 3, 2020

Hello! I made android library and i need to asseble it into .aar with all sources and docs. I tryed a lot of ways, but new project cant see the sources. When i opened my lib as archive i can see .kt files inside classes.jar. Also sources are present inside of libs folder as .jar file. When i open .aar package inside Android Studo, i can see my classes and its source, but navigation with Ctrl+click references to compiled .class file instead of source .kt file.
After gradle updating to 3.6.0 result is the same.
Can someone help me? :)

@Robyer
Copy link
Author

Robyer commented Mar 3, 2020

I updated the script for use in Android Studio 3.6. We don't need to handle the XML ourselves anymore as new Android Gradle plugin 3.6.0 will handle that itself. We still need to handle javadocs and sources manually, though.

I added also example usage how to easily (re-)use the script in multiple modules without copying and changing the script file.

@iqorqua I don't know how it works with Kotlin source files, but with Java source files in AAR created with this script the sources are recognized and used correctly.

@mochadwi
Copy link

mochadwi commented Apr 10, 2020

really appreciate and thanks @Robyer, as previouly stated from you:

New Android Studio 3.6 with Android Gradle Plugin 3.6.0 has now support for Maven Publish Plugin. This script is probably not needed anymore.
https://developer.android.com/studio/build/maven-publish-plugin

You also updated it the script, I'm a little curious, do you have a full open source/project in the github/somewhere?

This block of lines:

artifact bundleDistributable {
    classifier ""
}

Encountered below issue in my project:

A problem occurred evaluating project ':app'.
> Could not find method bundleDistributable() for arguments [build_a1v67a779r9u4vrutskt4b88d$_run_closure3$_closure9$_closure11$_closure12@3c5f1e] on object of type org.gradle.api.publish.maven.internal.publication.DefaultMavenPublication.

Any ideas what suggestion for me, to solve the issue? Please let me know if you need more information

EDITED:

I've made a mistake asking the question, here, in fact I'm using the old scripts provided from https://alessiobianchi.eu/blog/obfuscated-aar-local-maven/ instead of the gist provided here.

@Robyer
Copy link
Author

Robyer commented Apr 11, 2020

@mochadwi I'm not sure you still need the answer, but I am using my script (at the moment it's old version) in this project: https://github.com/adaptech-cz/Tesseract4Android

@zhitaocai
Copy link

zhitaocai commented Apr 23, 2020

Great! Thanks~

@spyhunter99
Copy link

spyhunter99 commented Apr 25, 2020

this doesn't seem to do the gpg signing, hashes, sources, or javadoc jars that are required for publishing to sonatype. Or am i missing something?

@Robyer
Copy link
Author

Robyer commented Apr 25, 2020

@spyhunter99 It creates sources and javadoc jars, but it doesn't do gpg signing or hashes. You can probably add that easily if you know how to work with Gradle, but I have no experience with Sonatype (in repository above I am using Bintray), so I can't help you with that.

@cyb3rko
Copy link

cyb3rko commented Jul 18, 2020

First of all thanks for this gist.
I have now implemented your templates and adjusted them to my project, but how do I then set description etc. and upload my project to Bintray?

Thanks!

@Robyer
Copy link
Author

Robyer commented Jul 19, 2020

@cyb3rko Hi, you can look at this config file, I am using older version of my gist there, but the Bintray part at the bottom is what is important for you: https://github.com/adaptech-cz/Tesseract4Android/blob/d03bd5fc063d3f34cefd1d48481da38421970136/publish.gradle#L99-L136

EDIT: Oh, and also these lines too: https://github.com/adaptech-cz/Tesseract4Android/blob/d03bd5fc063d3f34cefd1d48481da38421970136/publish.gradle#L53-L58

@ashu8826
Copy link

ashu8826 commented Dec 4, 2020

@Robyer
I am getting following error on line -- from components.release
Could not get unknown property 'release' for SoftwareComponentInternal set of type org.gradle.api.internal.component.DefaultSoftwareComponentContainer.

I don't need javadocs so I have not added any other artifact.
my library have buildType { release {...} } and using latest Android gradle plugin

What I am doing wrong?

EDIT:
Oops: I had also defined build Flavour, forgot to add that
Below worked for me because my build flavour is named "fat"
from components.fatRelease

@Hesowcharov
Copy link

Hesowcharov commented Dec 29, 2020

@Robyer, thanks, mate! You helped me a lot! 👍

Copy link

ghost commented Dec 31, 2020

When I do as per instructions I get Extension not initialized yet, couldn't access compileSdkVersion. error!

@Robyer
Copy link
Author

Robyer commented Dec 31, 2020

@realchandan Maybe you are using some incompatible version of Gradle plugin or other library? I am using it with stable Android Studio with Java codebase. You can try to use it in new empty project.

@ivangarza6
Copy link

ivangarza6 commented Jan 26, 2021

@Robyer I"m having trouble keeping my JNI and native lib dependencies inside my AAR. I suspect the pom file requires me to specify then? I could really use some help!

@Robyer
Copy link
Author

Robyer commented Jan 26, 2021

@ivangarza6 I think you should ask question on StackOverflow instead, I don't have experience with specifying native lib dependencies. I'm not even sure whether Android Studio / Gradle currently supports them.

@Robyer
Copy link
Author

Robyer commented Mar 29, 2021

@Petrakeas You need to first publish the moduleB with this script as one aar. Then you need to modify the moduleA's build.gradle and reference that moduleB from repository (e.g. as implementation 'com.example:moduleB:1.0.0' instead of implementation project(':moduleB')) and publish it as second aar (moduleA). This way reference to moduleB will be saved in the moduleA's *.pom file and Gradle will automatically download this dependency when downloading moduleA from the repository.

@Petrakeas
Copy link

Petrakeas commented Mar 29, 2021

@Petrakeas You need to first publish the moduleB with this script as one aar. Then you need to modify the moduleA's build.gradle and reference that moduleB from repository (e.g. as implementation 'com.example:moduleB:1.0.0' instead of implementation project(':moduleB')) and publish it as second aar (moduleA). This way reference to moduleB will be saved in the moduleA's *.pom file and Gradle will automatically download this dependency when downloading moduleA from the repository.

Thanks Robyer. I actually deleted by question (before you answered), because I noticed that when I had both modules configured for publishing with the proposed script, the maven-publish plugin worked automatically. It seems that maven-publish plugin was smart enough to replace the dependancy with one referencing maven. It even picked-up my custom artifactId that was different to the actual module name!

@Robyer
Copy link
Author

Robyer commented Mar 29, 2021

@Petrakeas I noticed that when I had both modules configured for publishing with the proposed script, the maven-publish plugin worked automatically. It seems that maven-publish plugin was smart enough to replace the dependancy with one referencing maven. It even picked-up my custom artifactId that was different to the actual module name!

Thanks for interesting info! I didn't know that and it sounds great.

@Petrakeas
Copy link

Petrakeas commented Apr 22, 2021

In case it helps someone, I have made some changes that enable correct UTF-8 Javadoc generation, repeatable builds and support for Java and Android Gradle plugin. I have created a guide here.

@Robyer
Copy link
Author

Robyer commented Mar 1, 2022

With Android Gradle Plugin 7.1 it is now very simple to do this without needing any complicated scripts. AGP now also handles creating source and javadocs jar.

You don't need any separate scripts, just write everything into your build.gradle file of your module:

plugins {
    ...
    id 'maven-publish'
}
android {
    ...
    publishing {
        singleVariant("release") {
            // if you don't want sources/javadoc, remove these lines
            withSourcesJar()
            withJavadocJar()
        }
    }
}
afterEvaluate {
    publishing {
        publications {
            release(MavenPublication) {
                from components.release
                groupId 'com.example'
                artifactId 'mylibrary'
                version = android.defaultConfig.versionName // or manually '1.0'
            }
        }
    }
}

See also: https://developer.android.google.cn/studio/build/maven-publish-plugin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment