Publicación de Android Library (aar) a Bintray con sabores elegidos


Acabo de añadir algunos flavors (o productFlavors si quieres) a mi proyecto.

El hecho es que cuando publico la biblioteca en bintray, todos los sabores se cargan (lo cual es genial), pero no puedo usarlos. El plugin utilizado es el oficial aquí.

El aar subido:

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

Como usted señaló, el fullRelease se nombra como el classifier, véase doc capítulo 23.4.1.3.

Estoy buscando una solución para elegir qué sabores que quiero subir.

He mirado ya bintray ejemplos (aquí y aquí) y este, con también otros ejemplos, pero todavía estoy atascado.

Aquí está mi script actual:

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

Para importar la biblioteca estoy usando esto:

compile ('com.example.lib:sdk:0.0.8:fullRelease@aar') {
    transitive = true;
}
Author: Community, 2015-12-17

5 answers

Me enfrenté al mismo desafío, y aquí está lo mejor que pude hacer todavía:{[26]]}

Usando mavenPublications y el complemento gradle maven-publish junto con el complemento bintray, puedes publicar cualquier variante en mavenLocal y bintray.

Aquí está el publish.gradle archivo que aplico al final de todos los módulos de la biblioteca de mi proyecto que quiero publicar:

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

Para que esto funcione, necesito tener definidas las propiedades bintray_user y bintray_api_key. Personalmente solo los tengo en mi archivo ~/.gradle/gradle.properties como esto:

bintray_user=my_bintray_user_name
bintray_api_key=my_private_bintray_api_key

También necesito definir las siguientes propiedades ext que utilicé en el publish.gradle archivo en mi proyecto raíz build.gradle archivo:

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

Y ahora, finalmente puedo usarlo en mi módulo de biblioteca de Android, donde tengo múltiples productFlavors. Aquí hay un fragmento de un módulo de biblioteca publicablebuild.gradle archivo:

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

Cuando tenga toda esta configuración correctamente, con el nombre de su biblioteca en lugar de la mía (que puede usar como un ejemplo), puede intentar publicar una versión de su biblioteca saborizada al intentar publicar primero en mavenLocal. Para hacerlo, ejecute este comando:

myLibrary $ ../gradlew publishToMavenLocal

Luego puede intentar agregar mavenLocal en los repositorios de su aplicación (ejemplo aquí) e intentar agregar su biblioteca como una dependencia (artifactId debe ser el nombre del tipo, con "_" reemplazado por "-") y compilarlo. También puede verificar con su explorador de archivos (use cmd+shift+G en Mac en Finder para acceder a la carpeta oculta) el directorio ~/.m2 y busca tu biblioteca.

Cuando llegue el momento de publicar en bintray / jcenter, solo tiene que ejecutar este comando:

myLibrary $ ../gradlew bintrayUpload

Importante:

Antes de publicar su biblioteca en mavenLocal, Bintray u otro repositorio maven, normalmente querrá probar su biblioteca con una aplicación de ejemplo que use la biblioteca. Esta aplicación de ejemplo, que debería ser otro módulo en el mismo proyecto solo necesita tener la dependencia del proyecto, que debería tener este aspecto: compile project(':myLibrary'). Sin embargo, dado que su biblioteca tiene varios sabores de productos, querrá probarlos todos. Desafortunadamente, actualmente es imposible especificar qué configuración desea usar del archivo build.gradle de su aplicación de ejemplo (a menos que use publishNonDefault true en el archivo build.gradle de su biblioteca, que rompe las publicaciones maven y bintray), pero puede especificar la configuración predeterminada (es decir, buildVariant) en el módulo de su biblioteca como tal: defaultPublishConfig "myLibraryDebug" en el cierre android. Puedes ver las variantes de compilación disponibles para tu biblioteca en las Ventanas de la herramienta" Construir variantes " en Android Studio.

, Siéntase libre de explorar mi biblioteca "Splitties" aquí si necesita un ejemplo. El módulo con sabor se llama concurrency, pero también uso mi script para módulos de biblioteca sin sabor, y lo probé completamente en todos los módulos de biblioteca de mi proyecto.

Puede ponerse en contacto conmigo si necesita ayuda para configurarlo para usted.

 11
Author: Louis CAD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-01 21:10:12

La configuración:

buildTypes {
  debug {
  }
  release {
  }
}

publishNonDefault true

La solución:

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

Esta corrección seguirá publicando todos los artefactos, pero publicará un artefacto predeterminado sin el sufijo sabor, que es suficiente para que todo funcione.

La solución para cargar solo el artefacto predeterminado sería esta (si el complemento bintray supiera qué son los filtros 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
    }
  }
}
 6
Author: Ricardo Freitas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-06 14:59:29

No lo intenté, así que eliminaré la respuesta si no resuelve el problema.

Debe publicar un artefacto diferente para cada sabor (o variante de compilación si lo prefiere).
De esta manera tendrá en jcenter x artefactos, cada uno de ellos con un archivo pom.

Algo como:

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

En su archivo de nivel superior puede definir

allprojects {
    repositories {
        jcenter()
    }

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

Luego en su módulo de biblioteca:

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

Finalmente asegúrese de publicar solo el tipo de compilación de la versión (¿por qué también la depuración versión?)

 3
Author: Gabriele Mariotti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-18 07:44:07

Si alguien todavía está atascado con este problema, esto es lo que funcionó para mí -

Digamos que desea publicar la compilación de la versión para su flavour1 agregue esto a su build.gradle

android {
    ...
    defaultPublishConfig "flavour1Release"
}

Elimina publishNonDefault true si está presente en tu archivo de gradle.

Añade esto dentro del bloque bintray así

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

Luego simplemente ejecute la tarea bintrayUpload como lo haría.

El defaultPublishConfig tendrá que ser cambiado cada vez que necesite publicar un nuevo sabor.

 2
Author: k1slay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-09 05:51:00

Parece que no quieres el clasificador en el nombre del archivo. Parece que el clasificador es el mismo que el nombre del archivo de biblioteca generado. ¿Ha intentado darles el mismo nombre de archivo pero enviándolos a directorios separados? Por ejemplo, en el ámbito de 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)
        }
    }
}
 1
Author: Jim Baca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-12 13:37:19