How to autoincrement versionCode in Android Gradle

送分小仙女□ 提交于 2019-12-17 04:10:34

问题


I'm experimenting with new Android build system based on Gradle and I'm thinking, what is the best way to autoincrease versionCode with it. I am thinking about two options

  1. create versionCode file, read number from it, increase it and write it back to the file
  2. parse AndroidManifest.xml, read versionCode from it, increase it and write it back to the AndroidManifest.xml

Is there any more simple or suitable solution?

Has anyone used one of mentiod options and could share it with me?


回答1:


I have decided for second option - to parse AndroidManifest.xml. Here is working snippet.

task('increaseVersionCode') << {
    def manifestFile = file("AndroidManifest.xml")
    def pattern = Pattern.compile("versionCode=\"(\\d+)\"")
    def manifestText = manifestFile.getText()
    def matcher = pattern.matcher(manifestText)
    matcher.find()
    def versionCode = Integer.parseInt(matcher.group(1))
    def manifestContent = matcher.replaceAll("versionCode=\"" + ++versionCode + "\"")
    manifestFile.write(manifestContent)
}

tasks.whenTaskAdded { task ->
    if (task.name == 'generateReleaseBuildConfig') {
        task.dependsOn 'increaseVersionCode'
    }
}

versionCode is released for release builds in this case. To increase it for debug builds change task.name equation in task.whenTaskAdded callback.




回答2:


I'm using this code to update both versionCode and versionName, using a "major.minor.patch.build" scheme.

import java.util.regex.Pattern

task('increaseVersionCode') << {
    def manifestFile = file("src/main/AndroidManifest.xml")
    def pattern = Pattern.compile("versionCode=\"(\\d+)\"")
    def manifestText = manifestFile.getText()
    def matcher = pattern.matcher(manifestText)
    matcher.find()
    def versionCode = Integer.parseInt(matcher.group(1))
    def manifestContent = matcher.replaceAll("versionCode=\"" + ++versionCode + "\"")
    manifestFile.write(manifestContent)
}

task('incrementVersionName') << {
    def manifestFile = file("src/main/AndroidManifest.xml")
    def patternVersionNumber = Pattern.compile("versionName=\"(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)\"")
    def manifestText = manifestFile.getText()
    def matcherVersionNumber = patternVersionNumber.matcher(manifestText)
    matcherVersionNumber.find()
    def majorVersion = Integer.parseInt(matcherVersionNumber.group(1))
    def minorVersion = Integer.parseInt(matcherVersionNumber.group(2))
    def pointVersion = Integer.parseInt(matcherVersionNumber.group(3))
    def buildVersion = Integer.parseInt(matcherVersionNumber.group(4))
    def mNextVersionName = majorVersion + "." + minorVersion + "." + pointVersion + "." + (buildVersion + 1)
    def manifestContent = matcherVersionNumber.replaceAll("versionName=\"" + mNextVersionName + "\"")
    manifestFile.write(manifestContent)
}

tasks.whenTaskAdded { task ->
    if (task.name == 'generateReleaseBuildConfig' || task.name == 'generateDebugBuildConfig') {
        task.dependsOn 'increaseVersionCode'
        task.dependsOn 'incrementVersionName'
    }
}



回答3:


it doesn't seem to be the exact setup you're using, but in my case the builds are being run by jenkins and i wanted to use its $BUILD_NUMBER as the app's versionCode. the following did the trick for me there.

defaultConfig {
    ...
    versionCode System.getenv("BUILD_NUMBER") as Integer ?: 9999
    ...
}



回答4:


I am using time stamp for the version code:

def date = new Date()
def formattedDate = date.format('yyMMddHHmm')
def code = formattedDate.toInteger()

defaultConfig {
    minSdkVersion 10
    targetSdkVersion 21
    versionCode code
}



回答5:


If you are holding the version code in the build.gradle file use the next snippet:

import java.util.regex.Pattern    
task('increaseVersionCode') << {
    def buildFile = file("build.gradle")
    def pattern = Pattern.compile("versionCode\\s+(\\d+)")
    def manifestText = buildFile.getText()
    def matcher = pattern.matcher(manifestText)
    matcher.find()
    def versionCode = Integer.parseInt(matcher.group(1))
    def manifestContent = matcher.replaceAll("versionCode " + ++versionCode)
    buildFile.write(manifestContent)
}



回答6:


To take both product flavors and build types into account and using @sealskej's logic for parsing manifest:

