使用选定的风格将 Android 库 (aar) 发布到 Bintray
Posted
技术标签:
【中文标题】使用选定的风格将 Android 库 (aar) 发布到 Bintray【英文标题】:Publishing Android Library (aar) to Bintray with chosen flavors 【发布时间】:2016-03-23 18:02:24 【问题描述】:我刚刚在我的项目中添加了一些flavors
(或productFlavors
)。
事实是,当我将库发布到 bintray 时,所有风味都已上传(这很棒),但我无法使用它们。使用的插件是官方的here。
上传的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
,请参阅doc chapter 23.4.1.3。
我正在寻找一种解决方案来选择我要上传的口味。
我已经看过 bintray 示例(here 和 here)和 this,还有其他示例,但我仍然卡住了。
这是我当前的脚本:
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;
【问题讨论】:
您必须将每种风味更新为不同的工件。 @GabrieleMariotti 如何在 bintrayconfigurations
中指定风味?
我之前没试过。但是您必须在风味块内指定部分 bintray 配置以分配工件名称。
【参考方案1】:
我面临同样的挑战,这是我能做到的最好的:
在 bintray 插件中使用 mavenPublications
和 gradle maven-publish
插件,您可以将任何变体发布到 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 '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.nameJavadoc", 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.nameJavadocJar", type: Jar, dependsOn: javadoc)
description "Puts Javadoc for $variant.name in a jar."
classifier = 'javadoc'
from javadoc.destinationDir
def sourcesJar = task("$variant.nameSourcesJar", 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.flavorNameCompile"].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
我还需要在我的根项目的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'
现在,我终于可以在我有多个productFlavors
的android 库模块中使用它了。这是来自可发布库模块的 build.gradle
文件的 sn-p:
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
当您正确完成所有这些设置后,使用您的库名称而不是 mine's(您可以将其用作示例),您可以尝试通过首先发布到 mavenLocal 来尝试发布您的风味库版本. 为此,请运行以下命令:
myLibrary $ ../gradlew publishToMavenLocal
然后,您可以尝试在应用程序的存储库 (example here) 中添加 mavenLocal
并尝试将您的库添加为依赖项(artifactId 应该是风味名称,将“_”替换为“-”)并构建它。
您还可以使用文件资源管理器(在 Mac 上的 Finder 中使用 cmd+shift+G 访问隐藏文件夹)目录~/.m2
并查找您的库。
当需要发布到 bintray/jcenter 时,您只需运行以下命令:
myLibrary $ ../gradlew bintrayUpload
重要:
在您将库发布到 mavenLocal、Bintray 或其他 maven 存储库之前,您通常需要针对使用该库的示例应用程序尝试您的库。这个示例应用程序应该是同一个项目中的另一个模块,只需要具有项目依赖项,它应该如下所示:compile project(':myLibrary')
。但是,由于您的库有多个 productFlavor,因此您需要测试所有这些。不幸的是,目前无法从示例应用程序的 build.gradle
文件中指定要使用的配置(除非您在库的 build.gradle
文件中使用 publishNonDefault true
,这会破坏 maven 和 bintray 出版物),但您可以指定库模块中的默认配置(即 buildVariant):defaultPublishConfig "myLibraryDebug"
在 android
闭包中。您可以在 Android Studio 的“构建变体”工具 Windows 中查看您的库的可用构建变体。
如果您需要示例,请随时探索my library "Splitties" here。风味模块被命名为concurrency
,但我也将我的脚本用于未风味的库模块,并且我在项目中的所有库模块上对其进行了全面测试。
如果您需要帮助设置它,可以联系我。
【讨论】:
作为底部部分的注释,您可以通过指定missingDimensionStrategy 来让消费应用程序与正确的配置对齐,就像missingDimensionStrategy 'brand', 'XXX' missingDimensionStrategy 'environment', 'ZZZ'
感谢您的出色回答。我面临一个问题:在 ~/.m2 目录中,每种风味都有不同的 .jar 文件,但是当我运行 bintrayUpload 时,它会在每种产品风味的 jar 文件中上传相同的内容。
@VikramBhati 正如答案中所说,您需要在发布指定的风味之前更改defaultPublishConfig
。
@LouisCAD 我刚刚尝试了您所说的,但它仍在为所有口味上传相同的 .jar 文件。到目前为止,即使使用 defaultPublishConfig "abc" 运行 bintrayUpload,也会在 bintray 上发布所有风格。所以我不认为bintrayUpload中的defaultPublishConfig是否有任何影响。如果我遗漏了什么,请纠正我。
@LouisCAD 似乎已弃用 publishNonDefault。运行 bintrayUpload 时收到警告 - publishNonDefault 已弃用且不再有效。所有变体现已发布。【参考方案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
最后确保只发布发布构建类型(为什么还要发布调试版本?)
【讨论】:
好的,有了这个我可以将不同的口味上传到不同的 bintray 包。但是分类器还在这里,每个包都有所有的味道。 对不起,我不知道你用分类器指的是什么。我正在检查 jcenter 中的 pom 文件,您应该有 groupId/artifactId 来识别库。 是的,我有这个,但分类器也在这里,所以我在每个包上都有androidsdk-0.0.4-lightDebug.aar
和androidsdk-0.0.4-lightDebug.aar
。所以目前有两个问题。例如,分类器是lightDebug
。
你找到答案了吗?
不,我仍然上传了 4 个库(2 个版本和发布 + 调试版本),每次在 bintray 上发布新版本时,我都需要删除调试版本。【参考方案4】:
如果有人仍然遇到这个问题,这对我有用 -
假设您要发布您的 flavor1 的发布版本,请将其添加到您的 build.gradle
android
...
defaultPublishConfig "flavour1Release"
如果您的 gradle 文件中存在 publishNonDefault true
,请删除它。
像这样在bintray
块中添加这个
bintray
...
archivesBaseName = 'YOUR_ARTIFACT_ID'
...
然后像你一样运行bintrayUpload
任务。
defaultPublishConfig
每次您需要发布新风格时都必须更改。
【讨论】:
删除publishNonDefault true
会阻止该模块在调试中用于其他模块,这是一个好主意,但不能完全解决问题
是的,如果你想在调试中使用库模块,你将不得不使用defaultPublishConfig "flavour1Debug"
之类的东西。仅当您必须发布到 bintray 时才切换到 defaultPublishConfig "flavour1Release"
【参考方案5】:
听起来您不希望文件名中包含分类器。看起来分类器与生成的库文件名相同。您是否尝试过为它们提供相同的文件名但将它们输出到单独的目录? 例如。在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)
【讨论】:
这允许我更改 .aar 文件名(来自build/outputs/aar/androidsdk/
但不是 bintray 插件使用的那个,所以它没有帮助。以上是关于使用选定的风格将 Android 库 (aar) 发布到 Bintray的主要内容,如果未能解决你的问题,请参考以下文章
使用 AAR 和源 JAR 将 Android 库发布到 Maven