問題描述
我正在嘗試使用自定義版本的 gradle-release 插件在 Android 中模擬 Maven 發布插件:https://github.com/townsfolk/gradle-release
I'm trying to emulate Maven release plugin in Android by using a customized version of gradle-release plugin: https://github.com/townsfolk/gradle-release
有趣的步驟是:
- 檢查未提交的更改
- 步驟版本代碼并刪除 -SNAPSHOT版本名稱的后綴
- 構建
- 步驟版本名稱并添加-SNAPSHOT下一個開發版本的后綴
但是生成的 APK 始終具有以前的版本(即 1.0.0-SNAPSHOT 而不是 1.0.0).
However the generated APK always has the previous versions (i.e. 1.0.0-SNAPSHOT instead of 1.0.0).
版本號在 gradle.properties 中存儲并正確更新,因此我假設我需要更新數據模型中的版本以及更改才能生效.
Version numbers are stored and correctly updated in gradle.properties, so I'm assuming that I need to update the versions in the data model as well for the changes to take effect.
我的安卓插件配置:
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.
But there's no versionName in a variant.
preBuild << {
android.buildTypes.each { type ->
type.versionName = versionName
}
}
但類型中沒有 versionName.
But there's no versionName in a type.
preBuild << {
android.productFlavors.each { flavor ->
flavor.versionName = versionName
}
}
但我的應用中沒有任何風格(僅限普通調試和發布構建類型).
But there are no flavors in my app (plain debug and release build types only).
我的替代方法是在調用 Gradle 之前編寫一個 bash/bat 腳本來步進版本,這幾乎違背了使用 Groovy 改進構建自定義的目的.
My alternative is to write a bash/bat script to step the versions before invoking Gradle, which pretty much defeats the purpose of using Groovy to improve build customization.
如何在Android Gradle插件的執行階段動態更新版本?
How can I update versions dynamically in the Android Gradle plugin in the execution phase?
推薦答案
這就是 buildTypes
的用途.你所描述的是一個 release
構建,IMO.
That's what buildTypes
are for. What you're describing is a release
build, IMO.
這是一個例子:當執行 assembleDebug
時,它會給你一個快照構建,而執行 assembleRelease
會給你一個干凈的構建,沒有任何后綴和遞增的版本號.下一個調試版本也將使用遞增的數字.
Here's an example: when executing assembleDebug
it will give you a snapshot build, and executing assembleRelease
will give you a clean build without any suffix and incremented version number. The next debug build will also use the incremented number.
以下是在文件夾中創建文件時功能齊全的構建.它也應該適用于口味,但這只是一個副產品:).Gradle 2.2.1,Android 插件 1.1.3
The following is a fully functional build when the files are created in a folder. It should also work with flavors, but that's just a side product :). Gradle 2.2.1, Android plugin 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()}"
src/main/AndroidManifest.xml
<manifest package="com.example" />
自動版本.gradle
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
的順序會產生不同的結果.
Execute gradle assembleDebug
to build normally, gradle assembleRelease
to increment and build, and gradle incrementVersion
to just increment.
Note: be careful with gradle assemble
because the order of assembleDebug
and assembleRelease
will yield different results.
檢查 build
目錄中生成的文件,看看這些值是否符合您的喜好.
Check the generated files in the build
directory to see if the values are to your liking.
您可能有多種風格,在這種情況下版本會多次遞增,因為多個變體與發布構建類型匹配.最初的問題是沒有味道.如果您想在版本號遞增時有更多控制權,只需刪除 afterEvaluate
塊并隨時調用 incrementVersion
任務:
It is possible you have multiple flavors in which case the version is incremented multiple times because multiple variants match the release build type. The original quesion was for no flavors. If you want to have more control when the version number is incremented just remove the afterEvaluate
block and call the incrementVersion
task whenever you want:
gradle incrementVersion assembleFreeRelease assemblePaidRelease
(上述手動執行是一個未經驗證的想法.)
(The above manual execution is an untested idea.)
此答案未涵蓋檢查未提交的更改",這是另一個游戲.如果我理解正確,您可以連接到 tasks.preBuild.doFirst {/*fail here if uncommited changes*