自动增加带有gradle额外属性的VersionCode

我正在用Gradle构build一个Android应用程序。 到目前为止,我使用Manifest文件来增加versionCode,但是我想从外部文件中读取versionCode,并根据它是释放风格还是debugging风格来增加versionCode。 我尝试了额外的属性,但你不能保存它们,这意味着下一次我build立它,我得到相同的versionCode。 任何帮助将非常感激!

project.ext{ devVersionCode = 13 releaseVersionCode = 1 } buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.6.+' } } apply plugin: 'android' repositories { mavenCentral() } dependencies { compile project(':Cropper') compile "com.android.support:appcompat-v7:18.0.+" compile "com.android.support:support-v4:18.0.+" compile fileTree(dir: 'libs', include: '*.jar') } def getReleaseVersionCode() { def version = project.releaseVersionCode + 1 project.releaseVersionCode = version println sprintf("Returning version %d", version) return version } def getDevVersionCode() { def version = project.devVersionCode + 1 project.devVersionCode = version println sprintf("Returning version %d", version) return version } def getLastVersioName(versionCode) { return "0.0." + versionCode } android { compileSdkVersion 19 buildToolsVersion "19.0.0" defaultConfig { minSdkVersion 9 targetSdkVersion 19 } sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] resources.srcDirs = ['src'] aidl.srcDirs = ['src'] renderscript.srcDirs = ['src'] res.srcDirs = ['res'] assets.srcDirs = ['assets'] } } buildTypes { release { runProguard true proguardFile getDefaultProguardFile('proguard-android-optimize.txt') proguardFile 'proguard.cfg' debuggable false signingConfig null zipAlign false } debug { versionNameSuffix "-DEBUG" } } productFlavors { dev { packageName = 'com.swisscom.docsafe.debug' versionCode getDevVersionCode() versionName getLastVersioName(project.devVersionCode) } prod { packageName = 'com.swisscom.docsafe' versionCode getReleaseVersionCode() versionName getLastVersioName(project.releaseVersionCode) } } } task wrapper(type: Wrapper) { gradleVersion = '1.8' } 

我想从外部文件读取versionCode