android.applicationVariants.all { variant ->
    /* Generate task to increment version code for release */
    if (variant.name.contains("Release")) {
        def incrementVersionCodeTaskName = "increment${variant.name}VersionCode"
        task(incrementVersionCodeTaskName) << {
            if (android.defaultConfig.versionCode == -1) {
                def manifestFile = file(android.sourceSets.main.manifest.srcFile)
                def pattern = Pattern.compile("versionCode=\"(\\d+)\"")
                def manifestText = manifestFile.getText()
                def matcher = pattern.matcher(manifestText)
                matcher.find()
                def versionCode = Integer.parseInt(matcher.group(1))
                android.defaultConfig.versionCode = versionCode + 1
                def manifestContent = matcher.replaceAll("versionCode=\"" + android.defaultConfig.versionCode + "\"")
                manifestFile.write(manifestContent)
            }
        }
        def hookTask = variant.generateBuildConfig
        hookTask.dependsOn(incrementVersionCodeTaskName)
    }
}



回答7:


Gradle Advanced Build Version is a plugin for Android that makes generating versionCode and versionName automatically. there are lots of customization. here you can find more info about it https://github.com/moallemi/gradle-advanced-build-version




回答8:


Increment VersionCode Task(Integer):

This works by incrementing the Version Code by 1, for example:

  android:versionCode="1"
1 + 1 = 2
import java.util.regex.Pattern

task incrementVersionCode << {
    def manifestFile = file('AndroidManifest.xml')
    def matcher = Pattern.compile('versionCode=\"(\\d+)\"')
    .matcher(manifestFile.getText())
    matcher.find()
    def manifestContent = matcher.replaceAll('versionCode=\"' +
        ++Integer.parseInt(matcher.group(1)) + '\"')
    manifestFile.write(manifestContent)
}

Increment VersionName Task(String):

Warning: Must contain 1 period for Regex

This works by incrementing the Version Name by 0.01, for example: You can easily modify and change your increment or add more digits.

android:versionName="1.0"
1.00 + 0.01 -> 1.01
1.01 + 0.01 -> 1.02
1.10 + 0.01 -> 1.11
1.99 + 0.01 -> 2.0
1.90 + 0.01 -> 1.91
import java.util.regex.Pattern

task incrementVersionName << {
    def manifestFile = file('AndroidManifest.xml')
    def matcher = Pattern.compile('versionName=\"(\\d+)\\.(\\d+)\"')
    .matcher(manifestFile.getText())
    matcher.find()
    def versionName = String.format("%.2f", Integer
        .parseInt(matcher.group(1)) + Double.parseDouble("." + matcher
            .group(2)) + 0.01)
    def manifestContent = matcher.replaceAll('versionName=\"' +
        versionName + '\"')
    manifestFile.write(manifestContent)
}

Before:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.exmaple.test"
    android:installLocation="auto"
    android:versionCode="1"
    android:versionName="1.0" >

After:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.exmaple.test"
    android:installLocation="auto"
    android:versionCode="2"
    android:versionName="1.01" >



回答9:


If you write your versionCode in gradle.build file(most case currently), here is a workaround. A little bit stupid(update "self"), but it works!

import java.util.regex.Pattern

task('increaseVersionCode') << {
    def buildFile = file("build.gradle")
    def pattern = Pattern.compile("versionCode(\\s+\\d+)")
    def buildText = buildFile.getText()
    def matcher = pattern.matcher(buildText)
    matcher.find()
    def versionCode = android.defaultConfig.versionCode
    def buildContent = matcher.replaceAll("versionCode " + ++versionCode)
    buildFile.write(buildContent)

    System.out.println("Incrementing Version Code ===> " + versionCode)
}

tasks.whenTaskAdded { task ->
    if (task.name == 'generateReleaseBuildConfig') {
        task.dependsOn 'increaseVersionCode'
    }
}



回答10:


To add on to @sealskej's post, this is how you can update both your version code and version name (Here I'm assuming your major and minor version are both 0):

task('increaseVersion') << {
    def manifestFile = file("AndroidManifest.xml")
    def patternVersionCode = Pattern.compile("versionCode=\"(\\d+)\"")
    def manifestText = manifestFile.getText()
    def matcherVersionCode = patternVersionCode.matcher(manifestText)
    matcherVersionCode.find()
    def versionCode = Integer.parseInt(matcherVersionCode.group(1))
    def manifestContent = matcherVersionCode.replaceAll("versionCode=\"" + ++versionCode + "\"")

    manifestFile.write(manifestContent)

    def patternVersionNumber = Pattern.compile("versionName=\"0.0.(\\d+)\"")
    manifestText = manifestFile.getText()
    def matcherVersionNumber = patternVersionNumber.matcher(manifestText)
    matcherVersionNumber.find()
    def versionNumber = Integer.parseInt(matcherVersionNumber.group(1))
    manifestContent = matcherVersionNumber.replaceAll("versionName=\"0.0." + ++versionNumber + "\"")
    manifestFile.write(manifestContent)
}



回答11:


what about this ? add to build.gradle (app module)

def getBuildVersionCode() {
    def date = new Date()
    def formattedDate = date.format('yyyyMMdd')
    def formattedSeconds = date.format('HHmmssSSS')
    def formatInt = formattedDate as int;
    def SecondsInt = formattedSeconds as int;
    return (formatInt + SecondsInt) as int
}

   defaultConfig {
    applicationId "com.app"
    minSdkVersion 17
    targetSdkVersion 22
    versionCode getBuildVersionCode()
    versionName "1.0"
}



