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

问题描述 投票:0回答:7

有人可以给我一些关于如何使用

maven-publish
Gradle 插件来发布带有 AAR 和源 jar 的
com.android.library
项目/模块的提示吗?我可以使用旧的
maven
插件来完成此操作 - 但我想使用新的
maven-publish
插件。

android gradle android-gradle-plugin android-library maven-publish
7个回答
143
投票

使用 Android Gradle Plugin 7.1 现在可以非常简单地执行此操作,无需任何复杂的脚本。 AGP 现在还可以处理创建源代码和 javadocs jar。

您不需要任何单独的脚本,只需将所有内容写入模块的

build.gradle
文件中即可:

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'
            }
        }
    }
}

参见官方文档:https://developer.android.com/build/publish-library


旧答案

自 Android Studio 3.6 发布以来,Android Gradle 插件 3.6.0(及更高版本)中实现了对构建 AAR(甚至 APK 和 AAB)的支持。

我们不再需要处理 XML 依赖关系并自行填充。

这是我更新的 Android Studio 3.6.0 要点:https://gist.github.com/Robyer/a6578e60127418b380ca133a1291f017

要点代码:

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'
            }
        }
    }
}

原答案:

这是我根据其他答案改进的解决方案。

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

其他答案的更改:

  • 已更改
    classifier
    - 必须是
    "sources"
    不是
    "source"
  • 处理依赖关系
    • 还支持

      @aar
      transitive: false
      。在这种情况下,我们在 POM 中设置排除以忽略此依赖项的所有传递依赖项。

    • 还支持依赖项的自定义排除规则,例如:

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

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

109
投票

这是使用新的

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

发布与

./gradlew clean build publish


35
投票

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

您可以通过定义以下内容来更改

version
groupId

version = '1.0.0'
group = 'foo.bar'

24
投票

如果你想避免样板代码,因为

maven-publish
插件不会将依赖项写入pom.xml

尝试这个插件:android-maven-publish

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

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

更新:

android-maven-publish 插件已弃用,因为 maven-publish 已被 AGP 正式支持。


4
投票

以下是我如何使用 Kotlin DSL(build.gradle.kts)包含 Dokka(查看在线)和我的 Android Kotlin 库的源 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)
            // ...
        }
    }
}

2
投票

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

-2
投票

您还可以使用android maven 插件。它创建 .aar、javadoc.jar、sources.jar 和 .pom,并在将文件上传到 maven 存储库后更新 maven-metadata.xml。我还将脚本放在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")
            }
        }
    }
}

调用它
./gradlew uploadArchives
© www.soinside.com 2019 - 2024. All rights reserved.