Публикация библиотеки Android (aar) в Bintray с выбранными вариантами

Я только что добавил flavors (или productFlavors, если хотите) в свой проект.

Дело в том, что когда я публикую библиотеку в bintray, подгружаются все вкусы (и это здорово), но я не могу их использовать. Используемый плагин является официальным здесь.

Загруженный файл 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, см. главу документа 23.4.1.3.

Я ищу решение, чтобы выбрать, какие ароматы я хочу загрузить.

Я уже рассматривал примеры bintray (здесь и здесь) и это, с другими примерами, но я все еще застрял.

Вот мой текущий скрипт:

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

person Hugo Gresse    schedule 17.12.2015    source источник
comment
Вы должны обновить каждый аромат как отдельный артефакт.   -  person Gabriele Mariotti    schedule 17.12.2015
comment
@GabrieleMariotti, как указать вкус в bintray configurations?   -  person Hugo Gresse    schedule 17.12.2015
comment
Я не пробовал это раньше. Но вы должны указать некоторую часть конфигураций bintray внутри блока флейвора, чтобы назначить имя артефакта.   -  person Gabriele Mariotti    schedule 17.12.2015


Ответы (5)


Я столкнулся с той же проблемой, и вот лучшее, что я мог сделать:

Используя mavenPublications и плагин gradle maven-publish вместе с плагином bintray, вы можете опубликовать любой вариант в 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 '[email protected]'
        }
    }
    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_user и bintray_api_key. Лично у меня они просто есть в моем ~/.gradle/gradle.properties файле вот так:

bintray_user=my_bintray_user_name
bintray_api_key=my_private_bintray_api_key

Мне также нужно определить следующие свойства ext, которые я использовал в файле publish.gradle. в файле build.gradle моего корневого проекта:

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

Когда у вас все это настроено правильно, с именем вашей библиотеки вместо моей (которое вы можете использовать например), вы можете попробовать опубликовать версию своей расширенной библиотеки, попытавшись сначала опубликовать ее в mavenLocal. Для этого выполните эту команду:

myLibrary $ ../gradlew publishToMavenLocal

Затем вы можете попробовать добавить mavenLocal в репозиторий вашего приложения (пример здесь) и попробуйте добавить свою библиотеку в качестве зависимости (artifactId должен быть именем разновидности, где «_» заменено на «-») и собрать ее. Вы также можете проверить в проводнике (используйте cmd+shift+G на Mac в Finder для доступа к скрытой папке) каталог ~/.m2 и найти свою библиотеку.

Когда пришло время опубликовать в bintray/jcenter, вам просто нужно запустить эту команду:

myLibrary $ ../gradlew bintrayUpload

Важно:

Прежде чем опубликовать свою библиотеку в mavenLocal, Bintray или другом репозитории maven, вы обычно захотите протестировать свою библиотеку на образце приложения, которое использует библиотеку. Этот образец приложения, который должен быть еще одним модулем в том же проекте, просто должен иметь зависимость от проекта, которая должна выглядеть так: compile project(':myLibrary'). Однако, поскольку в вашей библиотеке есть несколько productFlavors, вы захотите протестировать их все. К сожалению, в настоящее время невозможно указать, какую конфигурацию вы хотите использовать из файла build.gradle вашего примера приложения (если только вы не используете publishNonDefault true в файле build.gradle вашей библиотеки, что нарушает публикации maven и bintray), но вы можете указать конфигурацию по умолчанию (т.е. buildVariant) в модуле вашей библиотеки как таковой: defaultPublishConfig "myLibraryDebug" в замыкании android. Вы можете увидеть доступные варианты сборки для вашей библиотеки в инструменте «Варианты сборки» Windows в Android Studio.

Не стесняйтесь исследовать мою библиотеку "Splitties" здесь, если вам нужен пример. Ароматизированный модуль называется concurrency, но я использую свой скрипт и для неароматизированных библиотечных модулей, и я тщательно протестировал его на всех библиотечных модулях в моем проекте.

Вы можете связаться со мной, если вам нужна помощь в настройке.

