前语
有个读者问了一个比较有意思又很常见的问题,怎么修正VersionName和VersionCode?
这位读者发问的方法也挺好,报错信息和尝试过的方法都提到了。
关于报错以及解决方案,正如上图我谈论回复所说。
静态修正直接在build.gradle文件改就好了,动态修正还是有点意思的。
可是这种需求也比较常见,比方加上git commit id啊,时刻戳啊等等,以便于区分,省的测验同学提了bug搞半天是包不对…
那么本文就来带咱们实践一下,以及探究有没有其他方法。
配置BuildType
咱们能够经过配置不同的BuildType
,然后使用versionNameSuffix
,分别设置对应的版别称号后缀。
buildTypes {
debug{
versionNameSuffix "-测验包"
}
release {
versionNameSuffix "-正式包"
}
}
现在的版别称号和版别号:
defaultConfig {
versionCode 1
versionName "1.0"
}
调用看看有没有收效:
override fun onResume() {
super.onResume()
val packageInfo = applicationContext.packageManager.getPackageInfo(applicationContext.packageName, 0)
Log.wtf("yechaoa", "versionName = " + packageInfo.versionName)
Log.wtf("yechaoa", "versionCode = " + packageInfo.versionCode)
}
输出:
E versionName = 1.0-测验包
E versionCode = 1
收效是收效了,可是这种方法能够改versionName,改不了versionCode,有必定局限性。
动态Property
这种呢,便是经过占位符的方法,原有的versionName和versionCode不是写死的,经过动态获取的方法来设置,咱们就能够打包脚本里加上VersionName的配置,以到达编译期动态修正的作用,这种方法在CI/CD
中比较常见。
先加两个方法来获取versionName和versionCode:
def getVersionNameByProperty() {
def name
if (hasProperty("VersionName") && getProperty('VersionName') != null) {
name = getProperties().get('VersionName')
} else {
name = "2.0-default"
}
return name
}
def getVersionCodeByProperty() {
def code
if (hasProperty("VersionCode") && getProperties().get('VersionCode') != null) {
code = getProperties().get('VersionCode')
} else {
code = 2
}
return code
}
defaultConfig引证方法:
defaultConfig {
versionCode getVersionCodeByProperty()
versionName getVersionNameByProperty()
}
如上,正常点击按钮编译versionName应该是”2.0-default”,versionCode应该是的2。
咱们编译看下是不是契合预期:
E versionName = 2.0-default-测验包
E versionCode = 2
契合预期,并且加上了咱们在buildType里面设置的后缀“测验包”。
那么接下来再用指令履行试试:
./gradlew installDebug -PVersionName=2.0-property
这儿只是加了-PVersionName,VerisonCode同理。
输出:
E versionName = 2.0-property-测验包
E versionCode = 2
能够看到,versionName由「2.0-default-测验包」变成「2.0-property-测验包」了,咱们的作用到达了。
Variants
variants
是变体的意思,在构建中通常用来配置不同的版别、不同的环境等,比方多渠道打包,上面刚介绍的buildType也是。
但这儿要介绍的variants方法,跟buildType的时刻要晚一些,是在Configuration
阶段,也便是拿到一切的variants之后再去改。
variants才能是Gradle提供的,在Android中对应的是applicationVariants
。
首要遍历一切variants,然后经过Flavor拿到versionName和versionCode,然后再赋值。
applicationVariants.configureEach { variant ->
def flavor = variant.mergedFlavor
flavor.versionName = '3.0'
flavor.versionCode = 3
}
结果编译报错:
Caused by: java.lang.RuntimeException: com.android.build.gradle.internal.crash.ExternalApiUsageException: com.android.builder.errors.EvalIssueException: versionName cannot be set on a mergedFlavor directly.
然后瞅了下源码,是MergedFlavor
里面抛出来的:
class MergedFlavor(
name: String,
private val _applicationId: Property<String>,
private val services: VariantServices
) : AbstractProductFlavor(name), InternalBaseVariant.MergedFlavor {
//...
override var versionCode: Int?
get() = super.versionCode
set(value) {
// calling setVersionCode results in a sync Error because the manifest merger doesn't pick
// up the change.
reportErrorWithWorkaround("versionCode", "versionCodeOverride", value)
}
override var versionName: String?
get() = super.versionName
set(value) {
// calling setVersionName results in a sync Error because the manifest merger doesn't pick
// up the change.
reportErrorWithWorkaround("versionName", "versionNameOverride", value)
}
private fun reportErrorWithWorkaround(
fieldName: String,
outputFieldName: String,
fieldValue: Any?
) {
val formattedFieldValue = if (fieldValue is String) {
""" + fieldValue + """
} else {
fieldValue.toString()
}
val message = """$fieldName cannot be set on a mergedFlavor directly.
|$outputFieldName can instead be set for variant outputs using the following syntax:
|android {
| applicationVariants.all { variant ->
| variant.outputs.each { output ->
| output.$outputFieldName = $formattedFieldValue
| }
| }
|}""".trimMargin()
services.issueReporter.reportError(IssueReporter.Type.GENERIC, message)
}
}
调用setVersionName会导致同步错误,清单文件接纳不到更新。
当然反常里面也给了解决方案,使用versionNameOverride
。
applicationVariants.configureEach { variant ->
variant.outputs.each { output ->
if (variant.buildType.name == "debug") {
output.versionNameOverride = "3.0"
output.versionCodeOverride = 3
}
}
}
然后咱们这儿还把versionName和versionCode升级了一下,再来试试。
输出:
E versionName = 3.0
E versionCode = 3
ok,这到达咱们想要作用了。
总结
本文经过BuildType、Property、Variants三种方法介绍了动态修正VersionCode和VersionName的方法,可是他们的机遇却有不同。
- BuildType:有局限性,仅能修正VersionName,无法修正VersionCode;
- Property:使用比较便利,在云编译场景比较常见,本地的话能够写在打包脚本里面;
- Variants:比较彻底,能完全掩盖,并且也能够抽成Plugin,可是如果有云编译的话,会导致云编译的更改失效;
最终
以上即是本文介绍内容,学废了吗,写作不易,记得三连~
GitHub
github.com/yechaoa/Gra…