Подтвердить что ты не робот

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

Вот мой текущий 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
    }
}

Чтобы импортировать библиотеку, я в настоящее время использую это:

compile ('com.example.lib:sdk:0.0.8:[email protected]') {
    transitive = true;
}
4b9b3361

Ответ 1

Я столкнулся с тем же вызовом, и здесь лучшее, что я мог сделать:

Используя плагин 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 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

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

myLibrary $ ../gradlew publishToMavenLocal

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

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

myLibrary $ ../gradlew bintrayUpload

Важно:

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

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

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

Ответ 2

Настройка:

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

Ответ 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
    }
}

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

Ответ 4

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

Предположим, вы хотите опубликовать сборку релизов для своего flavour1, добавьте это в свой build.gradle

android {
    ...
    defaultPublishConfig "flavour1Release"
}

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

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

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

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

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

Ответ 5

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

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