我相信有很多可能的解决办法。 这里是一个:

 android { compileSdkVersion 18 buildToolsVersion "18.1.0" def versionPropsFile = file('version.properties') if (versionPropsFile.canRead()) { def Properties versionProps = new Properties() versionProps.load(new FileInputStream(versionPropsFile)) def code = versionProps['VERSION_CODE'].toInteger() + 1 versionProps['VERSION_CODE']=code.toString() versionProps.store(versionPropsFile.newWriter(), null) defaultConfig { versionCode code versionName "1.1" minSdkVersion 14 targetSdkVersion 18 } } else { throw new GradleException("Could not read version.properties!") } // rest of android block goes here } 

这段代码需要一个现有的version.properties文件,在第一次构build之前手动创buildVERSION_CODE=8

这个代码只是在每个版本上碰到版本代码 – 你需要扩展这个技术来处理每个版本的代码。

您可以看到演示此代码的整个示例项目 。

我想让versionName自动增加。 所以这只是CommonsWare对我完美工作的补充。 这对我有用

 defaultConfig { versionCode code versionName "1.1." + code minSdkVersion 14 targetSdkVersion 18 } 

编辑:

由于我有点懒,我想我的版本尽可能自动工作。 我想要的是随着每个版本的增加版本版本 ,而版本号版本名称只增加,当我发布版本。

这是我一年来一直在使用的,基本上来自CommonsWare的回答和我以前的回答,再加上一些。 这导致了以下版本:

版本名称: 1.0.5(123) – > Major.Minor.Patch(Build),Major和Minor被手动更改。

在build.gradle:

 ... android { compileSdkVersion 23 buildToolsVersion '23.0.1' def versionPropsFile = file('version.properties') if (versionPropsFile.canRead()) { def Properties versionProps = new Properties() versionProps.load(new FileInputStream(versionPropsFile)) def value = 0 def runTasks = gradle.startParameter.taskNames if ('assemble' in runTasks || 'assembleRelease' in runTasks || 'aR' in runTasks) { value = 1; } def versionMajor = 1 def versionMinor = 0 def versionPatch = versionProps['VERSION_PATCH'].toInteger() + value def versionBuild = versionProps['VERSION_BUILD'].toInteger() + 1 def versionNumber = versionProps['VERSION_NUMBER'].toInteger() + value versionProps['VERSION_PATCH'] = versionPatch.toString() versionProps['VERSION_BUILD'] = versionBuild.toString() versionProps['VERSION_NUMBER'] = versionNumber.toString() versionProps.store(versionPropsFile.newWriter(), null) defaultConfig { versionCode versionNumber versionName "${versionMajor}.${versionMinor}.${versionPatch} (${versionBuild}) Release" minSdkVersion 14 targetSdkVersion 23 } applicationVariants.all { variant -> variant.outputs.each { output -> def fileNaming = "apk/RELEASES" variant.outputs.each { output -> def outputFile = output.outputFile if (outputFile != null && outputFile.name.endsWith('.apk')) { output.outputFile = new File(getProject().getRootDir(), "${fileNaming}-${versionMajor}.${versionMinor}.${versionPatch}-${outputFile.name}") } } } } } else { throw new GradleException("Could not read version.properties!") } ... } ... 

如果你用'assemble''assembleRelease''aR'在你的项目根目录下创build一个叫做apk / RELEASE的新文件夹,你可以增加patch和versionCode,所以你不必查看构build/输出/ more / more / morefind你的apk。

您的版本属性将需要如下所示:

 VERSION_NUMBER=1 VERSION_BUILD=645 VERSION_PATCH=1 

显然从0开始。

如果版本文件不存在,CommonsWare的优秀答案的稍微收紧的版本将创build版本文件:

 def Properties versionProps = new Properties() def versionPropsFile = file('version.properties') if(versionPropsFile.exists()) versionProps.load(new FileInputStream(versionPropsFile)) def code = (versionProps['VERSION_CODE'] ?: "0").toInteger() + 1 versionProps['VERSION_CODE'] = code.toString() versionProps.store(versionPropsFile.newWriter(), null) defaultConfig { versionCode code versionName "1.1" minSdkVersion 14 targetSdkVersion 18 } 

我看了几个选项来做到这一点,并最终决定使用versionCode的当前时间更简单,而不是试图自动递增versionCode并将其检入到我的版本控制系统中。

将以下内容添加到您的build.gradle

 /** * Use the number of seconds/10 since Jan 1 2016 as the versionCode. * This lets us upload a new build at most every 10 seconds for the * next 680 years. */ def vcode = (int)(((new Date().getTime()/1000) - 1451606400) / 10) android { defaultConfig { ... versionCode vcode } } 

但是,如果您希望在2696年以后上传构build版本,则可能需要使用其他解决scheme。

最近我正在为Android生成一个gradle插件,它会自动生成versionCodeversionName 。 有很多的定制。 在这里你可以find更多关于它的信息https://github.com/moallemi/gradle-advanced-build-version

另一种自动获取versionCode是将versionCode设置为签出的git分支中的提交数量。 它完成了以下目标:

  1. versionCode是在任何机器(包括Continuous Integration和/或Continuous Deployment服务器)上自动且一致地生成的。
  2. 使用此versionCode应用可以提交给GooglePlay。
  3. 不依赖于回购之外的任何文件。
  4. 不推回任何东西回购
  5. 如果需要,可以手动重写

使用gradle-git库来完成上述目标。 将以下代码添加到您的build.gradle文件/app目录中:

 import org.ajoberstar.grgit.Grgit repositories { mavenCentral() } buildscript { repositories { mavenCentral() } dependencies { classpath 'org.ajoberstar:grgit:1.5.0' } } android { /* if you need a build with a custom version, just add it here, but don't commit to repo, unless you'd like to disable versionCode to be the number of commits in the current branch. ex. project.ext.set("versionCodeManualOverride", 123) */ project.ext.set("versionCodeManualOverride", null) defaultConfig { versionCode getCustomVersionCode() } } def getCustomVersionCode() { if (project.versionCodeManualOverride != null) { return project.versionCodeManualOverride } // current dir is <your proj>/app, so it's likely that all your git repo files are in the dir // above. ext.repo = Grgit.open(project.file('..')) // should result in the same value as running // git rev-list <checked out branch name> | wc -l def numOfCommits = ext.repo.log().size() return numOfCommits } 

注意:要使此方法起作用,最好只从同一分支(例如master )部署到Google Play商店。

另一个选项,用于增加versionCodeversionName ,使用时间戳。

 defaultConfig { versionName "${getVersionNameTimestamp()}" versionCode getVersionCodeTimestamp() } def getVersionNameTimestamp() { return new Date().format('yy.MM.ddHHmm') } def getVersionCodeTimestamp() { def date = new Date() def formattedDate = date.format('yyMMddHHmm') def code = formattedDate.toInteger() println sprintf("VersionCode: %d", code) return code } 

从1月份开始,1 2022 formattedDate = date.format('yyMMddHHmm')超过Integers的容量

仅在发行版本中增加versionCode才可以:

 android { compileSdkVersion 21 buildToolsVersion "21.1.2" def versionPropsFile = file('version.properties') def code = 1; if (versionPropsFile.canRead()) { def Properties versionProps = new Properties() versionProps.load(new FileInputStream(versionPropsFile)) List<String> runTasks = gradle.startParameter.getTaskNames(); def value = 0 for (String item : runTasks) if ( item.contains("assembleRelease")) { value = 1; } code = Integer.parseInt(versionProps['VERSION_CODE']).intValue() + value versionProps['VERSION_CODE']=code.toString() versionProps.store(versionPropsFile.newWriter(), null) } else { throw new GradleException("Could not read version.properties!") } defaultConfig { applicationId "com.pack" minSdkVersion 14 targetSdkVersion 21 versionName "1.0."+ code versionCode code } 

需要一个现有的c://YourProject/app/version.properties文件,在第一次构build之前手动创buildVERSION_CODE=8

文件version.properties

VERSION_CODE=8

创build文件version.properties

 MAJOR=1 MINOR=3 PATCH=6 VERSION_CODE=1 

更改build.gradle

 android { def _versionCode=0 def _major=0 def _minor=0 def _patch=0 def _applicationId = "com.example.test" def versionPropsFile = file('version.properties') if (versionPropsFile.canRead()) { def Properties versionProps = new Properties() versionProps.load(new FileInputStream(versionPropsFile)) _patch = versionProps['PATCH'].toInteger() + 1 _major = versionProps['MAJOR'].toInteger() _minor = versionProps['MINOR'].toInteger() _versionCode= versionProps['VERSION_CODE'].toInteger()+1 if(_patch==99) { _patch=0 _minor=_minor+1 } if(_major==99){ _major=0 _major=_major+1 } versionProps['MAJOR']=_major.toString() versionProps['MINOR']=_minor.toString() versionProps['PATCH']=_patch.toString() versionProps['VERSION_CODE']=_versionCode.toString() versionProps.store(versionPropsFile.newWriter(), null) } else { throw new GradleException("Could not read version.properties!") } def _versionName = "${_major}.${_versionCode}.${_minor}.${_patch}" compileSdkVersion 23 buildToolsVersion "23.0.3" defaultConfig { applicationId _applicationId minSdkVersion 11 targetSdkVersion 23 versionCode _versionCode versionName _versionName } 

}

输出: 1.1.3.6

AndroidManifest.xml定义versionName

 android:versionName="5.1.5" 

在应用程序级别的build.gradleandroid{...}块内:

 defaultConfig { applicationId "com.example.autoincrement" minSdkVersion 18 targetSdkVersion 23 multiDexEnabled true def version = getIncrementationVersionName() versionName version } 

在应用程序级别的build.gradleandroid{...}build.gradle

 def getIncrementedVersionName() { List<String> runTasks = gradle.startParameter.getTaskNames(); //find version name in manifest def manifestFile = file('src/main/AndroidManifest.xml') def matcher = Pattern.compile('versionName=\"(\\d+)\\.(\\d+)\\.(\\d+)\"').matcher(manifestFile.getText()) matcher.find() //extract versionName parts def firstPart = Integer.parseInt(matcher.group(1)) def secondPart = Integer.parseInt(matcher.group(2)) def thirdPart = Integer.parseInt(matcher.group(3)) //check is runTask release or not // if release - increment version for (String item : runTasks) { if (item.contains("assemble") && item.contains("Release")) { thirdPart++ if (thirdPart == 10) { thirdPart = 0; secondPart++ if (secondPart == 10) { secondPart = 0; firstPart++ } } } } def versionName = firstPart + "." + secondPart + "." + thirdPart // update manifest def manifestContent = matcher.replaceAll('versionName=\"' + versionName + '\"') manifestFile.write(manifestContent) println "incrementVersionName = " + versionName return versionName } 

创build单卡APK后:

 android:versionName="5.1.6" 

注意:如果你的versionName与我的不同,你需要改变正则expression式提取部分逻辑

感谢CommonsWare(接受的答案)Paul Cantrell(创build文件,如果不存在的话)ahmad aghazadeh(版本名称和代码)

所以我把他们所有的想法集中在一起,并提出了这个想法。 这就是第一篇文章所要求的拖放解决scheme。

它将根据发布状态自动更新versionCode和versionName。 当然,你可以移动variables来满足你的需求。

 def _versionCode=0 def versionPropsFile = file('version.properties') def Properties versionProps = new Properties() if(versionPropsFile.exists()) versionProps.load(new FileInputStream(versionPropsFile)) def _patch = (versionProps['PATCH'] ?: "0").toInteger() + 1 def _major = (versionProps['MAJOR'] ?: "0").toInteger() def _minor = (versionProps['MINOR'] ?: "0").toInteger() List<String> runTasks = gradle.startParameter.getTaskNames(); def value = 0 for (String item : runTasks) if ( item.contains("assembleRelease")) { value = 1; } _versionCode = (versionProps['VERSION_CODE'] ?: "0").toInteger() + value if(_patch==99) { _patch=0 _minor=_minor+1 } if(_major==99){ _major=0 _major=_major+1 } versionProps['MAJOR']=_major.toString() versionProps['MINOR']=_minor.toString() versionProps['PATCH']=_patch.toString() versionProps['VERSION_CODE']=_versionCode.toString() versionProps.store(versionPropsFile.newWriter(), null) def _versionName = "${_major}.${_versionCode}.${_minor}.${_patch}" compileSdkVersion 24 buildToolsVersion "24.0.0" defaultConfig { applicationId "com.yourhost.yourapp" minSdkVersion 16 targetSdkVersion 24 versionCode _versionCode versionName _versionName } 

使用Gradle任务图,我们可以检查/切换构buildtypes。

基本的想法是在每个版本上增加versionCode 。 每个构build一个存储在version.properties文件中的计数器。 它将在每一个新的APK构build中保持更新,并用这个递增的计数器值replacebuild.gradle文件中的versionCodestring。

 apply plugin: 'com.android.application' android { compileSdkVersion 25 buildToolsVersion '25.0.2' def versionPropsFile = file('version.properties') def versionBuild /*Setting default value for versionBuild which is the last incremented value stored in the file */ if (versionPropsFile.canRead()) { def Properties versionProps = new Properties() versionProps.load(new FileInputStream(versionPropsFile)) versionBuild = versionProps['VERSION_BUILD'].toInteger() } else { throw new FileNotFoundException("Could not read version.properties!") } /*Wrapping inside a method avoids auto incrementing on every gradle task run. Now it runs only when we build apk*/ ext.autoIncrementBuildNumber = { if (versionPropsFile.canRead()) { def Properties versionProps = new Properties() versionProps.load(new FileInputStream(versionPropsFile)) versionBuild = versionProps['VERSION_BUILD'].toInteger() + 1 versionProps['VERSION_BUILD'] = versionBuild.toString() versionProps.store(versionPropsFile.nminSdkVersion 14 targetSdkVersion 21 versionCode 1ewWriter(), null) } else { throw new FileNotFoundException("Could not read version.properties!") } } defaultConfig { minSdkVersion 16 targetSdkVersion 21 versionCode 1 versionName "1.0.0." + versionBuild } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } // Hook to check if the release/debug task is among the tasks to be executed. //Let's make use of it gradle.taskGraph.whenReady {taskGraph -> if (taskGraph.hasTask(assembleDebug)) { /* when run debug task */ autoIncrementBuildNumber() } else if (taskGraph.hasTask(assembleRelease)) { /* when run release task */ autoIncrementBuildNumber() } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:25.3.1' } 

将上面的脚本放在主模块的build.gradle文件中。

参考url: http : //devdeeds.com/auto-increment-build-number-using-gradle-in-android/

感谢和问候!