Как автоинкремент версии Код в Android Gradle

Я экспериментирую с новой системой сборки Android, основанной на Gradle, и я думаю, что это лучший способ автоматического улучшения версииCode. Я думаю о двух вариантах

  1. Создать файл версииCode, прочитать номер из него, увеличить его и записать в файл
  2. Проанализируйте AndroidManifest.xml, прочитайте версиюCode, увеличьте его и запишите в AndroidManifest.xml

Есть ли еще более простое или подходящее решение?

Кто-нибудь использовал один из вариантов ментодиола и мог поделиться им со мной?

Я решил второй вариант – разобрать AndroidManifest.xml . Вот рабочий фрагмент.

 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 выпускается для релизов в этом случае. Чтобы увеличить его для отладочных построений, измените уравнение task.whenTaskAdded в task.whenTaskAdded callback.

Я использую этот код для обновления как versionCode, так и versionName, используя схему «major.minor.patch.build».

 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' } } 

Это, похоже, не точная настройка, которую вы используете, но в моем случае сборки выполняются jenkins, и я хотел использовать его $ BUILD_NUMBER в качестве версии VersionCode приложения. Следующий трюк для меня там.

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

Я использую отметку времени для кода версии:

 def date = new Date() def formattedDate = date.format('yyMMddHHmm') def code = formattedDate.toInteger() defaultConfig { minSdkVersion 10 targetSdkVersion 21 versionCode code } 

Если вы держите код версии в файле build.gradle, используйте следующий фрагмент:

 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) } 

Принимать во внимание вкусы и типы продуктов и использовать логику @ sealskej для анализа манифеста:

 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) } } 

Gradle Advanced Build Version – это плагин для Android, который автоматически генерирует версию VersionCode и versionName . Есть много настроек. Здесь вы можете найти дополнительную информацию об этом https://github.com/moallemi/gradle-advanced-build-version

Increment VersionCode Task (Integer):

Это работает, увеличивая код версии на 1 , например:

  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):

Предупреждение: должно содержать 1 период для Regex

Это работает, увеличивая имя версии на 0.01 , например: вы можете легко изменить и изменить свой прирост или добавить больше цифр.

 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) } 

До:

 <?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" > 

После:

 <?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" > 

Чтобы добавить на пост @ sealskej, так вы можете обновить как свой код версии, так и имя версии (здесь я предполагаю, что ваша основная и младшая версии равны 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) } 

как насчет этого ? Добавить в build.gradle (модуль приложения)

 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" } 

Если вы напишете свой gradle.build файле gradle.build (в большинстве случаев в настоящее время), это обходное решение. Немного глупо (обновляю «я»), но он работает!

 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' } } 

Так как я смотрел на большинство решений, они были хорошими, но недостаточно, поэтому я написал это, по одному приращению на мультиразведение:

Это увеличит сборку при компиляции версий отладки и увеличит код точки и версии при развертывании.

 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 } } 

Мой подход состоит в том, чтобы прочитать файл манифеста из папки создания и получить buildVersion оттуда, чем удалить папку. Когда задача создает новый манифест, моя добавленная переменная buildVersion уже существует.

 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 ]} }