person Louis CAD    schedule 27.01.2017
comment
в качестве примечания к нижнему разделу вы можете настроить приложение-потребитель на правильную конфигурацию, указавmissingDimensionStrategy следующим образом: missingDimensionStrategy 'brand', 'XXX' missingDimensionStrategy 'environment', 'ZZZ' - person MrTristan; 12.01.2018
comment
Спасибо за отличный ответ. Я столкнулся с одной проблемой: в каталоге ~/.m2 у меня есть разные файлы .jar для каждого вкуса, но когда я запускаю bintrayUpload, он загружает один и тот же контент в файл jar каждого вкуса продукта. - person Vikram; 29.11.2018
comment
@VikramBhati Как сказано в ответе, вам нужно изменить defaultPublishConfig перед публикацией указанного аромата. - person Louis CAD; 29.11.2018
comment
@LouisCAD Я только что попробовал то, что вы сказали, но все равно загружает один и тот же файл .jar для всех вкусов. На данный момент запуск bintrayUpload даже с defaultPublishConfig abc публикует все варианты на bintray. Поэтому я не думаю, что есть какое-либо влияние defaultPublishConfig в bintrayUpload. Пожалуйста, поправьте меня, если я что-то пропустил. - person Vikram; 29.11.2018
comment
@LouisCAD Кажется, publishNonDefault устарела. Получил предупреждение при запуске bintrayUpload - publishNonDefault устарел и больше не действует. Все варианты уже опубликованы. - person Vikram; 29.11.2018
comment
Это объясняет. Обратите внимание, что я больше не использую это. Я предпочитаю делать несколько модулей, один с общим кодом, а другие с вещами, которые я хочу изменить, а затем выбираю один или другой. - person Louis CAD; 30.11.2018

Установка:

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

Это исправление по-прежнему будет публиковать все артефакты, но оно будет публиковать артефакт по умолчанию без суффикса варианта, которого достаточно, чтобы все заработало.

Исправление для загрузки только артефакта по умолчанию было бы следующим (если бы плагин 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
    }
  }
}
person Ricardo Freitas    schedule 06.02.2017

Я не пробовал, поэтому я удалю ответ, если он не решит проблему.

Вы должны опубликовать разные артефакты для каждого варианта (или варианта сборки, если хотите).
Таким образом, вы будете иметь в 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
    }
}

Наконец, не забудьте опубликовать только тип сборки выпуска (почему еще и отладочную версию?)

person Gabriele Mariotti    schedule 18.12.2015
comment
хорошо, с этим я могу загружать разные вкусы в разные пакеты bintray. Но классификатор все еще здесь, и у каждого пакета есть все вкусы. - person Hugo Gresse; 18.12.2015
comment
Извините, но я не знаю, что вы имеете в виду с классификатором. Я проверяю файл pom в jcenter, и у вас должен быть groupId/artifactId для идентификации библиотеки. - person Gabriele Mariotti; 18.12.2015
comment
да, у меня есть это, но классификатор тоже здесь, поэтому у меня есть и androidsdk-0.0.4-lightDebug.aar, и androidsdk-0.0.4-lightDebug.aar на каждом пакете. Так что в настоящее время есть две проблемы с этим. Например, классификатор lightDebug. - person Hugo Gresse; 29.12.2015
comment
Вы нашли ответ? - person Ali Naddaf; 07.02.2016
comment
нет, у меня все еще загружено 4 библиотеки (2 варианта и релиз + отладочная сборка), мне нужно удалять отладочную сборку каждый раз, когда я выпускаю новую версию на bintray. - person Hugo Gresse; 08.12.2016

Если кто-то все еще застрял с этой проблемой, вот что сработало для меня -

Допустим, вы хотите опубликовать сборку релиза для своего варианта1, добавьте его в свой build.gradle

android {
    ...
    defaultPublishConfig "flavour1Release"
}

Удалите publishNonDefault true, если он присутствует в вашем файле gradle.

Добавьте это внутри блока bintray вот так

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

Затем просто запустите задачу bintrayUpload, как обычно.

defaultPublishConfig нужно будет менять каждый раз, когда вам нужно опубликовать новый вкус.

person k1slay    schedule 09.12.2016
comment
Удаление publishNonDefault true предотвратит использование модуля в другом модуле при отладке, это хорошая идея, но не решает проблему полностью. - person Hugo Gresse; 09.12.2016
comment
Да, если вы хотите использовать библиотечный модуль в отладке, вам придется использовать что-то вроде defaultPublishConfig "flavour1Debug". Вы переключаетесь на defaultPublishConfig "flavour1Release" только тогда, когда вам нужно опубликовать в bintray - person k1slay; 09.12.2016

Похоже, вам не нужен классификатор в имени файла. Похоже, что классификатор совпадает с именем сгенерированного файла библиотеки. Вы пытались дать им одно и то же имя файла, но вывести их в разные каталоги? Например. в области андроида:

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)
        }
    }
}
person Jim Baca    schedule 12.01.2016
comment
которые позволяют мне изменить имя файла .aar (с build/outputs/aar/androidsdk/, но не с того, которое используется плагином bintray, поэтому это не помогло. - person Hugo Gresse; 12.01.2016