自动更改 versionCode

前言

在我们每次发布新包的时候,总是需要更改 versionName 和 versionCode,versionName 是展示给用户看的版本名字,所以,每次发布都需要更改,这个可以理解,但是 versionCode 基本都是自增,那有没有什么方式可以让其在发布的时候自增?

答案当然是可以的,不然这篇文章就不会发布出去了。

正文

首先,我们在 gradle.properties 中定义一个 APP_VERSION_CODE

然后在 build.gradle 更改 versionCode 为:

versionCode APP_VERSION_CODE as int

这样的话,只要我们更改 APP_VERSION_CODE 的值,打包出来的 versionCode 就会改变了。但是,这样还需要手动去改,想要自动的话,我们还需要一个 task(示例是在 build.gradle 中编写):

task updateVersionCode(){
    doFirst{
        // 获取 gradle.properties 文件
        def gradleProperties = file('../gradle.properties')
        // 读取里面的键值对
        def properties = new Properties()
        properties.load(new FileInputStream(gradleProperties))
        // 获取里面的 APP_VERSION_CODE 进行 +1
        def codeBumped = properties['APP_VERSION_CODE'].toInteger() + 1
        // 重新赋值
        properties['APP_VERSION_CODE'] = codeBumped.toString()
        // 写入
        properties.store(gradleProperties.newWriter(), null)
    }
}

至于要把代码放入 doFirst 中,是因为 task 的代码每次编译的时候都会执行的,但是 doFirst 和 doLast 是要等到这个 task 执行的时候才会执行,所以,这里也可以使用 doLast。

这时,我们可以运行这个 task 看下:

为了避免部分同学没有配置 gradle 命令,所以直接使用 Android Studio 图形化的进行演示:

双击运行。

我们再来查看下 gradle.properties 文件:

可以看到 APP_VERSION_CODE 是更改成功了!!!

但是,好像有什么不妥?

哦!没错!它直接把 gradle.properties 文件内容给全改了,之前的那些注释和顺序都被改动了!

所以,我们不能把 APP_VERSION_CODE 放到 gradle.properties 中,我们新建一个 version.properties 进行存放:

由于 build.gradle 无法直接读取 version.properties 文件里面的 APP_VERSION_CODE,所以,我们要改成闭包进行读取:

versionCode getMyAppVersionCode()
def getMyAppVersionCode() {  //获取APP版本号
    def gradleProperties = file('../version.properties')
    def properties = new Properties()
    properties.load(new FileInputStream(gradleProperties))
    def codeBumped = properties['APP_VERSION_CODE'].toInteger()
    return codeBumped as int
}

updateVersionCode task 无需改动:

task updateVersionCode(){
    doFirst{
        // 获取 gradle.properties 文件
        def gradleProperties = file('../version.properties')
        // 读取里面的键值对
        def properties = new Properties()
        properties.load(new FileInputStream(gradleProperties))
        // 获取里面的 APP_VERSION_CODE 进行 +1
        def codeBumped = properties['APP_VERSION_CODE'].toInteger() + 1
        // 重新赋值
        properties['APP_VERSION_CODE'] = codeBumped.toString()
        // 写入
        properties.store(gradleProperties.newWriter(), null)
    }
}

不过,我希望它能够在每次编译时都自动调用 updateVersionCode task,所以,需要添加这行:

preBuild.dependsOn(updateVersionCode)

好了,万事俱备了,我们把 APP_VERSION_CODE 改回为 1,并且双击 assembleRelease 试试,看看打出的 apk 的 versionCode 为多少。

至于如何查看 versionCode,可以使用 aapt,当然,还有最简单的方式,直接在 Android Studio 中打开即可:

em… 怎么 versionCode 还是 1…

我们来看看 version.properties

没错啊,确实是有改了。

我们添加日志输出看看,是不是执行顺序出错了:

task updateVersionCode(){
    doFirst{
        println("---------->updateVersionCode")
        ...
    }
}

preBuild.dependsOn(updateVersionCode)

def getMyAppVersionCode() {  //获取APP版本号
    println("---------->getMyAppVersionCode")
    ...
}

双击 assembleRelease

好吧,原来 getMyAppVersionCode 比 task 还早运行…

至于这个方案的解决方式,我想了很多,也请教了一些大佬,后来决定以一种取巧的方式进行解决,也就是在读取出来的 APP_VERSION_CODE 基础上 +1 :

def getMyAppVersionCode() {  //获取APP版本号
    def gradleProperties = file('../version.properties')
    def properties = new Properties()
    properties.load(new FileInputStream(gradleProperties))
    def codeBumped = properties['APP_VERSION_CODE'].toInteger() + 1
    return codeBumped as int
}

由此,之后构建出来的包,其 versionCode 就跟 APP_VERSION_CODE 保持一致了!

不过,现在还是有一个问题,那就是每次构建的时候都会调用 updateVersionCode,但其实,我们更加需要的是每次调用 assembleRelease 才会调用 updateVersionCode。

所以,我们需要把这个行进行删除:

preBuild.dependsOn(updateVersionCode)

添加这段:

project.tasks.whenTaskAdded { Task theTask ->
    if (theTask.name == 'assembleRelease') {
        theTask.dependsOn(updateVersionCode)
        theTask.mustRunAfter(updateVersionCode) // updateVersionCode在assembleRelease之前执行
    }
}

至此,该功能就全部完成了,以下为 build.gradle 的全部源码:

plugins {
    id 'com.android.application'
    id 'kotlin-android'
}

android {
    compileSdkVersion 31
    buildToolsVersion "30.0.3"

    defaultConfig {
        applicationId "com.bjsdm.testproject"
        minSdkVersion 16
        targetSdkVersion 30
        versionCode getMyAppVersionCode()
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {

    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.1'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

task updateVersionCode(){
    doFirst{
        // 获取 gradle.properties 文件
        def gradleProperties = file('../version.properties')
        // 读取里面的键值对
        def properties = new Properties()
        properties.load(new FileInputStream(gradleProperties))
        // 获取里面的 APP_VERSION_CODE 进行 +1
        def codeBumped = properties['APP_VERSION_CODE'].toInteger() + 1
        // 重新赋值
        properties['APP_VERSION_CODE'] = codeBumped.toString()
        // 写入
        properties.store(gradleProperties.newWriter(), null)
    }
}

project.tasks.whenTaskAdded { Task theTask ->
    if (theTask.name == 'assembleRelease') {
        theTask.dependsOn(updateVersionCode)
        theTask.mustRunAfter(updateVersionCode)				// updateVersionCode在assembleRelease之前执行
    }
}

//preBuild.dependsOn(updateVersionCode)


def getMyAppVersionCode() {  //获取APP版本号
    def gradleProperties = file('../version.properties')
    def properties = new Properties()
    properties.load(new FileInputStream(gradleProperties))
    def codeBumped = properties['APP_VERSION_CODE'].toInteger() + 1
    return codeBumped as int
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值