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

新手上路,请多包涵

有人可以给我一个关于如何使用 maven-publish Gradle 插件发布 com.android.library 项目/模块与 AAR 和源 jar 的提示吗?我可以使用旧的 maven 插件来做到这一点 - 但我想使用新的 maven-publish 插件。

原文由 ligi 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 792
2 个回答

这是使用新的 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

原文由 dskinner 发布,翻译遵循 CC BY-SA 3.0 许可协议

当前答案

使用 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 = android.defaultConfig.versionName // or manually '1.0'
            }
        }
    }
}

另见: https ://developer.android.google.cn/studio/build/maven-publish-plugin


旧答案

2020 年 3 月 3 日更新:

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

  • 处理依赖关系

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

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

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

变更日志:

  • 27.3.2018 - 在新的 Gradle 中添加了对 api / 实现 依赖项的支持
  • 2018 年 11 月 23 日- 重命名 bundleReleasebundleReleaseAar 因为它在新 Gradle 中已更改(请参阅 此答案
  • 2018 年 11 月 23 日 - 将 — getAllDependencies 更改为 getDependencies 以修复重复的结果条目(如我的 Gist 评论中所述)。
  • 2019 年 4 月 23 日 - 包装在 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") }
                }
            }
        }
    }
}

原文由 Robyer 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题