I'm using the maven-publish plugin to publish an aar file to a maven repository. However I noticed that compile dependencies are not added to the pom.xml even after I add the transitive property. I'm using com.android.tools.build:gradle:1.1.3
Any hints on how to resolve this ?
build.gradle
publishing {
publications {
sdkAar(MavenPublication) {
artifacts {
groupId 'com.test'
artifactId 'my_sdk'
version currentVersion
artifact 'build/outputs/aar/release.aar'
artifact androidJavadocsJar {
classifier "javadoc"
}
}
}
sdkJar(MavenPublication) {
groupId 'com.test'
artifactId 'my_sdk_jar'
version currentVersion
artifact 'build/libs/release.jar'
artifact androidJavadocsJar {
classifier "javadoc"
}
}
}
repositories {
maven {
credentials {
username archiva_username
password archiva_password
}
}
}
}
Thanks in Advance
If you want the dependencies to be added automatically to the POM, you need to use the components feature. Here's an example from the user guide:
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}
That from ... is important. What I don't know is whether the Android plugin sets up its own software components. I can't see any references to such things.
Remember that the new publishing mechanism is currently incubating, and perhaps that's why the Android plugin doesn't offer any direct support for it at the moment.
If you really want to use the publishing plugin, you can grab the runtime dependencies of your artifacts and manually add them to the POM using the syntax described in the user guide. I wouldn't recommend that approach though as it's messy and looks error prone.
dependency not added automatically you need to add publishing tag.
publishing {
publications {
aar(MavenPublication) {
groupId libraryGroupId
version = libraryVersion
artifactId libraryArtifactId
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
pom.withXml {
def dependencies = asNode().appendNode('dependencies')
configurations.getByName("_releaseCompile").getResolvedConfiguration().getFirstLevelModuleDependencies().each {
def dependency = dependencies.appendNode('dependency')
dependency.appendNode('groupId', it.moduleGroup)
dependency.appendNode('artifactId', it.moduleName)
dependency.appendNode('version', it.moduleVersion)
}
}
}
}
please try this code, I tried it successfully.
//generate pom nodes for dependencies
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.implementation.allDependencies.each { dependency ->
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', dependency.group)
dependencyNode.appendNode('artifactId', dependency.name)
dependencyNode.appendNode('version', dependency.version)
}
}
Related
When you want to publish your library, there are two ways to do it.
Using artifact()
publishing {
publications {
aar(MavenPublication) {
groupId packageName
version = libraryVersion
artifactId project.getName()
// Tell maven to prepare the generated "*.aar" file for publishing
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
pom.withXml {
def dependencies = asNode().appendNode('dependencies')
configurations.getByName("_releaseCompile").getResolvedConfiguration().getFirstLevelModuleDependencies().each {
def dependency = dependencies.appendNode('dependency')
dependency.appendNode('groupId', it.moduleGroup)
dependency.appendNode('artifactId', it.moduleName)
dependency.appendNode('version', it.moduleVersion)
}
}
}
}
}
Using components:
afterEvaluate {
publishing {
publications {
release(MavenPublication) {
groupId = "com.app.core"
artifactId = project.name
version = "1.0.1"
from components.release
}
}
artifactoryPublish {
publications(publishing.publications.release)
}
}
}
I read some blog posts and they mention that pom.withXml needs to be included in order to include the transitive dependencies. i.e if your library uses a third party dependency, then it will not included if you don't use the pom.withXml section and app will crash on runtime.
When you use components definition, it automatically includes the transitive dependencies. I couldn't find any documentation on usage of these APIs. What is actually the components definition is doing? What is the difference between using components and artifact definitions?
I'm using jFrog artifactory to publish an Android Library. The library is getting published fine. But when I try to use it, the gradle dependencies of the library are not loading up.
My pom.xml already has those dependencies.
My library has two modules -
-app
-secondarymod
And this is my code in main project level build.gradle -
artifactoryPublish.skip = true
project('app') {
artifactoryPublish.dependsOn('build')
publishing {
publications {
aar(MavenPublication) {
groupId = "in.mikkel.mainapp"
artifactId = project.getName()
version = "1.0.24"
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
pom.withXml {
def dependencies = asNode().appendNode("dependencies")
configurations.implementation.allDependencies.each {
def dependency = dependencies.appendNode("dependency")
print(it.group)
dependency.appendNode("groupId", it.group)
dependency.appendNode("artifactId", it.name)
dependency.appendNode("version", it.version)
}
}
}
}
}
artifactoryPublish {
publications(publishing.publications.aar)
}
}
project('secondarymod') {
artifactoryPublish.dependsOn('build')
publishing {
publications {
aar(MavenPublication) {
groupId = "in.mikkel.mainapp"
artifactId = project.getName()
version = "1.0.24"
// Tell maven to prepare the generated "*.aar" file for publishing
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
pom.withXml {
def dependencies = asNode().appendNode("dependencies")
configurations.implementation.allDependencies.each {
def dependency = dependencies.appendNode("dependency")
print(it.group)
dependency.appendNode("groupId", it.group)
dependency.appendNode("artifactId", it.name)
dependency.appendNode("version", it.version)
}
}
}
}
}
artifactoryPublish {
publications(publishing.publications.aar)
}
}
artifactory {
contextUrl = 'https://mikkel.jfrog.io/artifactory'
publish {
repository {
repoKey = 'mikkelcl-gradle-release-local'
username = "***"
password = "***"
}
defaults {
publications('aar')
publishArtifacts = true
publishPom = true
}
}
}
Can anyone tell me what's wrong?
Generally speaking, in the package managers world, dependencies are never published. Only Artifacts does. The dependencies should be downloaded in the CI in the same way you download them in your local machine.
If the dependencies are your private code, you should build and publish them separately.
Otherwise, you should configure the dependencies repository on your build.gradle file. In that case, please make sure that the repository is configured in the repositories clause.
Read more about Declaring repositories in Gradle here.
UPDATE2: I was not generating a aar file, now it's included in the package that you can check here: https://github.com/fabrizioiacobucci/range-bar-preference/packages/787218
I see javadoc, sources and aar are there, but when I add the package as dependency in another project I don't even see it in the External Libraries.
UPDATE: This is the problem, I don't see my source files in the downloaded jar:
I recently forked a little project on Github and migrated its old code version to AndroidX and new gradle build.
After some time everything work fine and I was able also to publish the library on Git packages.
However, I tried to declare it as dependency on a different project on my local computer. It downloads fine but when I try to import it in a source file, I cannot find the package:
If I go into the project folder I see the library downloaded and related files.
This is the Project build.gradle file of the published library.
build.gradle (project)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.0'
classpath 'io.github.gradle-nexus:publish-plugin:1.1.0'
}
}
plugins {
id 'maven-publish'
}
apply from: "${rootDir}/scripts/publish-root.gradle"
apply plugin: 'io.github.gradle-nexus.publish-plugin'
ext {
VERSION = '1.0.0'
DESCRIPTION = 'A range bar that can be used as an android shared preference'
GROUPID = 'com.fabrizioiacobucci.android'
ARTIFACTID = 'range-bar-preference'
GITREPO = 'https://github.com/fabrizioiacobucci/tree/development/range-bar-preference.git'
PROJECTURL = 'https://github.com/fabrizioiacobucci/tree/development/range-bar-preference'
PUBLISHGIT = 1
PUBLISHMAVEN = 0
}
nexusPublishing {
repositories {
sonatype {
stagingProfileId = '1c4ab2dc896731'
//packageGroup = "com.fabrizioiacobucci.android"
username = ossrhUsername
password = ossrhPassword
nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"))
snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
}
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
build.gradle (module)
apply plugin: 'com.android.library'
android {
compileSdkVersion 30
buildToolsVersion '31.0.0 rc3'
defaultConfig {
minSdkVersion 14
targetSdkVersion 30
version VERSION
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
versionCode 1
versionName VERSION
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
testOptions {
unitTests {
includeAndroidResources = true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test:rules:1.3.0'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.legacy:legacy-preference-v14:1.0.0'
implementation 'com.appyvet:materialrangebar:1.3'
implementation 'androidx.appcompat:appcompat:1.2.0'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.robolectric:robolectric:4.5.1'
}
apply from: "${rootDir}/scripts/publish-module-maven.gradle"
apply from: "${rootDir}/scripts/publish-module-githubpkg.gradle"
publish-module-maven.gradle
apply plugin: 'maven-publish'
apply plugin: 'signing'
task androidSourcesJar(type: Jar) {
archiveClassifier.set('sources')
from android.sourceSets.main.java.srcDirs
}
task javadoc(type: Javadoc) {
failOnError false
source = android.sourceSets.main.java.srcDirs
classpath = configurations.compile
}
task javadocJar(type: Jar, dependsOn: javadoc) {
archiveClassifier.set('javadoc')
from javadoc.destinationDir
}
artifacts {
archives androidSourcesJar
archives javadocJar
}
afterEvaluate {
publishing {
publications {
release(MavenPublication) {
// The coordinates of the library, being set from variables that
// we'll set up later
groupId GROUPID
artifactId ARTIFACTID
version VERSION
artifact("$buildDir/outputs/aar/range-bar-preference-release.aar")
artifact androidSourcesJar
artifact javadocJar
// Mostly self-explanatory metadata
pom {
name = 'Range Bar Preference'
description = 'A range bar that can be used as an android shared preference'
url = PROJECTURL
groupId GROUPID
licenses {
license {
name = 'The Apache Software License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
distribution = 'repo'
}
}
developers {
developer {
id = 'FabrizioIacobucci'
name = 'Fabrizio Iacobucci'
email = 'fabrizio.iacobucci90#mail.com'
}
}
scm {
connection = 'scm:git:github.com/fabrizioiacobucci/range-bar-preference.git'
developerConnection = 'scm:git:ssh://github.com/fabrizioiacobucci/range-bar-preference.git'
url = 'https://github.com/fabrizioiacobucci/range-bar-preference/'
}
}
}
}
}
}
ext["signing.keyId"] = rootProject.ext["signing.keyId"]
ext["signing.password"] = rootProject.ext["signing.password"]
ext["signing.secretKeyRingFile"] = rootProject.ext["signing.secretKeyRingFile"]
signing {
sign publishing.publications
}
publish-module-githubpkg.gradle
artifacts {
archives androidSourcesJar
archives javadocJar
}
project.publishing {
publications {
maven(MavenPublication) {
groupId = GROUPID
artifactId = ARTIFACTID
version = VERSION
artifact("$buildDir/outputs/aar/range-bar-preference-release.aar")
artifact androidSourcesJar
artifact javadocJar
versionMapping {
usage('java-api') {
fromResolutionOf('runtimeClasspath')
}
usage('java-runtime') {
fromResolutionResult()
}
}
pom {
name = 'Range Bar Preference'
packaging = 'aar'
description = 'A range bar that can be used as an android shared preference'
url = PROJECTURL
licenses {
license {
name = 'The Apache Software License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
distribution = 'repo'
}
}
developers {
developer {
id = 'FabrizioIacobucci'
name = 'Fabrizio Iacobucci'
email = 'fabrizio.iacobucci90#mail.com'
}
}
scm {
connection = 'scm:git:github.com/fabrizioiacobucci/range-bar-preference/range-bar-preference.git'
developerConnection = 'scm:git:ssh://github.com/fabrizioiacobucci/range-bar-preference/range-bar-preference.git'
url = 'https://github.com/fabrizioiacobucci/range-bar-preference/'
}
}
}
}
repositories {
maven {
name = "GitHubPackages"
url = uri('https://maven.pkg.github.com/fabrizioiacobucci/range-bar-preference')
credentials {
username = System.getenv("GITHUB_USER")
password = System.getenv("GITHUB_TOKEN")
}
}
}
}
I don't know if there is anything else relevant to share, please let me know in case.
Do you have any idea what am I missing?
Thanks a lot in advance for any help.
As promised I forked the original project upgraded to android and then all the dependencies to the latest.
For the fast release of SDK to do the POC, I released it to jitpack.io
How to add the new library as a dependency.
Add it in your root build.gradle at the end of repositories:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
Add this to your app module dependencies:
dependencies {
implementation 'com.github.dk19121991:range-bar-preference:0.0.7'
}
I did try it myself and it's working fine for me, I updated the app module in my forked version to use the library from jitpack only, and it's working smoothly.
Please try the library and let me know if you feel anything else you need.
https://github.com/dk19121991/range-bar-preference
import com.nfx.android.rangebarpreference
change fabrizioiacobucci to nfx will solve your poblem
i have a android project with kotlin, it includes a library module, i would like to upload this library to jfrog artifactory. i have uploaded an aar file to artifactory successfully. now i would like to upload library-sources.jar to artifactory. But when i execute gradle task artifactoryPublish, it will generate two pom-default.xml files, and publish one of them randomly.
Project build.gradle
buildscript {
ext.kotlin_version = "1.4.30"
repositories {
maven {
url "http://localhost:8081/artifactory/my_virtual_repo/"
}
}
dependencies {
classpath "com.android.tools.build:gradle:4.1.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.15.2"
}
}
allprojects {
repositories {
maven {
url "http://localhost:8081/artifactory/my_virtual_repo/"
}
}
}
library build.gradle
......
apply plugin: "com.jfrog.artifactory"
apply plugin: "maven-publish"
def MAVEN_LOCAL_PATH = "http://localhost:8081/artifactory"
def GROUP_ID = "com.xxx.artifactlib"
def ARTIFACT_ID = "artifactlib"
def VERSION_NAME = "1.3"
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
task sourcesJar(type: Jar) {
group = 'jar'
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
artifacts {
archives sourcesJar
}
publishing {
publications {
mavenJava(MavenPublication) {
groupId = GROUP_ID
artifactId = ARTIFACT_ID
version = VERSION_NAME
artifact tasks.sourcesJar
pom.withXml {
def dependencies = asNode().appendNode("dependencies")
configurations.api.allDependencies.each {
def dependency = dependencies.appendNode("dependency")
print(it.group)
dependency.appendNode("groupId", it.group)
dependency.appendNode("artifactId", it.name)
dependency.appendNode("version", it.version)
}
}
}
}
publications {
aar_pub(MavenPublication) {
groupId = GROUP_ID
artifactId = ARTIFACT_ID
version = VERSION_NAME
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
pom.withXml {
def dependencies = asNode().appendNode("dependencies")
configurations.api.allDependencies.each {
def dependency = dependencies.appendNode("dependency")
dependency.appendNode("groupId", it.group)
dependency.appendNode("artifactId", it.name)
dependency.appendNode("version", it.version)
}
}
}
}
}
artifactoryPublish {
contextUrl = MAVEN_LOCAL_PATH
publications("mavenJava", "aar_pub")
clientConfig.publisher.repoKey = "my_local_repo"
clientConfig.publisher.username = "xxx"
clientConfig.publisher.password = "xxx"
}
......
pom-default.xml of aar_pub
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.xxx.artifactlib</groupId>
<artifactId>artifactlib</artifactId>
<version>1.3</version>
<packaging>aar</packaging>
<dependencies/>
</project>
pom-default.xml of mavenJava
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.xxx.artifactlib</groupId>
<artifactId>artifactlib</artifactId>
<version>1.3</version>
<packaging>pom</packaging>
<dependencies/>
</project>
how to upload a given pom file(like pom-default of aar_pub)? thank you.
A single Publication contains all artifacts for a single release.
You defined two identical Publications (well, both have the aar and pom, only one of them has sources JAR) and are trying to upload both of them to the same coordinates at the same time.
Don't define one Publication for each of aar, jar, pom, whatever.
Merge all articacts into a single Publication.
In your case:
publishing {
publications {
mavenJava(MavenPublication) {
groupId = GROUP_ID
artifactId = ARTIFACT_ID
version = VERSION_NAME
artifact tasks.sourcesJar
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
pom.withXml {
def dependencies = asNode().appendNode("dependencies")
configurations.api.allDependencies.each {
def dependency = dependencies.appendNode("dependency")
print(it.group)
dependency.appendNode("groupId", it.group)
dependency.appendNode("artifactId", it.name)
dependency.appendNode("version", it.version)
}
}
}
}
}
artifactoryPublish {
publications("mavenJava")
}
Potential issues
There's no formal relationship between the publication and whatever task that produces the AAR. You'll have to manually execute assemble before publish. (And remember to do that every time.)
Consider migrating to Android Gradle Plugin 3.6.0 or newer which supports maven-publish plugin natively. See documentation. This has the following benefits:
You don't have to manually write dependencies to POM.
Whenever AAR would change the publication would pick it up automatically. (You don't publish nothing after a clean build. You don't have to manually execute assemble before publish.)
You still have to handle sources JAR until support for withSourcesJar() is added to AGP. See issue.
In your case it would look something like this:
// Because the components are created only during the afterEvaluate phase, you must
// configure your publications using the afterEvaluate() lifecycle method.
afterEvaluate {
publishing {
publications {
mavenJava(MavenPublication) {
// Applies the component for the release build variant.
from components.release
artifact tasks.sourcesJar
groupId = GROUP_ID
artifactId = ARTIFACT_ID
version = VERSION_NAME
}
}
}
artifactoryPublish {
// ...
}
}
Can somebody give me a hint on how to use the maven-publish Gradle plugin to publish a com.android.library project/module with AAR and source jar? I am able to do this with the old maven plugin - but I would like to use the new maven-publish plugin.
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 = '1.0.0'
}
}
}
}
See also: https://developer.android.google.cn/studio/build/maven-publish-plugin
Old answer
Since release of Android Studio 3.6 the support for building AAR (or even APK and AAB) is implemented in Android Gradle plugin 3.6.0 (and newer).
We don't need to handle the XML dependencies and stuff ourselves anymore.
Here is my updated Gist for Android Studio 3.6.0: https://gist.github.com/Robyer/a6578e60127418b380ca133a1291f017
Code from gist:
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 (if you save this as script and include it build.gradle file, then you can just replicate this whole block there only with changed fields).
//groupId = 'com.example'
//artifactId = 'custom-artifact'
version = android.defaultConfig.versionName // or just '1.0'
}
}
}
}
Original answer:
Here is my improved solution, based on other answers.
Gist: https://gist.github.com/Robyer/a6578e60127418b380ca133a1291f017
Changes from other answers:
Changed classifier - it must be "sources" (not "source")
Handles dependencies
Supports also #aar and transitive: false. In that case we set exclusion in POM to ignore all transitive dependencies of this dependency.
Supports also custom exclude rules on dependencies, e.g.:
compile('com.example:something:1.0', {
exclude group: 'com.exclude.this', module: 'some-module'
})
Doesn't need to specify artifact path manually.
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.javaCompile.classpath
}
}
exclude '**/R.html', '**/R.*.html', '**/index.html'
}
task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
classifier = 'javadoc'
from androidJavadocs.destinationDir
}
task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.srcDirs
}
project.afterEvaluate {
publishing {
publications {
maven(MavenPublication) {
//groupId 'cz.example'
//artifactId 'custom-artifact'
//version = android.defaultConfig.versionName
artifact bundleReleaseAar
artifact androidJavadocsJar
artifact androidSourcesJar
pom.withXml {
final dependenciesNode = asNode().appendNode('dependencies')
ext.addDependency = { Dependency dep, String scope ->
if (dep.group == null || dep.version == null || dep.name == null || dep.name == "unspecified")
return // ignore invalid dependencies
final dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', dep.group)
dependencyNode.appendNode('artifactId', dep.name)
dependencyNode.appendNode('version', dep.version)
dependencyNode.appendNode('scope', scope)
if (!dep.transitive) {
// If this dependency is transitive, we should force exclude all its dependencies them from the POM
final exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion')
exclusionNode.appendNode('groupId', '*')
exclusionNode.appendNode('artifactId', '*')
} else if (!dep.properties.excludeRules.empty) {
// Otherwise add specified exclude rules
final exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion')
dep.properties.excludeRules.each { ExcludeRule rule ->
exclusionNode.appendNode('groupId', rule.group ?: '*')
exclusionNode.appendNode('artifactId', rule.module ?: '*')
}
}
}
// List all "compile" dependencies (for old Gradle)
configurations.compile.getDependencies().each { dep -> addDependency(dep, "compile") }
// List all "api" dependencies (for new Gradle) as "compile" dependencies
configurations.api.getDependencies().each { dep -> addDependency(dep, "compile") }
// List all "implementation" dependencies (for new Gradle) as "runtime" dependencies
configurations.implementation.getDependencies().each { dep -> addDependency(dep, "runtime") }
}
}
}
}
}
Here's a sample using the new maven-publish plugin.
apply plugin: 'maven-publish'
task sourceJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier "sources"
}
publishing {
publications {
bar(MavenPublication) {
groupId 'com.foo'
artifactId 'bar'
version '0.1'
artifact(sourceJar)
artifact("$buildDir/outputs/aar/bar-release.aar")
}
}
repositories {
maven {
url "$buildDir/repo"
}
}
}
Publish with ./gradlew clean build publish
A little tweak to dskinners answer with correct dependency generation:
apply plugin: 'maven-publish'
task sourceJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier "source"
}
publishing {
publications {
bar(MavenPublication) {
groupId 'com.foo'
artifactId 'bar'
version '0.1'
artifact(sourceJar)
artifact("$buildDir/outputs/aar/bar-release.aar")
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
//Iterate over the compile dependencies (we don't want the test ones), adding a <dependency> node for each
configurations.compile.allDependencies.each {
if(it.group != null && (it.name != null || "unspecified".equals(it.name)) && it.version != null)
{
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
}
}
}
}
}
repositories {
maven {
url "$buildDir/repo"
}
}
}
And you can change version and groupId by defining:
version = '1.0.0'
group = 'foo.bar'
If you want to avoid boilerplate codes, because the maven-publish plugin do not write dependencies into pom.xml
Try this plugin: android-maven-publish
publishing {
publications {
mavenAar(MavenPublication) {
groupId 'com.example'
artifactId 'mylibrary'
version '1.0.0'
from components.android
}
}
repositories {
maven {
url "$buildDir/releases"
}
}
}
Update:
android-maven-publish plugin is deprecated, since maven-publish is officially supported by AGP.
This is how I included Dokka (view it online) and sources JARs for my Android Kotlin library using Kotlin DSL (build.gradle.kts):
plugins {
// ...
id("org.jetbrains.dokka") version "1.4.32"
id("maven-publish")
}
lateinit var sourcesArtifact: PublishArtifact
lateinit var javadocArtifact: PublishArtifact
tasks {
val sourcesJar by creating(Jar::class) {
archiveClassifier.set("sources")
from(android.sourceSets["main"].java.srcDirs)
}
val dokkaHtml by getting(org.jetbrains.dokka.gradle.DokkaTask::class)
val javadocJar by creating(Jar::class) {
dependsOn(dokkaHtml)
archiveClassifier.set("javadoc")
from(dokkaHtml.outputDirectory)
}
artifacts {
sourcesArtifact = archives(sourcesJar)
javadocArtifact = archives(javadocJar)
}
}
publishing {
// ...
publications {
create<MavenPublication>("MyPublication") {
from(components["release"])
artifact(sourcesArtifact)
artifact(javadocArtifact)
// ...
}
}
}
Using Kotlin build.gradle.kts:
publishing.publications {
register<MavenPublication>("aar") {
groupId = "com.foo"
artifactId = "bar"
version = "0.1"
artifact("$buildDir/outputs/aar/bar-release.aar")
pom.withXml {
val dependencies = asNode().appendNode("dependencies")
val addNode = { groupId: String, artifactId: String, version: String ->
val dependency = dependencies.appendNode("dependency")
dependency.appendNode("groupId", groupId)
dependency.appendNode("artifactId", artifactId)
dependency.appendNode("version", version)
}
addNode("com.example", "dependency-name", "1.0")
}
}
}
You can also use the android maven plugin. It creates the .aar, javadoc.jar, sources.jar and .pom and updates the maven-metadata.xml after uploading the files to the maven repository. I also put the script on GitHub.
apply plugin: 'com.android.library'
apply plugin: 'maven'
//Your android configuration
android {
//...
}
//maven repository info
group = 'com.example'
version = '1.0.0'
ext {
//Specify your maven repository url here
repositoryUrl = 'ftp://your.maven.repository.com/maven2'
//Or you can use 'file:\\\\C:\\Temp' or 'maven-temp' for a local maven repository
}
//Upload android library to maven with javadoc and android sources
configurations {
deployerJars
}
//If you want to deploy to an ftp server
dependencies {
deployerJars "org.apache.maven.wagon:wagon-ftp:2.2"
}
// custom tasks for creating source/javadoc jars
task javadoc(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
destinationDir = file("../javadoc/")
failOnError false
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
//Creating sources with comments
task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.srcDirs
}
//Put the androidSources and javadoc to the artifacts
artifacts {
archives androidSourcesJar
archives javadocJar
}
uploadArchives {
repositories {
mavenDeployer {
configuration = configurations.deployerJars
repository(url: repositoryUrl) {
//if your repository needs authentication
authentication(userName: "username", password: "password")
}
}
}
}
Call it with
./gradlew uploadArchives