简介
完成一个开源库之后为了方便使用我们通常会将aar包上传到JCenter方便分发使用。上传依赖一个个人维护的插件android-maven-gradle-plugin。
升级Android studio到3.6.1,Android gradle plugin也默认随之升级到
com.android.tools.build:gradle:3.6.1之后
com.github.dcendents:android-maven-gradle-plugin:2.1再次拉跨,发现原作者已经弃坑,并推荐https://github.com/sky-uk/gradle-maven-plugin
但是这个脚本采用直接引用远程脚本的方式,并不稳定,也不符合国情。使用方式我的众多开源库的现有脚本差异巨大。所以我在改项目的基础上做了较大的改进, 使用更加方便:
使用方式
- 项目根目录创建以下文件:
gradle-mavenizer.gradle:
apply plugin: 'maven-publish'
//utils
def isAndroidProject() {
def plugins = project.getPlugins()
return plugins.hasPlugin('com.android.application') || plugins.hasPlugin('com.android.library')
}
def getStringProperty(String propertyName) {
return project.hasProperty(propertyName) ? project.getProperty(propertyName) : ""
}
def getBooleanProperty(String propertyName) {
return project.hasProperty(propertyName) ? project.getProperty(propertyName) : false
}
def getArrayProperty(String propertyName) {
return project.hasProperty(propertyName) ? project.getProperty(propertyName) : []
}
//pom manager
def decoratePom(pom) {
pom.name = getStringProperty("mavProjectName")
pom.description = getStringProperty("mavLibraryDescription")
pom.url = getStringProperty("mavSiteUrl")
pom.licenses {
getArrayProperty("mavLibraryLicenses").each { licenseName, licenseUrl ->
license {
name = licenseName
url = licenseUrl
}
}
}
pom.developers {
getArrayProperty("mavDevelopers").each { developerId, developerName ->
developer {
id = developerId
name = developerName
}
}
}
pom.scm {
connection = getStringProperty("mavGitUrl")
developerConnection = getStringProperty("mavGitUrl")
url = getStringProperty("mavSiteUrl")
}
addDependencies(pom)
}
def addDependencies(pom) {
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
if (dep.artifacts.size() > 0) {
dep.artifacts.each { art ->
addDependencyNode(dependenciesNode, dep, scope, art.classifier, art.extension)
}
} else {
addDependencyNode(dependenciesNode, dep, scope, null, null)
}
}
manageConfigurations(configurations)
}
}
def addDependencyNode(dependenciesNode, dep, scope, classifier, extension) {
final dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', dep.group)
dependencyNode.appendNode('artifactId', dep.name)
dependencyNode.appendNode('version', dep.version)
if (classifier != null) {
dependencyNode.appendNode('classifier', classifier)
}
if (extension != null) {
dependencyNode.appendNode('type', extension)
}
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('artifactId', '*')
exclusionNode.appendNode('groupId', '*')
} else if (!dep.properties.excludeRules.empty) {
// Otherwise add specified exclude rules
final exclusionsNode = dependencyNode.appendNode('exclusions')
dep.properties.excludeRules.each { ExcludeRule rule ->
final exclusionNode = exclusionsNode.appendNode('exclusion')
exclusionNode.appendNode('artifactId', rule.module ?: '*')
exclusionNode.appendNode('groupId', rule.group ?: '*')
}
}
}
def manageConfigurations(configurations) {
configurations.compile.getDependencies().each { dep -> addDependency(dep, "compile") }
configurations.api.getDependencies().each { dep -> addDependency(dep, "compile") }
configurations.implementation.getDependencies().each { dep -> addDependency(dep, "runtime") }
configurations.testImplementation.getDependencies().each { dep -> addDependency(dep, "test") }
configurations.testCompile.getDependencies().each { dep -> addDependency(dep, "test") }
if (!isAndroidProject()) {
configurations.runtime.getDependencies().each { dep -> addDependency(dep, "runtime") }
configurations.testRuntime.getDependencies().each { dep -> addDependency(dep, "test") }
}
}
//javadoc handler
if (isAndroidProject()) {
task androidJavadocs(type: Javadoc) {
title = "${getStringProperty("mavProjectName")} ${project.version} API"
description "Generates Javadoc"
source = android.sourceSets.main.java.srcDirs
classpath += files(android.bootClasspath)
android.libraryVariants.all { variant ->
if (variant.name == 'release') {
owner.classpath += variant.javaCompileProvider.get().classpath
}
}
exclude '**/R.html', '**/R.*.html', '**/index.html', '**/*.kt'
options {
windowTitle("${getStringProperty("mavProjectName")} ${project.version} Reference")
locale = 'en_US'
encoding = 'UTF-8'
charSet = 'UTF-8'
links("http://docs.oracle.com/javase/7/docs/api/")
linksOffline("http://d.android.com/reference", "${android.sdkDirectory}/docs/reference")
setMemberLevel(JavadocMemberLevel.PUBLIC)
}
}
task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
classifier = 'javadoc'
from androidJavadocs.destinationDir
}
task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.srcDirs
}
} else {
task sourcesJar(type: Jar) {
from sourceSets.main.allJava
archiveClassifier = 'sources'
}
task javadocJar(type: Jar) {
from javadoc
archiveClassifier = 'javadoc'
}
}
//publish
project.afterEvaluate {
publishing {
publications {
mavenPublish(MavenPublication) {
if (isAndroidProject()) {
artifact bundleReleaseAar
artifact androidJavadocsJar
artifact androidSourcesJar
} else {
artifact jar
artifact sourcesJar
artifact javadocJar
}
decoratePom(pom)
}
}
repositories {
def isToRemoteRepo = getBooleanProperty("mavPublishToRemoteRepo")
def isToInternalRepo = getBooleanProperty("mavPublishToInternalRepo")
def isToMavenLocal = getBooleanProperty("mavPublishToMavenLocal")
if (isToRemoteRepo) {
maven {
credentials {
username getStringProperty("mavRemoteRepoUser")
password getStringProperty("mavRemoteRepoPassword")
}
url = getStringProperty("mavRepoRemoteUrl")
}
}
if (isToInternalRepo) {
maven {
url = getStringProperty("mavRepoInternalUrl")
}
}
if (isToMavenLocal || (!isToInternalRepo && !isToRemoteRepo)) {
mavenLocal()
}
}
}
}
deployBintray.gradle:
apply plugin: 'com.jfrog.bintray'
if (!bintray_user) {
//需要将bintary账户信息配置在~/.gradle.properties中
print("add your bintray_user & bintray_key first!!")
return
}
def properties = new Properties()
properties.load(new FileInputStream(rootProject.file('project.properties')))
project.ext {
mavGitUrl = properties.getProperty("project.gitUrl")
mavProjectName = properties.getProperty("project.name")
mavLibraryLicenses = ["Apache-2.0":'http://www.apache.org/licenses/LICENSE-2.0.txt']
mavLibraryDescription = properties.getProperty("project.desc")
mavPublishToMavenLocal = true
mavSiteUrl = properties.getProperty("project.siteUrl")
}
bintray {
user = "${bintray_user}"
key = "${bintray_key}"
publications = ['mavenPublish']
configurations = ['archives']
override = true
pkg {
repo = properties.getProperty("project.repo")
name = properties.getProperty("project.name")
websiteUrl = properties.getProperty("project.siteUrl")
vcsUrl = properties.getProperty("project.gitUrl")
description = properties.getProperty("project.desc")
publicDownloadNumbers = true
licenses = ['Apache-2.0']
}
}
apply from: rootProject.file('gradle-mavenizer.gradle')
project.properties:(配置信息)
# suppress inspection "UnusedProperty" for whole file
#project
project.repo=bintray注册的maven仓库名,默认为maven
project.name=项目名
project.desc=描述
project.groupId=xxx
project.packaging=aar
project.siteUrl=xxx
project.gitUrl=xxx
license.name=Apache-2.0
license.url=https\://opensource.org/licenses/apache2.0.php
developer.id=xxx
developer.name=xxx
developer.email=xxx
- 在用户目录的~/.gradle/gradle.properties配置如下信息:
bintray_key=从bintray控制台获得的token
bintray_user=bintray用户名
- 在root项目的build.gradle中添加如下信息为每个library子模块设置group 和version
subprojects {
if ("lib" == it.name) {
group = 'com.example.xxx'//发布到 bintray 的groupId号
version = "1.0.0" // 发布到 bintray 的版本号
}
}
- build.graldet添加插件
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
- 在library模块的build.gradle的最下方引用:
apply from: '../deployBintray.gradle'
- 最后执行
bintrayUpload任务将library打包上传的JCenter
示例项目: github.com/hotstu/chip…