Как autoincrement versionCode в Android Gradle
я экспериментирую с новой системой сборки Android на основе Gradle, и я думаю, что это лучший способ автоматического увеличения versionCode с ним. Я думаю о двух вариантах
- создайте файл versionCode, прочитайте номер из него, увеличьте его и запишите обратно в файл
- разбор AndroidManifest.xml, прочитайте код версии из него, увеличьте его и запишите обратно в AndroidManifest.xml
есть ли более простое и подходящее решение?
кто-нибудь использовал один из вариантов mentiod и мог бы поделиться им со мной?
13 ответов:
Я решил для второго варианта-разобрать
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.name уравнение вtask.whenTaskAddedобратный.
Я использую этот код для обновления как versionCode, так и versionName, используя "major.незначительный.заплатка.построить схему".
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' } }
это не похоже на точную настройку, которую вы используете, но в моем случае сборки запускаются Дженкинсом, и я хотел использовать его $BUILD_NUMBER в качестве кода версии приложения. следующий сделал трюк для меня.
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 }
Если вы держите код версии в сборке.файл 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 = 2import 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период для регулярных выраженийэто работает путем увеличения название версии
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.91import 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) }
Как насчет этого ? добавить в сборку.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" }
Если написать
versionCodeingradle.buildфайл (в большинстве случаев в настоящее время), вот обходной путь. Немного глупо (обновление "self"), но это работает!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 ]} }
Comments