前言
做过安卓开发的都知道,app版本控制主要依赖于两个参数versionName和versionCode,它们在我们项目模块的gradle文件中配置。而以往在做升级时,我们都是手动的去修改这两个参数。这在多人合作开发中是很不提倡的,因为往往较大的项目gradle文件经常要做修改替换,容易弄混,很不方便。
后来我们习惯将这两个参数的值提取出来,放在全局的配置文件gradle.properties中,然后在build.gradle中引用配置文件中定义的参数,从而确保版本控制参数从build.gradle中剥离。
//以下代码在根目录的gradle.properties中
VERSION_NAME = 1.0.0
VERSION_CODE = 1
//以下代码在build.gradle的android{}中配置
defaultConfig {
...
versionCode Integer.parseInt(project.VERSION_CODE)
versionName project.VERSION_NAME
...
}
还有种方式也是同样的思路,把版本号的配置单独的抽取出来的,放在单独的文件里,供build引用,就像我们在Android里,单独新建一个存放常量的Java类一样,供其他类调用。我们新建一个version.gradle文件并在其中添加以下代码。
ext{
VERSION_NAME = 1.0.0
VERSION_CODE = 1
}
然后在build.gradle中通过apply from:'version.gradle'来引用该模块,最后同上在build.gradle的android{}中配置即可。
其实以上几种方式都大同小异,都需要通过人为去修改参数从而控制版本号。那么有没有什么方式来自动控制版本号,实现版本自增的操作呢?接下来就让我们一起来实现它。
实现
第一步:在app模块的根目录下新建一个version.properties,并在其中添加如下key-value。
version_major=0
version_minor=0
version_patch=1
version_build=0
version_name=v_0.0.1
version_code=1
这里解释以下这几个参数:
| 参数 | 说明 |
|---|---|
| version_major | 主版本号,除非有重大更新一般不需要去修改它 |
| version_minor | 副版本号,小版本更新时去手动自增 |
| version_patch | 补丁版本号,每次build正式版时会自动加一 |
| version_build | build版本号,每次build测试版时会自增,正式发布时会置为0,并且不会带上此版本号 |
| version_name | 根据规则自动拼接组合,不需要手动修改 |
| version_code | 根据规则自动拼接组合,不需要手动修改 |
第二步:在app模块的build.gradle文件中定义如下方法实现文件读写操作。
//读取操作
static Properties readProperties(propertiesFile) {
if (propertiesFile.canRead()) { //判断文件是否可读
Properties properties = new Properties()
def inputStream = new FileInputStream(propertiesFile)
properties.load(inputStream)
inputStream.close()
return properties
} else {
def message = "不能读取 " + propertiesFile.name + " 文件!"
System.err.println(message)
throw new GradleException(message)
}
}
//写入操作
def static writeProperties(propertiesFile, properties) {
def writer = propertiesFile.newWriter()
//这里的desc是生成文件时的描述内容,可自己定义。
def desc = "Automatic Properties\n" +
"Please do not arbitrarily change the parameter values under this file\n" +
"\t version_major: Major version number (manually modified when a major version is updated)\n" +
"\t version_minor: Minor version number (manually modified when the minor version is updated, the value range is 0~99)\n" +
"\t version_patch: Patch version number (automatically increase by 1 when the official version is released, please manually set 0 for modified size version, the value range is 0~999)\n" +
"\t version_build: Test version number (informal version will be automatically added by one, official version will be automatically removed and set to 0)\n" +
"\t version_name: Unmodifiable, automatically generated\n" +
"\t version_code: Unmodifiable, automatically generated"
properties.store(writer, desc)
writer.close()
}
第三步:在app模块的build.gradle文件中定义如下方法来判断build操作是正式还是测试。
//判断是否为单元测试或debug包
def isTestTask() {
def tasks = gradle.getStartParameter().getTaskNames()
return ":app:testDebugUnitTest" in tasks ||
"testDebugUnitTest" in tasks ||
":app:testReleaseUnitTest" in tasks ||
"testReleaseUnitTest" in tasks ||
":app:assembleDebug" in tasks ||
"assembleDebug" in tasks
}
//判断是否为正式包
def isReleaseTask() {
def tasks = gradle.getStartParameter().getTaskNames()
return ":app:assembleRelease" in tasks ||
"assembleRelease" in tasks ||
":app:bundleRelease" in tasks ||
"bundleRelease" in tasks
}
第四步:在app模块的build.gradle文件中定义如下方法实现版本控制(注意:这里生成的versionName和versionCode规则可以根据自己需求定)。
//自动更新版本信息
def updateVersion() {
def propertiesFile = file("version.properties")
Properties properties = readProperties(propertiesFile)
def versionMajor = properties["version_major"].toString().toInteger()
def versionMinor = properties["version_minor"].toString().toInteger()
def versionPatch = properties["version_patch"].toString().toInteger()
def versionBuild = properties["version_build"].toString().toInteger()
if (isReleaseTask()) { //正式版
versionPatch++
versionBuild = 0
}
if (isTestTask()) { //测试版
versionBuild++
}
def versionName = "v_${versionMajor}.${versionMinor}.${versionPatch}"
def versionCode = versionMajor * 100000 + versionMinor * 1000 + versionPatch
def applicationId = android.defaultConfig.applicationId
if (!isReleaseTask()) { //非正式包 加上build版本号
versionName = versionName + ".${versionBuild}"
applicationId = applicationId + "_"+android.buildTypes.debug.applicationIdSuffix
}
properties["version_major"] = versionMajor.toString()
properties["version_minor"] = versionMinor.toString()
properties["version_patch"] = versionPatch.toString()
properties["version_build"] = versionBuild.toString()
properties["version_name"] = versionName.toString()
properties["version_code"] = versionCode.toString()
writeProperties(propertiesFile, properties)
System.out.println(">>> " + project.parent.name + " " + versionName + " (" + versionCode + ") " + applicationId)
//配置根据自己规则计算好的versionCode和versionName到defaultConfig中
android.defaultConfig.versionCode = versionCode
android.defaultConfig.versionName = versionName
}
第五步:在app模块的build.gradle文件中android{}内合适的时机来调用此updateVersion()方法。
updateVersion() //必须在修改打包文件包名之前调用
//如果你需要修改打包后的文件名并带上versionName的话,则需要在其之前调用updateVersion()。
applicationVariants.all { variant ->
variant.outputs.all { output ->
if (variant.buildType.name.equals('release')) {
def releaseApkName = "_${defaultConfig.versionName}_" + 'release.apk'
outputFileName = releaseApkName
} else if (variant.buildType.name.equals("debug")) {
def releaseApkName = "_${defaultConfig.versionName}_" + 'debug.apk'
outputFileName = releaseApkName
}
}
}
至此,一个自动版本控制的配置已经完成了,现在我们试试成果。
成果
首先我们来试试打一个测试包,看下我们的version.properties文件是否发生了变化。
测试包返图.jpg
可以看到当我们打测试包时,version_build会自动加一,且version_name的值会带上version_build,由于测试包不发布所以version_code不变。
接下来我们打个正式包看看。
正式包返图.jpg
可以看到当我们打正式包时,version_build会清0,且version_name的值不会带上version_build,正式包的version_patch会自增,所以version_code也变大了。
补充
这里的version_major和version_minor还是需要开发者手动维护的,您也可以根据自己的逻辑定义方法来达到这两个参数的自动控制。











网友评论