Autoincrement VersionCode con propiedades adicionales de gradle

Estoy construyendo una aplicación para Android con Gradle. Hasta ahora utilicé el archivo Manifest para boost el código de versión, pero me gustaría leer el código de versión desde un archivo externo y dependiendo de si es el sabor de la versión o el sabor de depuración boost el código de versión. Probé las propiedades adicionales, pero no puede guardarlas, lo que significa que la próxima vez que lo haga obtendré el mismo código de versión. ¡Cualquier ayuda sería muy apreciada!

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

Me gustaría leer la versionCode de un archivo externo

Estoy seguro de que hay muchas soluciones posibles. Aqui hay uno:

 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 } 

Este código espera un archivo version.properties existente, que crearía a mano antes de la primera comstackción para tener VERSION_CODE=8 .

Este código simplemente topa con el código de la versión en cada comstackción. Tendría que ampliar la técnica para manejar su código de versión por sabor.

Puede ver el proyecto de ejemplo de Versioning que demuestra este código.

Aquí viene una modernización de mi respuesta anterior que se puede ver a continuación. Este se ejecuta con Gradle 4.4 y Android Studio 3.1.1 .

Lo que hace este script:

  • Crea un archivo version.properties si no existe (vote por encima la respuesta de Paul Cantrell a continuación, que es de donde saqué la idea si le gusta esta respuesta)
  • Para cada comstackción, versión de depuración o cada vez que presione el botón Ejecutar en Android Studio, el número de VERSION_BUILD aumenta.
  • Cada vez que ensamblas un lanzamiento, aumenta el código de tu versión de Android para Play Store y aumenta tu número de parche .
  • Bonificación: una vez que se projectDir/apk su apk en projectDir/apk para hacerlo más accesible.

Este script creará un número de versión que se parece a v1.3.4 (123) y v1.3.4 (123) un archivo apk como AppName-v1.3.4.apk .

 Major version ⌄ ⌄ Build version v1.3.4 (123) Minor version ⌃|⌃ Patch version 

Versión principal: tiene que cambiarse manualmente para cambios más grandes.

Versión menor: tiene que cambiarse manualmente para cambios ligeramente menores.

Versión de parche: aumenta al ejecutar gradle assembleRelease

Versión de comstackción: aumenta cada comstackción

Número de versión: al igual que la versión de parche , esto es para el código de versión que Play Store necesita haber aumentado para cada nueva carga de apk.

Simplemente cambie el contenido en los comentarios etiquetados 1 – 3 a continuación y el script debería hacer el rest. 🙂

 android { compileSdkVersion 27 buildToolsVersion '27.0.3' def versionPropsFile = file('version.properties') def value = 0 Properties versionProps = new Properties() if (!versionPropsFile.exists()) { versionProps['VERSION_PATCH'] = "0" versionProps['VERSION_NUMBER'] = "0" versionProps['VERSION_BUILD'] = "-1" // I set it to minus one so the first build is 0 which isn't super important. versionProps.store(versionPropsFile.newWriter(), null) } def runTasks = gradle.startParameter.taskNames if ('assembleRelease' in runTasks) { value = 1 } def mVersionName = "" def mFileName = "" if (versionPropsFile.canRead()) { versionProps.load(new FileInputStream(versionPropsFile)) versionProps['VERSION_PATCH'] = (versionProps['VERSION_PATCH'].toInteger() + value).toString() versionProps['VERSION_NUMBER'] = (versionProps['VERSION_NUMBER'].toInteger() + value).toString() versionProps['VERSION_BUILD'] = (versionProps['VERSION_BUILD'].toInteger() + 1).toString() versionProps.store(versionPropsFile.newWriter(), null) // 1: change major and minor version here mVersionName = "v1.0.${versionProps['VERSION_PATCH']}" // 2: change AppName for your app name mFileName = "AppName-${mVersionName}.apk" defaultConfig { minSdkVersion 21 targetSdkVersion 27 applicationId "com.example.appname" // 3: change to your package name versionCode versionProps['VERSION_NUMBER'].toInteger() versionName "${mVersionName} Build: ${versionProps['VERSION_BUILD']}" } } else { throw new FileNotFoundException("Could not read version.properties!") } if ('assembleRelease' in runTasks) { applicationVariants.all { variant -> variant.outputs.all { output -> if (output.outputFile != null && output.outputFile.name.endsWith('.apk')) { outputFileName = mFileName } } } } task copyApkFiles(type: Copy){ from 'build/outputs/apk/release' into '../apk' include mFileName } afterEvaluate { assembleRelease.doLast { tasks.copyApkFiles.execute() } } signingConfigs { ... } buildTypes { ... } } 

=============================================== ==

RESPUESTA INICIAL:

Quiero que versionName aumente automáticamente también. Así que esto es solo una adición a la respuesta de CommonsWare que funcionó perfectamente para mí. Esto es lo que funciona para mí

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

EDITAR:

Como soy un poco vago, quiero que mi versión funcione lo más automáticamente posible. Lo que quiero es tener una versión de comstackción que aumente con cada comstackción, mientras que el número de versión y el nombre de la versión solo aumentan cuando realizo una comstackción de lanzamiento.

Esto es lo que he estado usando durante el año pasado, los conceptos básicos provienen de la respuesta de CommonsWare y mi respuesta anterior, más algunos más. Esto da como resultado el siguiente control de versiones:

Nombre de la versión: 1.0.5 (123) -> Major.Minor.Patch (Build), Major y Minor se cambian manualmente.

En 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!") } ... } ... 

Patch y versionCode aumentan si ensambla su proyecto a través del terminal con ‘assemble’ , ‘assembleRelease’ o ‘aR’, que crea una nueva carpeta en la raíz del proyecto llamada apk / RELEASE para que no tenga que mirar a través de build / outputs / más / más / más para encontrar tu apk.

Las propiedades de su versión deberían verse así:

 VERSION_NUMBER=1 VERSION_BUILD=645 VERSION_PATCH=1 

Obviamente comienza con 0. 🙂

Una versión ligeramente ajustada de la excelente respuesta de CommonsWare crea el archivo de versión si no existe:

 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 } 

Miré algunas opciones para hacer esto, y finalmente decidí que era más simple usar la hora actual para el código de versión en lugar de tratar de incrementar automáticamente el código de versión y verificarlo en mi sistema de control de revisiones.

Agregue lo siguiente a su 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 } } 

