Gradle 5.x之后上传开源库到JCenter用这个就够了

2,162 阅读2分钟

简介

完成一个开源库之后为了方便使用我们通常会将aar包上传到JCenter方便分发使用。上传依赖一个个人维护的插件android-maven-gradle-plugin。 升级Android studio到3.6.1Android 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

但是这个脚本采用直接引用远程脚本的方式,并不稳定,也不符合国情。使用方式我的众多开源库的现有脚本差异巨大。所以我在改项目的基础上做了较大的改进, 使用更加方便:

使用方式

  1. 项目根目录创建以下文件:

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
  1. 在用户目录的~/.gradle/gradle.properties配置如下信息:
bintray_key=从bintray控制台获得的token
bintray_user=bintray用户名
  1. 在root项目的build.gradle中添加如下信息为每个library子模块设置group 和version
subprojects {
    if ("lib" == it.name) {
        group = 'com.example.xxx'//发布到 bintray 的groupId号
        version = "1.0.0" // 发布到 bintray 的版本号
    }
}
  1. build.graldet添加插件
        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'

  1. 在library模块的build.gradle的最下方引用:
apply from: '../deployBintray.gradle'
  1. 最后执行bintrayUpload任务将library打包上传的JCenter

示例项目: github.com/hotstu/chip…