在开发的时候,需要给测试人员打包,此时就会涉及到一个版本问题,我们不希望release版本的versionCode被debug等buildTypes影响,这里就需要做到不同的buildType有不同的versionCode。
修改versionCode包含两个部分:
- BuildConfig里面的版本号
- 打包成apk之后,AndroidManifest.xml文件里面的android:versionCode里面的值
刚开始的时候,在buil.gralde里面只修改了BuildConfig里面的值,导致打包出来的apk里面的android:versionCode的值还是取的build.gralde里面的(versionCode 59)这个值
applicationVariants.all { variant ->
variant.outputs.all { output ->
def code = getAppVersionCode(variant.versionName)
variant.mergedFlavor.versionCode = code
}
}
应该还需要通过output.processManifest.doLast{}方法去修改AndroidManifest.xml里面的android:versionCode的值,下面附上完整修改versionCode代码,我这里只修改debugSign的versionCode,版本号取值的逻辑是取versionName里面的值,把"."去掉,按String方式拼接起来:
applicationVariants.all { variant -> //批量修改Apk名字
variant.outputs.all { output ->
if (!variant.buildType.isDebuggable()) {
//获取签名的名字 variant.signingConfig.name
//要被替换的源字符串
def sourceFile = "-${variant.flavorName}-${variant.buildType.name}"
//替换的字符串
def replaceFile = "_V${variant.versionName}_${variant.flavorName}_${variant.buildType.name}_${buildTime()}"
outputFileName = output.outputFile.name.replace(sourceFile, replaceFile)
//遗留问题:如何获取当前module的name,如CodeBooke这个名字怎么获取到
} else if (variant.buildType.name.equals("debugSign")) {
def code = getAppVersionCode(variant.versionName)
def originalVersionCode = variant.versionCode
//修改buildConfig中的versionCode
variant.mergedFlavor.versionCode = code
//修改AndroidManifest.xml文件中的versionCode字段
output.processManifest.doLast {
// Stores the path to the maifest.
String manifestPath = "$manifestOutputDirectory/AndroidManifest.xml"
// Stores the contents of the manifest.
def manifestContent = file(manifestPath).getText('UTF-8')
// Changes the version code in the stored text.
manifestContent = manifestContent.replace(
getManifestVersionMeta(originalVersionCode),
getManifestVersionMeta(code))
// Overwrites the manifest with the new text.
file(manifestPath).write(manifestContent, 'UTF-8')
}
}
}
}
/**
* 返回AndroidManifest.xml中versionCode元素
* @param verCode
* @return
*/
def getManifestVersionMeta(verCode) {
return String.format('android:versionCode="%s"', verCode)
}
/**
* 生成当前时间
* @return
*/
def buildTime() {
return new Date().format('yyyyMMdd')
}
/**
* 根据versionName算版本号
* @param shortVersionCode
* @return
*/
def getAppVersionCode(versionName) {
String vCode = ""
String[] version = versionName.split("\\.");
version.each { ver ->
if (ver.isInteger()) {
vCode += ver;
}
}
if (vCode.isEmpty()) {
vCode = "1";
}
return Integer.valueOf(vCode)
}
在这里需要注意的是:
def manifestContent = file(manifestPath).getText(‘UTF-8’)
file(manifestPath).write(manifestContent, ‘UTF-8’)
这里官方文档上没有指定编码格式(UTF-8),导致我在这里走了很久的弯路,最后在Stack Overflow上找到了答案。
适用gradle版本3.0;
参考资料:
Gradle 3.0官方API
gradlew 3.0解读一
gradlew 3.0解读二
注意需要指定字符编码格式,因为没有指定字符编码格式,导致我在这个问题上耗了很长时间;