简体   繁体   English

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

[英]Publishing Android Library (aar) to Bintray with chosen flavors

I've juste added some flavors (or productFlavors if you want) to my project. 我已经在我的项目中添加了一些flavors (或者你想要的productFlavors )。

The fact is that when I publish the library to bintray , all flavors are uploaded (which is great), but I'm unable to use them. 事实是,当我将库发布到bintray时 ,所有的风格都被上传(这很棒),但我无法使用它们。 The plugin used is the official one here . 使用该插件是官方的一个在这里

The uploaded aar: 上传的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

As you noted, the fullRelease is named as the classifier , see doc chapter 23.4.1.3 . 如您所述, fullRelease被命名为classifier ,请参阅文档第23.4.1.3节

I am searching for a solution to choose which flavors that I want to upload. 我正在寻找一种解决方案来选择我要上传的口味。

I've already looked at bintray examples ( here and here ) and this , with also other examples but I'm still stuck. 我已经看过bintray的例子( 这里这里 )和这个 ,还有其他例子,但我仍然卡住了。

Here is my current script: 这是我目前的脚本:

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

To import the library I'm currently using this: 要导入我正在使用的库:

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

I faced the same challenge, and here's the best I could make yet: 我面临同样的挑战,这是我能做的最好的事情:

Using mavenPublications and the gradle maven-publish plugin along the bintray plugin, you can publish any variant to mavenLocal and bintray. 使用mavenPublications和bintray插件中的gradle maven-publish插件,您可以将任何变体发布到mavenLocal和bintray。

Here's the publish.gradle file I apply at the end of all my project's library modules I want to publish: 这是我在我要发布的所有项目库模块末尾应用的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'
        }
    }
}

In order for this to work, I need to have the bintray_user and bintray_api_key properties defined. 为了使其工作,我需要定义bintray_userbintray_api_key属性。 I personally just have them in my ~/.gradle/gradle.properties file like this: 我个人只是将它们放在我的~/.gradle/gradle.properties文件中,如下所示:

bintray_user=my_bintray_user_name
bintray_api_key=my_private_bintray_api_key

I also need to define the following ext properties I used in the publish.gradle file in my root project's build.gradle file: 我还需要在root项目的build.gradle文件中定义我在publish.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'
    }
}

And now, I can finally use it in my android library module, where I have multiple productFlavors . 现在,我终于可以在我的android库模块中使用它,我有多个productFlavors Here's a snippet from a publishable library module's build.gradle file: 这是来自可发布库模块的build.gradle文件的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

When you have all of this setup properly, with the name of your library instead of mine's (which you can use as an example), you can try publishing a version of your flavored library by trying to first publishing to mavenLocal. 当您正确地使用所有这些设置时,使用您的库的名称而不是我的 (您可以将其用作示例),您可以尝试通过首先发布到mavenLocal来发布您的风味库的版本。 To do so, run this command: 为此,请运行以下命令:

myLibrary $ ../gradlew publishToMavenLocal

You can then try adding mavenLocal in your app's repositories (example here) and try adding your library as a dependency (artifactId should be the flavor name, with "_" replaced with "-") and building it. 然后,您可以尝试在应用程序的存储库中添加mavenLocal (此处为示例)并尝试将库添加为依赖项(artifactId应为flavor名称,“_”替换为“ - ”)并构建它。 You can also check with your file explorer (use cmd+shift+G on Mac in Finder to access hidden folder) the directory ~/.m2 and look for your library. 您还可以使用文件资源管理器(在Finder中使用cmd + shift + G访问隐藏文件夹)检查目录~/.m2并查找您的库。

When it's time to publish to bintray/jcenter, you just have to run this command: 什么时候发布到bintray / jcenter,你只需要运行这个命令:

myLibrary $ ../gradlew bintrayUpload

Important: 重要:

