una - Cómo autoincrementar versionCode en Android Gradle
android:versioncode (13)
Estoy experimentando con el nuevo sistema de compilación de Android basado en Gradle y estoy pensando, ¿cuál es la mejor manera de autoincrementar versionCode con él. Estoy pensando en dos opciones
- crea el archivo versionCode, lee el número, increméntalo y escríbelo de nuevo en el archivo
- analizar AndroidManifest.xml, leer el código de versión, aumentarlo y volver a escribirlo en el archivo AndroidManifest.xml
¿Hay alguna solución más simple o adecuada?
¿Alguien ha usado una de las opciones de mentiod y podría compartirla conmigo?
Incrementar la tarea de VersionCode (Entero):
Esto funciona incrementando el código de versión en 1
, por ejemplo:
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)
}
Incrementar VersionName Task (String):
Advertencia: debe contener 1
período para Regex
Esto funciona incrementando el nombre de la versión por 0.01
, por ejemplo: puede modificar y cambiar fácilmente su incremento o agregar más dígitos.
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)
}
Antes de:
<?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" >
Después:
<?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" >
Así que mientras estudiaba la mayor parte de la solución, eran agradables pero no lo suficiente, así que escribí esto, un incremento por despliegue múltiple:
Esto incrementará la compilación al compilar versiones de depuración e incrementará el código de punto y versión cuando se implemente.
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
}
}
Estoy usando este código para actualizar tanto versionCode como versionName, usando un esquema "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''
}
}
Estoy usando la marca de tiempo para el código de la versión:
def date = new Date()
def formattedDate = date.format(''yyMMddHHmm'')
def code = formattedDate.toInteger()
defaultConfig {
minSdkVersion 10
targetSdkVersion 21
versionCode code
}
He decidido por la segunda opción: analizar AndroidManifest.xml
. Aquí está el fragmento de trabajo.
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
se lanza para compilaciones de lanzamiento en este caso. Para aumentarlo para las compilaciones de depuración, cambie la ecuación task.whenTaskAdded
en la task.whenTaskAdded
llamada task.whenTaskAdded
.
La versión de compilación avanzada de Gradle es un complemento para Android que hace que se generen versionCode y versionName automáticamente. hay mucha personalización. aquí puedes encontrar más información al respecto https://github.com/moallemi/gradle-advanced-build-version
Mi enfoque es leer el archivo manifest de la carpeta de compilación y obtener buildVersion de allí, que eliminar una carpeta. Cuando la tarea crea un nuevo manifiesto, mi variable buildVersion incrementada ya está allí.
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
]}
}
Para agregar a la publicación de @ sealskej, esta es la forma de actualizar tanto el código de la versión como el nombre de la versión (Aquí estoy suponiendo que su versión principal y secundaria son ambas 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)
}
Para tener en cuenta los sabores de los productos y los tipos de compilación y usar la lógica de @sealskej para analizar el manifiesto:
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)
}
}
Si escribe su versionCode
en el archivo gradle.build
(la mayoría de los casos actualmente), aquí hay una solución. Un poco estúpido (actualización "self"), pero funciona!
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''
}
}
Si mantiene el código de versión en el archivo build.gradle use el siguiente fragmento:
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)
}
no parece ser la configuración exacta que está utilizando, pero en mi caso las compilaciones están siendo ejecutadas por jenkins y quería usar su $ BUILD_NUMBER como código de versión de la aplicación. Lo siguiente hizo el truco para mí allí.
defaultConfig {
...
versionCode System.getenv("BUILD_NUMBER") as Integer ?: 9999
...
}
que tal esto? agregar a build.gradle (módulo de aplicación)
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"
}