Sin embargo, si espera subir construcciones más allá del año 2696, es posible que desee utilizar una solución diferente.

Otra forma de obtener un versionCode automáticamente es establecer el versionCode de versionCode en el número de confirmaciones en la twig de git desprotegida. Cumple los siguientes objectives:

  1. versionCode se genera de forma automática y coherente en cualquier máquina (incluido un servidor de Continuous Integration y / o Continuous Deployment ).
  2. La aplicación con este versionCode se puede enviar a GooglePlay.
  3. No confía en ningún archivo fuera del repository.
  4. No empuja nada al repository
  5. Se puede anular manualmente, si es necesario

Usando la biblioteca gradle-git para lograr los objectives anteriores. Agregue el siguiente código a su archivo build.gradle , el directorio /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 /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  | wc -l def numOfCommits = ext.repo.log().size() return numOfCommits } 

NOTA: Para que este método funcione, lo mejor es implementarlo solo en Google Play Store desde la misma twig (por ejemplo, master ).

Recientemente estuve trabajando en un plugin de gradle 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

Otra opción, para incrementar el versionCode y el versionName , es utilizar una marca de tiempo.

 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 } 

A partir del 1 de enero de 2022 formattedDate = date.format (‘yyMMddHHmm’) excede la capacidad de los enteros

Para incrementar versionCode solo en la versión de lanzamiento, hazlo:

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

espera un archivo c://YourProject/app/version.properties existente, que crearía a mano antes de la primera comstackción para tener VERSION_CODE=8

Archivo version.properties :

VERSION_CODE=8

Crear archivo version.properties

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

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

}

Salida: 1.1.3.6

Definir versionName en AndroidManifest.xml

 android:versionName="5.1.5" 

Dentro de android{...} bloque en build.gradle de nivel de aplicación:

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

Bloque externo de android{...} en build.gradle de nivel de aplicación:

 def getIncrementedVersionName() { List 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 } 

Después de crear el APK chamuscado:

 android:versionName="5.1.6" 

Nota: Si su versionName es diferente de my, necesita cambiar la expresión regular y extraer la lógica de partes .

Créditos a CommonsWare (Respuesta aceptada) Paul Cantrell (Crear archivo si no existe) ahmad aghazadeh (Nombre y código de la versión)

Así que aplasté todas sus ideas y se me ocurrió esto. Esta es la solución de arrastrar y soltar exactamente lo que pidió la primera publicación.

Se actualizará automáticamente el versionCode y el versionName según el estado de la versión. Por supuesto, puede mover las variables para adaptarlas a sus necesidades.

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

Usando Gradle Task Graph podemos verificar / cambiar el tipo de comstackción.

La idea básica es incrementar el versionCode en cada comstackción. En Cada comstackción, un contador almacenado en el archivo version.properties . Se mantendrá actualizado en cada nueva comstackción de APK y reemplazará la cadena versionCode en el archivo build.gradle con este valor de contador incrementado.

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

Coloque la secuencia de comandos anterior dentro de su archivo build.gradle del módulo principal.

Sitio web de referencia: http://devdeeds.com/auto-increment-build-number-using-gradle-in-android/

¡Gracias y Saludos!