回答12:


So as I was looking into most of the solution, they were nice but not enough so I wrote this, one increment per multi-deploy:

This will increment the build when compiling debug versions, and increment the point and version code when deploying.

import java.util.regex.Pattern

def incrementVersionName(int length, int index) {
    def gradleFile = file("build.gradle")
    def versionNamePattern = Pattern.compile("versionName\\s*\"(.*?)\"")
    def gradleText = gradleFile.getText()
    def matcher = versionNamePattern.matcher(gradleText)
    matcher.find()

    def originalVersion = matcher.group(1)
    def originalVersionArray = originalVersion.split("\\.")
    def versionKeys = [0, 0, 0, 0]
    for (int i = 0; i < originalVersionArray.length; i++) {
        versionKeys[i] = Integer.parseInt(originalVersionArray[i])
    }
    def finalVersion = ""
    versionKeys[index]++;
    for (int i = 0; i < length; i++) {
        finalVersion += "" + versionKeys[i]
        if (i < length - 1)
            finalVersion += "."
    }

    System.out.println("Incrementing Version Name: " + originalVersion + " ==> " + finalVersion)

    def newGradleContent = gradleText.replaceAll("versionName\\s*\"(.*?)\"", "versionName \"" + finalVersion + "\"")
    gradleFile.write(newGradleContent)
}

def incrementVersionCode() {
    def gradleFile = file("build.gradle")
    def versionCodePattern = Pattern.compile("versionCode\\s*(\\d+)")
    def gradleText = gradleFile.getText()
    def matcher = versionCodePattern.matcher(gradleText)
    matcher.find()

    def originalVersionCode = Integer.parseInt(matcher.group(1) + "")
    def finalVersionCode = originalVersionCode + 1;
    System.out.println("Incrementing Version Code: " + originalVersionCode + " ==> " + finalVersionCode)

    def newGradleContent = gradleText.replaceAll("versionCode\\s*(\\d+)", "versionCode " + finalVersionCode)
    gradleFile.write(newGradleContent)
}

task('incrementVersionNameBuild') << {
    incrementVersionName(4, 3)
}

task('incrementVersionNamePoint') << {
    incrementVersionName(3, 2)
}

task('incrementVersionCode') << {
    incrementVersionCode()
}


def incrementedBuild = false
def incrementedRelease = false

tasks.whenTaskAdded { task ->
    System.out.println("incrementedRelease: " + incrementedRelease)
    System.out.println("incrementedBuild: " + incrementedBuild)
    System.out.println("task.name: " + task.name)

    if (!incrementedBuild && task.name.matches('generate.*?DebugBuildConfig')) {
        task.dependsOn 'incrementVersionNameBuild'
        incrementedBuild = true
        return
    }

    if (!incrementedRelease && task.name.matches('generate.*?ReleaseBuildConfig')) {
        task.dependsOn 'incrementVersionCode'
        task.dependsOn 'incrementVersionNamePoint'
        incrementedRelease = true
        return
    }
}



回答13:


My approach is to read manifest file from build folder and get buildVersion out of there, than I delete a folder. When task creates new manifest, my incremented buildVersion variable is already there.

def versionPattern = "Implementation-Version=(\\d+.\\d+.\\d+.\\d+\\w+)"

task generateVersion (dependsOn : 'start') {
    // read build version from previous manifest
    def file = file("build/libs/MANIFEST.MF")
    if (file.exists()) {
        def pattern = Pattern.compile(versionPattern)
        def text = file.getText()
        def matcher = pattern.matcher(text)
        matcher.find()
        buildNumber = Integer.parseInt(matcher.group(1))
        // increment build version
        version = "${majorVer}.${minorVer}.${patchVer}.${++buildNumber}${classifier}_${access}"
    } 
    else 
        version = "${majorVer}.${minorVer}.${patchVer}.1${classifier}_${access}"
}

task specifyOutputDir (dependsOn : 'generateVersion', type : JavaCompile) {
    // create a folder for new build
    destinationDir = file("build/${version}/")
}

task clean (dependsOn : 'generateVersion', type : Delete) {
    doLast {
        delete "build/${version}"
        println 'Build directory is deleted'
    }
}

task configureJar (dependsOn : 'generateVersion', type : Jar) {
    baseName = applicationName
    version = project.version
    archiveName = "${applicationName}_ver${version}.${extension}"
    manifest {[
            "Main-Class" : mainClassName,
            "Implementation-Title" : name,
            "Implementation-Version" : version,
            "Access" : access,
            "Developer" : developer
    ]}
}


来源:https://stackoverflow.com/questions/17448565/how-to-autoincrement-versioncode-in-android-gradle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!