简体   繁体   English

使用 AAR 和源代码 JAR 将 Android 库发布到 Maven

[英]Publish an Android library to Maven with AAR and sources JAR

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?有人可以提示我如何使用maven-publish Gradle 插件发布带有 AAR 和源 jar 的com.android.library项目/模块吗? I am able to do this with the old maven plugin - but I would like to use the new maven-publish plugin.我可以使用旧的maven插件来做到这一点——但我想使用新的maven-publish插件。

Here's a sample using the new maven-publish plugin.这是使用新的maven-publish插件的示例。

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使用./gradlew clean build publish

Updated 3.3.2020: 2020 年 3 月 3 日更新:

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).自 Android Studio 3.6 发布以来,在 Android Gradle 插件 3.6.0(及更新版本)中实现了对构建 AAR(甚至 APK 和 AAB)的支持。

We don't need to handle the XML dependencies and stuff ourselves anymore.我们不再需要自己处理 XML 依赖项和东西了。

Here is my updated Gist for Android Studio 3.6.0:https://gist.github.com/Robyer/a6578e60127418b380ca133a1291f017这是我更新的 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'
            }
        }
    }
}

Old answer:旧答案:

Here is my improved solution, based on other answers.这是我根据其他答案改进的解决方案。

Gist:https://gist.github.com/Robyer/a6578e60127418b380ca133a1291f017要点:https ://gist.github.com/Robyer/a6578e60127418b380ca133a1291f017

Changes from other answers:其他答案的变化:

  • Changed classifier - it must be "sources" ( not "source" )更改classifier - 它必须是"sources"而不是"source"
  • Handles dependencies处理依赖关系

    • Supports also @aar and transitive: false .还支持@aartransitive: false In that case we set exclusion in POM to ignore all transitive dependencies of this dependency.在这种情况下,我们在 POM 中设置排除以忽略此依赖项的所有传递依赖项。
    • Supports also custom exclude rules on dependencies, eg:还支持对依赖项的自定义排除规则,例如:

       compile('com.example:something:1.0', { exclude group: 'com.exclude.this', module: 'some-module' })
  • Doesn't need to specify artifact path manually.不需要手动指定工件路径。

Changelog:变更日志:

  • 27.3.2018 - Added support for api / implementation dependencies in new Gradle 27.3.2018 - 在新 Gradle 中添加了对api /实现依赖项的支持
  • 23.11.2018 - Renamed bundleRelease to bundleReleaseAar as it was changed in new Gradle (see this answer ) 2018年11月23日-更名bundleReleasebundleReleaseAar因为它在新的摇篮改变(见这个答案
  • 23.11.2018 - Changed getAllDependencies to getDependencies to fix duplicated resulting entries (as mentioned in comments on my Gist). 2018年11月23日-更改getAllDependenciesgetDependencies以修复复制结果条目(如在评论中提到我的GIST)。
  • 23.04.2019 - Wrapped in project.afterEvaluate{...} to fix it for new Gradle. 23.04.2019 - 包裹在project.afterEvaluate{...}以针对新 Gradle 修复它。

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") }
                }
            }
        }
    }
}

A little tweak to dskinners answer with correct dependency generation:通过正确的依赖生成对 dskinners 的回答进行一些调整:

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:您可以通过定义来更改versiongroupId

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如果你想避免样板代码,因为maven-publish插件不会将依赖写入 pom.xml

Try this plugin: android-maven-publish试试这个插件: android-maven-publish

publishing {
    publications {
        mavenAar(MavenPublication) {
            groupId 'com.example'
            artifactId 'mylibrary'
            version '1.0.0'
            from components.android
        }
    }

    repositories {
        maven {
            url "$buildDir/releases"
        }
    }
}

This is how I included Dokka (view it online ) and sources JARs for my Android Kotlin library using Kotlin DSL (build.gradle.kts):这就是我使用Kotlin DSL (build.gradle.kts) 为我的 Android Kotlin 库包含Dokka在线查看)和源 JAR 的方式:

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)
            // ...
        }
    }
}

You can also use the android maven plugin .您还可以使用android maven 插件 It creates the .aar, javadoc.jar, sources.jar and .pom and updates the maven-metadata.xml after uploading the files to the maven repository.它创建 .aar、javadoc.jar、sources.jar 和 .pom,并在将文件上传到 maven 存储库后更新 maven-metadata.xml。 I also put the script on GitHub .我也把脚本放在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

Using Kotlin build.gradle.kts :使用 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")
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM