将Android库(aar)发布到Bintray,并选择其他风味

时间:2015-12-17 10:03:38

标签: android android-gradle android-productflavors bintray

我是juste在我的项目中添加了一些flavors(或productFlavors,如果你愿意的话)。

事实是,当我将库发布到 bintray 时,会上传所有风格(这很棒),但我无法使用它们。使用的插件是官方插件here

上传的aar:

 androidsdk-0.0.4-fullRelease.aar
 androidsdk-0.0.4-fullDebug.aar
 androidsdk-0.0.4-lightRelease.aar
 androidsdk-0.0.4-lightDebug.aar

如您所知,fullRelease被命名为classifier,请参阅doc chapter 23.4.1.3

我正在寻找一种解决方案来选择我要上传的口味。

我已经查看了bintray示例(herehere)和this,还有其他示例,但我仍然卡住了。

这是我目前的剧本:

apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'com.jfrog.bintray'

buildscript {
    repositories {
        jcenter()
    }
}

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        minSdkVersion 9
        targetSdkVersion 23
        versionCode 64
        versionName "0.0.4"
    }

    publishNonDefault true

    productFlavors {
        full {
        }
        light {
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:recyclerview-v7:23.1.1'
    fullCompile 'com.squareup.picasso:picasso:2.5.0'
}

version = android.defaultConfig.versionName

uploadArchives {
    repositories.mavenDeployer {
        pom.project {

            packaging 'aar'

        }
    }
}

////////////////////////////////
// Bintray Upload configuration

Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())

bintray {
    user = properties.getProperty("bintray.user")
    key = properties.getProperty("bintray.apikey")

    configurations = ['archives']
    pkg {
        repo = "MyRepo" // repo name
        userOrg = 'hugo'
        name = "AndroidSDK" // Package name
        websiteUrl = siteUrl
        vcsUrl = gitUrl
        publish = true
    }
}

要导入我正在使用的库:

compile ('com.example.lib:sdk:0.0.8:fullRelease@aar') {
    transitive = true;
}

5 个答案:

答案 0 :(得分:12)

我面临着同样的挑战,而且这是我能做的最好的事情:

在bintray插件中使用mavenPublications和gradle maven-publish插件,您可以将任何变体发布到mavenLocal和bintray。

这是我在我要发布的所有项目库模块末尾应用的publish.gradle文件:

def pomConfig = {
    licenses {
        license {
            name 'The Apache Software License, Version 2.0'
            url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
        }
    }
    developers {
        developer {
            id 'louiscad'
            name 'Louis CAD'
            email 'louis.cognault@gmail.com'
        }
    }
    scm {
        connection 'https://github.com/LouisCAD/Splitties.git'
        developerConnection 'https://github.com/LouisCAD/Splitties.git'
        url siteUrl
    }
}

def publicationNames = []
publishing.publications {
    android.libraryVariants.all { variant ->
        if (variant.buildType.name == "debug") return // Prevents publishing debug library

        def flavored = !variant.flavorName.isEmpty()

        /**
         * Translates "_" in flavor names to "-" for artifactIds, because "-" in flavor name is an
         * illegal character, but is well used in artifactId names.
         */
        def variantArtifactId = flavored ? variant.flavorName.replace('_', '-') : project.name

        /**
         * If the javadoc destinationDir wasn't changed per flavor, the libraryVariants would
         * overwrite the javaDoc as all variants would write in the same directory
         * before the last javadoc jar would have been built, which would cause the last javadoc
         * jar to include classes from other flavors that it doesn't include.
         *
         * Yes, tricky.
         *
         * Note that "${buildDir}/docs/javadoc" is the default javadoc destinationDir.
         */
        def javaDocDestDir = file("${buildDir}/docs/javadoc ${flavored ? variantArtifactId : ""}")

        /**
         * Includes
         */
        def sourceDirs = variant.sourceSets.collect {
            it.javaDirectories // Also includes kotlin sources if any.
        }
        def javadoc = task("${variant.name}Javadoc", type: Javadoc) {
            description "Generates Javadoc for ${variant.name}."
            source = variant.javaCompile.source // Yes, javaCompile is deprecated,
            // but I didn't find any working alternative. Please, tweet @Louis_CAD if you find one.
            destinationDir = javaDocDestDir
            classpath += files(android.getBootClasspath().join(File.pathSeparator))
            classpath += files(configurations.compile)
            options.links("http://docs.oracle.com/javase/7/docs/api/");
            options.links("http://d.android.com/reference/");
            exclude '**/BuildConfig.java'
            exclude '**/R.java'
            failOnError false
        }
        def javadocJar = task("${variant.name}JavadocJar", type: Jar, dependsOn: javadoc) {
            description "Puts Javadoc for ${variant.name} in a jar."
            classifier = 'javadoc'
            from javadoc.destinationDir
        }
        def sourcesJar = task("${variant.name}SourcesJar", type: Jar) {
            description "Puts sources for ${variant.name} in a jar."
            from sourceDirs
            classifier = 'sources'
        }

        def publicationName = "splitties${variant.name.capitalize()}Library"
        publicationNames.add(publicationName)

        "$publicationName"(MavenPublication) {
            artifactId variantArtifactId
            group groupId
            version libraryVersion

            artifact variant.outputs[0].packageLibrary // This is the aar library
            artifact sourcesJar
            artifact javadocJar

            pom {
                packaging 'aar'
                withXml {
                    def root = asNode()
                    root.appendNode("name", 'Splitties')
                    root.appendNode("url", siteUrl)
                    root.children().last() + pomConfig
                    def depsNode = root["dependencies"][0] ?: root.appendNode("dependencies")

                    def addDep = {
                        if (it.group == null) return // Avoid empty dependency nodes
                        def dependencyNode = depsNode.appendNode('dependency')
                        dependencyNode.appendNode('groupId', it.group)
                        dependencyNode.appendNode('artifactId', it.name)
                        dependencyNode.appendNode('version', it.version)
                        if (it.hasProperty('optional') && it.optional) {
                            dependencyNode.appendNode('optional', 'true')
                        }
                    }

                    // Add deps that everyone has
                    configurations.compile.allDependencies.each addDep
                    // Add flavor specific deps
                    if (flavored) {
                        configurations["${variant.flavorName}Compile"].allDependencies.each addDep
                    }
                    // NOTE: This library doesn't use builtTypes specific dependencies, so no need to add them.
                }
            }
        }
    }
}

group = groupId
version = libraryVersion

afterEvaluate {
    bintray {
        user = bintray_user
        key = bintray_api_key
        publications = publicationNames

        override = true
        pkg {
            repo = 'splitties'
            name = project.name
            desc = libraryDesc
            websiteUrl = siteUrl
            issueTrackerUrl = 'https://github.com/LouisCAD/Splitties/issues'
            vcsUrl = gitUrl
            licenses = ['Apache-2.0']
            labels = ['aar', 'android']
            publicDownloadNumbers = true
            githubRepo = 'LouisCAD/Splitties'
        }
    }
}

为了实现这一点,我需要定义bintray_userbintray_api_key属性。我个人只是将它们放在我的~/.gradle/gradle.properties文件中:

bintray_user=my_bintray_user_name
bintray_api_key=my_private_bintray_api_key

我还需要在我的根项目publish.gradle文件中的build.gradle文件中定义以下ext属性:

allprojects {
    ...
    ext {
        ...
        // Libraries
        groupId = "xyz.louiscad.splitties"
        libraryVersion = "1.2.1"
        siteUrl = 'https://github.com/LouisCAD/Splitties'
        gitUrl = 'https://github.com/LouisCAD/Splitties.git'
    }
}

现在,我终于可以在我的android库模块中使用它,我有多个productFlavors。这是来自可发布图书馆模块build.gradle文件的摘录:

plugins {
    id "com.jfrog.bintray" version "1.7.3" // Enables publishing to bintray
    id "com.github.dcendents.android-maven" version "1.5" // Allows aar in mavenPublications
}

apply plugin: 'com.android.library'
apply plugin: 'maven-publish' // Used for mavenPublications

android {
    ...
    defaultPublishConfig "myLibraryDebug" // Allows using this library in another
    // module in this project without publishing to mavenLocal or Bintray.
    // Useful for debug purposes, or for your library's sample app.
    defaultConfig {
        ...
        versionName libraryVersion
        ...
    }
    ...
    productFlavors {
        myLibrary
        myLibrary_logged // Here, the "_" will be replaced "-" in artifactId when publishing.
        myOtherLibraryFlavor
    }
    ...
}

dependencies {
    ...
    // Timber, a log utility.
    myLibrary_loggedCompile "com.jakewharton.timber:timber:${timberVersion}"; // Just an example
}
...

ext {
    libraryDesc = "Delegates for kotlin on android that check UI thread"
}

apply from: '../publish.gradle' // Makes this library publishable

当您正确使用所有这些设置时,使用您的库的名称而不是mine's(您可以将其用作示例),您可以尝试通过首先发布来发布您的风味库的版本到mavenLocal。 为此,请运行以下命令:

myLibrary $ ../gradlew publishToMavenLocal

