由于我经常会忘记在打包时修改版本号, 所以就想着如果版本号不需要我每次修改就好了

最近才知道, Gradle基于Groovy, 是可以执行一些代码获取数据, 然后再用返回值作为配置属性的, 所以也就动手折腾了一波


比较常见的方案是, 将git提交次数作为versionCode, 将git tag作为versionName, 我采用的也是这种方案

在build.gradle中编写两个方法, 分别用来获取git提交次数和tag:

static def gitVersionCode() {
    def cmd = 'git rev-list HEAD --first-parent --count'
    cmd.execute().text.trim().toInteger()
}
static def gitVersionTag() {
    def cmd = 'git describe --tags'
    cmd.execute().text.trim().split('-')[0]
}

设置tag时可能会出现这种情况: tag是1.2.3, 通过"git describe --tags"获得的是1.2.3-1-gXXXXX, 所以在gitVersionTag()中调用了split并使用第一个数值, 这样就能得到tag原文

修改versionCode和versionName的定义:

android {
    defaultConfig {
        versionCode gitVersionCode()
        versionName gitVersionTag()
    }
}

我个人喜欢在debug编译就看到版本号变化, 所以直接写在了defaultConfig里, 如果希望只在release编译才动态获取版本号, 可以这样写:

android {
    applicationVariants.all { variant ->
        if (variant.buildType.name == 'release') {
            variant.outputs.each { output ->
                output.versionCodeOverride = gitVersionCode()
                output.versionNameOverride = gitVersionTag()
            }
        }
    }
}

注意, 网上有人给出的写法是这样的:

variant.mergedFlavor.versionCode = gitVersionCode()
variant.mergedFlavor.versionName = gitVersionTag()

这个写法在最新版本的Gradle里是不允许的, 会在sync的时候报错


初次之外, 测试人员还希望我编译内测版本的时候把时间加上, 这样他好判断自己有没有在拿最新版本来测bug

所以我创建了一个flavor, 定义versionNameSuffix, 实现在现有版本号后面再加上一串文本

代码如下:

android {
    flavorDimensions "default"
    productFlavors {
        _dev {
            versionNameSuffix " dev${new SimpleDateFormat("MMddHHmm").format(new Date())}"
        }
    }
}

这样我需要变更版本号的时候, 只需要在git里打上tag就行, 平常打包内测版本的时候也不需要改Gradle配置了