【Gradle-11】动态修改VersionName和VersionCode

前言

有个读者问了一个比较有意思又很常见的问题,怎么修改VersionName和VersionCode?
读者.png
这位读者提问的方式也挺好,报错信息和尝试过的方式都提到了。
关于报错以及解决方案,正如上图我评论回复所说。

静态修改直接在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

https://github.com/yechaoa/GradleX

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Unity是一款跨平台的游戏引擎,支持多种平台的游戏开发。在Android平台上,Unity使用Gradle来构建项目。Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建工具。下面是关于Unity Gradle的介绍和演示: 1. Gradle版本 Unity使用的Gradle版本可以在以下路径中找到:C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Tools\gradle。 2. Gradle构建 Unity使用Gradle来构建Android项目。在Unity中,你可以通过File->Build Settings->Android来打开Android Build Settings窗口。在这个窗口中,你可以选择Gradle作为构建系统。选择Gradle后,你可以在Player Settings中设置Gradle的版本和构建类型。 3. Gradle依赖 在module的gradle文件中,你可以添加依赖。例如,如果你想添加Google Play Services库,你可以在module的gradle文件中添加以下代码: ```gradle dependencies { implementation 'com.google.android.gms:play-services:11.8.0' } ``` 4. AndroidManifest替换变量 在module的gradle文件中,你可以使用AndroidManifest替换变量。例如,如果你想在AndroidManifest中使用应用程序的版本号,你可以在module的gradle文件中添加以下代码: ```gradle android { defaultConfig { manifestPlaceholders = [appVersionCode: versionCode, appVersionName: versionName] } } ``` 然后,在AndroidManifest.xml文件中,你可以使用以下代码来引用这些变量: ```xml android:versionCode="${appVersionCode}" android:versionName="${appVersionName}" ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yechaoa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值