然后,您可以尝试在应用的存储库(example here)中添加mavenLocal并尝试添加您的库作为依赖项(artifactId应该是风格名称,使用" _&#34 ;替换为" - ")并构建它。 您还可以使用文件资源管理器(在Finder中使用cmd + shift + G来访问隐藏文件夹)查看目录~/.m2并查找您的库。

当发布到bintray / jcenter的时候,你只需要运行这个命令:

myLibrary $ ../gradlew bintrayUpload

重要:

在将库发布到mavenLocal,Bintray或其他maven存储库之前,您通常希望针对使用该库的示例应用程序尝试使用您的库。此示例应用程序应该是同一项目中的另一个模块,只需要具有项目依赖关系,它应如下所示:compile project(':myLibrary')。但是,由于您的库有多个productFlavors,您将要测试所有这些。不幸的是,目前无法在示例应用的build.gradle文件中指定您要使用的配置(除非您在图书馆使用publishNonDefault true build.gradle defaultPublishConfig "myLibraryDebug" 1}}文件,它打破了maven和bintray出版物),但您可以在库的模块中指定默认配置(即buildVariant):android闭包中的concurrency。您可以在" Build Variants"中找到库的可用构建变体。在Android Studio中使用Windows工具。

如果您需要一个例子,请随意浏览my library "Splitties" here。风味模块名为application.Union,但我也将脚本用于非风味的库模块,并且我在项目中的所有库模块上都经过了测试。

如果您需要帮助,可以联系我。

答案 1 :(得分:6)

设置:

buildTypes {
  debug {
  }
  release {
  }
}

publishNonDefault true

修复:

defaultPublishConfig 'release'

// Fix for defaultPublishConfig not working as expected
// ref: https://github.com/dcendents/android-maven-gradle-plugin/issues/11
libraryVariants.all { variant ->
  if( publishNonDefault && variant.name == defaultPublishConfig ) {
    def bundleTask = tasks["bundle${variant.name.capitalize()}"]
    artifacts {
      archives(bundleTask.archivePath) {
        classifier null //necessary to get rid of the suffix in the artifact
        builtBy bundleTask
        name name.replace('-' + variant.name, '')//necessary to get rid of the suffix from the folder name
      }
    }
  }
}

此修补程序仍将发布所有工件,但它将发布没有flavor后缀的默认工件,这足以使其全部工作。

仅上传默认工件的修复​​程序就是这样(如果bintray插件知道POM过滤器是什么):

install {
  repositories.mavenInstaller {
    /*
    POM filters can be used to block artifacts from certain build variants.

    However, Bintray does not respect POM filters, therefore this only works for maven deploy plugin.
    Also, bintray crashes with named filters, since it always expects a /build/pom/pom-default.xml,
  which does not happen with named filters.
    */
    filter { artifact, file ->
      // this how the default classifier is identified in case the defaultPublishConfig fix is applied
      artifact.attributes.classifier == null
    }
  }
}

答案 2 :(得分:3)

我没有尝试过,所以如果它没有解决问题,我会删除答案。

您应该为每种风格发布不同的工件(或者如果您愿意,可以构建变体) 通过这种方式,您将拥有jcenter x工件,每个工件都带有一个pom文件。

类似的东西:

groupId
|--library-full
|----.pom
|----.aar
|--library-light
|----.pom
|----.aar

在您的顶级文件中,您可以定义

allprojects {
    repositories {
        jcenter()
    }

    project.ext {
        groupId="xxx" 
        libraryName = ""
        ......
    }
}

然后在你的图书馆模块中:

productFlavors {
        full {
            project.ext.set("libraryName", "library-full");
        }
        light {
            project.ext.set("libraryName", "library-light");
        }
}

bintray {

    //...
    pkg {
        //...Do the same for other variables
        name = project.ext.libraryName
    }
}

最后确保只发布发布版本类型(为什么还要调试版本?)

答案 3 :(得分:2)

如果有人仍然坚持这个问题,那么对我有用的东西 -

假设您要发布针对您的flavour1的发布版本,请将其添加到您的build.gradle

android {
    ...
    defaultPublishConfig "flavour1Release"
}

如果您的gradle文件中存在publishNonDefault true,请将其删除。

bintray区块中添加此内容

bintray {
    ...
    archivesBaseName = 'YOUR_ARTIFACT_ID'
    ...
}

然后就像你一样运行bintrayUpload任务。

每次需要发布新口味时,都必须更改defaultPublishConfig

答案 4 :(得分:1)

听起来你不想在文件名中使用分类器。看起来分类器与生成的库文件名相同。你试过给他们相同的文件名但是把它们输出到不同的目录吗? 例如。在android范围内:

libraryVariants.all { variant ->
    variant.outputs.each { output ->
        def outputFile = output.outputFile
        if (outputFile != null && outputFile.name.endsWith('.aar')) {
            def fileName = "same_name-${version}.aar"
            output.outputFile = new File(outputFile.parent+"/${archivesBaseName}", fileName)
        }
    }
}