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;
}
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.
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
}
}
}
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?)
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.
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)
}
}
}
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