我试图通过使用自定义版本的gradle-release插件来模拟Android中的Maven发布插件:https://github.com/townsfolk/gradle-release
有趣的步骤是:
但是生成的APK总是具有以前的版本(即1.0.0-SNAPSHOT而不是1.0.0)。
版本号在gradle.properties中存储并正确更新,因此我假设我需要更新数据模型中的版本以使更改生效。
我的android插件配置:
defaultConfig {
versionCode versionCode as int // taken from gradle.properties
versionName versionName // taken from gradle.properties
minSdkVersion 10
targetSdkVersion 19
}
我试过的事情:
preBuild << {
android.applicationVariants.each { variant ->
variant.versionName = versionName
}
}
但是变体中没有versionName。
preBuild << {
android.buildTypes.each { type ->
type.versionName = versionName
}
}
但是类型中没有versionName。
preBuild << {
android.productFlavors.each { flavor ->
flavor.versionName = versionName
}
}
但是我的应用程序中没有任何风格(仅限普通的调试和发布版本类型)。
我的另一种方法是在调用Gradle之前编写一个bash / bat脚本来处理版本,这几乎违背了使用Groovy来改进构建自定义的目的。
如何在执行阶段在Android Gradle插件中动态更新版本?
这就是buildTypes
的用途。你所描述的是一个release
构建,IMO。
这是一个例子:当执行assembleDebug
时,它将为您提供快照构建,并且执行assembleRelease
将为您提供一个没有任何后缀和增加版本号的干净构建。下一个调试版本也将使用递增的数字。
在文件夹中创建文件时,以下是完整功能的构建。它也适用于口味,但这只是副产品:)。 Gradle 2.2.1,Android插件1.1.3
apply plugin: 'com.android.application'
apply from: 'auto-version.gradle'
buildscript {
repositories { jcenter() }
dependencies { classpath 'com.android.tools.build:gradle:1.1.3' }
}
android {
buildToolsVersion = "21.1.2"
compileSdkVersion = "android-21"
buildTypes {
debug {
versionNameSuffix "-SNAPSHOT"
}
}
}
println "config code: ${calculateVersionCode()}, name: ${calculateVersionName()}"
<manifest package="com.example" />
ext {
versionFile = new File(project.rootDir, 'version.properties')
calculateVersionName = {
def version = readVersion()
return "${version['major']}.${version['minor']}.${version['build']}"
}
calculateVersionCode = {
def version = readVersion()
def major = version['major'] as int // 1..∞
def minor = version['minor'] as int // 0..99
def build = version['build'] as int // 0..999
return (major * 100 + minor) * 1000 + build
}
}
Properties readVersion() {
def version = new Properties()
def stream
try {
stream = new FileInputStream(versionFile)
version.load(stream)
} catch (FileNotFoundException ignore) {
} finally {
if (stream != null) stream.close()
}
// safety defaults in case file is missing
if(!version['major']) version['major'] = "1"
if(!version['minor']) version['minor'] = "0"
if(!version['build']) version['build'] = "0"
return version
}
void incrementVersionNumber() {
def version = readVersion()
// careful with the types, culprits: "9"++ = ":", "9" + 1 = "91"
def build = version['build'] as int
build++
version['build'] = build.toString()
def stream = new FileOutputStream(versionFile)
try {
version.store(stream, null)
} finally {
stream.close()
}
}
task incrementVersion {
description "Increments build counter in ${versionFile}"
doFirst {
incrementVersionNumber()
}
}
if (plugins.hasPlugin('android') || plugins.hasPlugin('android-library')) {
android {
defaultConfig {
versionName = calculateVersionName()
versionCode = calculateVersionCode()
}
afterEvaluate {
def autoIncrementVariant = { variant ->
if (variant.buildType.name == buildTypes.release.name) { // don't increment on debug builds
variant.preBuild.dependsOn incrementVersion
incrementVersion.doLast {
variant.mergedFlavor.versionName = calculateVersionName()
variant.mergedFlavor.versionCode = calculateVersionCode()
}
}
}
if (plugins.hasPlugin('android')) {
applicationVariants.all { variant -> autoIncrementVariant(variant) }
}
if (plugins.hasPlugin('android-library')) {
libraryVariants.all { variant -> autoIncrementVariant(variant) }
}
}
}
}
执行gradle assembleDebug
正常构建,gradle assembleRelease
增加和构建,gradle incrementVersion
只增加。注意:小心使用gradle assemble
,因为assembleDebug
和assembleRelease
的顺序会产生不同的结果。
检查build
目录中生成的文件,看看这些值是否符合您的喜好。
您可能有多种风格,在这种情况下,版本会多次递增,因为多个变体与发布版本类型匹配。最初的问题是没有味道。如果您想在版本号递增时获得更多控制权,只需删除afterEvaluate
块并随时调用incrementVersion
任务:
gradle incrementVersion assembleFreeRelease assemblePaidRelease
(上面的手动执行是一个未经考验的想法。)
这个答案中没有涉及“检查未提交的更改”,这是另一个游戏。如果我理解正确,你可以挂钩到tasks.preBuild.doFirst { /*fail here if uncommited changes*/ }
。但这在很大程度上取决于您的版本控制。再问一个问题!
我需要将当前git提交的代码修订版附加到版本名称。它在很多情况下都很方便。我最终得到了以下简单的gradle文件
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
def gitCommitCount = "git rev-list HEAD --count".execute().text.trim()
defaultConfig {
applicationId "my.app.package.name"
minSdkVersion 16
targetSdkVersion 21
versionCode 6
versionName "0.8"
}
buildTypes {
debug {
versionNameSuffix ".${gitCommitCount}"
}
release {
versionNameSuffix ".${gitCommitCount}"
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
与gitCommitCount类似,您可以生成自己的变量来自定义版本名称。因为我只是执行一个终端命令来将其结果存储在一个变量中。
这并没有直接解决你如何完全更改versionName的问题,但这是我用来为我的buildTypes附加后缀的方法:
defaultConfig {
versionName "1.0"
}
buildTypes {
debug {
versionNameSuffix "-SNAPSHOT"
}
}
我只是使用Javanator's answer并对其进行了一些修改,以便提交计数不仅有助于更改名称,还可以确保版本代码也保持唯一。以下是我所做的一些示例(可能有一些事情可以优化,但仍然可以为我完成工作):
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
def gitCommitCount = "git rev-list HEAD --count".execute().text.trim().toBigInteger()
project.ext.set("versionCode", gitCommitCount)
project.ext.set("versionNameSuffix", "(${gitCommitCount})")
defaultConfig {
applicationId "my.app.package.name"
minSdkVersion 15
targetSdkVersion 25
versionCode project.versionCode
versionName "1.0"
versionNameSuffix project.versionNameSuffix
setProperty("archivesBaseName", "MyProject-$versionName")
....
}
signingConfigs {
config {
.........
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.config
}
}
packagingOptions {
.....
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(
output.outputFile.parent,
output.outputFile.name.replace(".apk", "-${variant.versionName}.apk"))
}
}
}
编辑:最后一点也可能是
applicationVariants.all { variant ->
if (variant.name.contains('release')) {
variant.outputs.each { output ->
variant.outputs.all {
outputFileName = "MyProject-${variant.versionName}${variant.versionCode}.apk"
}
}
}
}
我面临着为发布和非发布版本提供单独构建逻辑的类似需求。除了不同的版本控制,我不得不使用一组不同的依赖项,甚至是不同的存储库。
没有一个可用的插件具有我需要的所有功能,所以我基于简单的方法 - 命令行参数开发了我自己的解决方案。
您可以在调用gradle构建脚本时传递命令行参数,如下所示:
gradle build -PmyParameter=myValue
或者在我的情况下
gradle build -PisRelease=true
Gradle将解析它,它将自动作为项目对象的属性提供。然后你可以像这样使用它:
if (project.isRelease) {
// Here be the logic!
}
我将这个逻辑提取到一个单独的插件中,并且我已成功地在不同的项目中使用它。
虽然这不能直接回答你的问题,但我希望我给你另一个角度思考问题和另一个可能的解决方案。