Before you publish your library to mavenLocal, Bintray or another maven repository, you'll usually want to try your library against a sample app which uses the library. 在将库发布到mavenLocal,Bintray或其他maven存储库之前,您通常需要针对使用该库的示例应用程序尝试使用您的库。 This sample app, which should be another module in the same project just need to have the project dependency, which should look like this: compile project(':myLibrary') . 这个示例应用程序应该是同一项目中的另一个模块,只需要具有项目依赖性,它应该如下所示: compile project(':myLibrary') However, since your library has multiple productFlavors, you'll want to test all of them. 但是,由于您的库有多个productFlavor,因此您需要测试所有这些。 Unfortunately, it's currently impossible to specify which configuration you want to use from your sample app's build.gradle file (unless, you use publishNonDefault true in your library's build.gradle file, which breaks maven and bintray publications), but you can specify the default configuration (ie buildVariant) in your library's module as such: defaultPublishConfig "myLibraryDebug" in the android closure. 不幸的是,目前无法从示例应用程序的build.gradle文件中指定要使用的配置(除非您在库的build.gradle文件中使用publishNonDefault true ,这会破坏maven和bintray发布),但您可以指定默认值你的库模块中的配置(即buildVariant): android封闭中的defaultPublishConfig "myLibraryDebug" You can see the available build variants for your library in the "Build Variants" tool Windows in Android Studio. 您可以在Android Studio的“Build Variants”工具Windows中查看库的可用构建变体。

Feel free to explore my library "Splitties" here if you need an example. 如果您需要一个例子,请随意浏览我的图书馆“Splitties” The flavored module is named concurrency , but I use my script for unflavored library modules too, and I tested it throughly on all the library modules in my project. 风味模块被命名为concurrency ,但我也将我的脚本用于无味的库模块,并且我在项目中的所有库模块上进行了彻底的测试。

You can reach me out if you need help setting it up for you. 如果您需要帮助,可以联系我。

The setup: 设置:

buildTypes {
  debug {
  }
  release {
  }
}

publishNonDefault true

The fix: 修复:

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

This fix will still publish all the artifacts, but it will publish a default artifact without the flavour suffix, which is enough to make it all work. 此修复程序仍将发布所有工件,但它将发布没有flavor后缀的默认工件,这足以使其全部工作。

The fix to upload only the default artifact would be this (if the bintray plugin knew what POM filters are): 只上传默认工件的修复​​程序是这样的(如果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
    }
  }
}

I didn't try it so I will delete the answer if it doesn't resolve the issue. 我没有尝试,所以如果不能解决问题,我会删除答案。

You should post a different artifact for each flavor (or build variant if you prefer). 您应该为每种风格发布不同的工件(或者如果您愿意,可以构建变体)。
In this way you will have in jcenter x artifacts, each of them with a pom file. 通过这种方式,您将拥有jcenter x工件,每个工件都带有一个pom文件。

Something like: 就像是:

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

In your top level file you can define 在您的顶级文件中,您可以定义

allprojects {
    repositories {
        jcenter()
    }

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

Then in your library module: 然后在你的库模块中:

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

Finally make sure to publish only the release build type (why also the debug version?) 最后确保只发布发布版本类型(为什么还要调试版本?)

If someone is still stuck with this problem here's what worked for me - 如果有人仍然坚持这个问题,这对我有用 -

Let's say you want to publish the release build for your flavour1 add this to your build.gradle 假设您要发布flavour1的发布版本,请将其添加到build.gradle

android {
    ...
    defaultPublishConfig "flavour1Release"
}

Remove publishNonDefault true if it is present in your gradle file. 如果您的gradle文件中存在publishNonDefault true则将其删除。

Add this inside the bintray block like this 像这样在bintray块中添加它

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

Then just run the bintrayUpload task as you would. 然后就像你一样运行bintrayUpload任务。

The defaultPublishConfig will have to be changed everytime you need to publish a new flavour. 每次需要发布新的flavor时,都必须更改defaultPublishConfig

It sounds like you don't want the classifier in the filename. 听起来你不想在文件名中使用分类器。 It looks like the classifier is the same as the generated library file name. 看起来分类器与生成的库文件名相同。 Have you tried giving them the same filename but outputting them to separate directories? 你试过给他们相同的文件名但是把它们输出到不同的目录吗? Eg in the android scope: 例如在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)
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM