Autoincrement VersionCode con propiedades adicionales de gradle

121

Estoy creando una aplicación de Android con gradle. Hasta ahora usé el archivo Manifest para aumentar el versionCode, pero me gustaría leer el versionCode de un archivo externo y dependiendo de si es el tipo de lanzamiento o el tipo de depuración, aumentar el versionCode. Probé las propiedades adicionales, pero no puede guardarlas, lo que significa que la próxima vez que lo construya 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'
}
carvaq
fuente
Vea mi respuesta aquí: stackoverflow.com/a/33637600/348189
TacB0sS
Otra opción (un enfoque de configurar y olvidar): medium.com/@passsy/…
Simon B.
Una línea con los complementos de Gradle que elijas: stackoverflow.com/a/61718437/4548500
SUPERCILEX

Respuestas:

207

Me gustaría leer el versionCode de un archivo externo

Estoy seguro de que hay varias soluciones posibles; acá 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 version.propertiesarchivo existente , que crearía a mano antes de tener la primera compilación VERSION_CODE=8.

Este código simplemente agrega el código de la versión en cada compilación; necesitaría extender la técnica para manejar su código de versión por sabor.

Puede ver el proyecto de ejemplo de control de versiones que muestra este código.

CommonsWare
fuente
4
¿Cómo habilitar esta versión incrementándose solo mientras se realizan versiones de lanzamiento?
Piotr
@Piotr: Si te refieres a "solo incrementar el número en una versión de lanzamiento", eso debería ser posible, aunque no conozco los detalles. Personalmente, dado que hay ~ 2 mil millones de códigos de versión disponibles, supongo que no se me acabarán. :-)
CommonsWare
3
@Piotr crearía una tarea que incremente por separado el código de la versión y luego haga algo similar assembleRelease.finalizedBy incrementVersiono algo similar. Publicaré mi código una vez que lo haya ordenado.
Chris.Jenkins
Usando una tarea personalizada puedes hacer algo como ./gradlew incrementVersionCode build. Las tareas llamadas secuencialmente de esta manera se detendrán tan pronto como falle alguna de las tareas.
Dori
3
Como @ chris.jenkins todavía está actualizando su código: p Aquí está lo anterior en la forma de tarea y método gist.github.com/doridori/544c24509be236c11fd5 que se puede usar dentro del DSL de Android conversionCode getIncrementingVersionCode()
Dori
83

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 .

Qué hace este script:

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

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

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

Versión principal: debe cambiarse manualmente para cambios más importantes.

Versión secundaria: debe cambiarse manualmente para cambios un poco menos importantes.

Versión del parche: aumenta cuando se ejecutagradle assembleRelease

Versión de compilación: aumenta cada compilación

Número de versión: Igual que la versión de parche , esto es para el código de versión que Play Store debe aumentar 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 resto. :)

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 mi

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

EDITAR:

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

Esto es lo que he estado usando durante el año pasado, los conceptos básicos son de la respuesta de CommonsWare y mi respuesta anterior, y algo 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!")
    }

    ...
}

...

El parche y el código de versión aumentan si ensambla su proyecto a través de la terminal con 'ensamblar' , 'ensamblarRelease' o 'aR' que crea una nueva carpeta en la raíz de su proyecto llamada apk / RELEASE para que no tenga que revisar la compilación / salidas / más / más / más para encontrar su apk.

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

VERSION_NUMBER=1
VERSION_BUILD=645
VERSION_PATCH=1

Obviamente comienza con 0. :)

just_user
fuente
2
La segunda 'variant.outputs.each {salida ->' se puede eliminar, con el correspondiente '}'.
redocoder
Esto está causando que todas mis compilaciones estén en código nativo x86_64 solamente
Chisko
@Chisko Dudo que esta parte del código de Gradle sea la causa. Haga una nueva pregunta y comparta su código gradle y podemos intentar averiguar qué está mal. :)
just_user
1
Ahora puedo confirmar que esta no fue la causa raíz. Mis disculpas.
Chisko
1
@AlexanderGavriliuk es el código de versión utilizado por Play Store que necesita aumentar constantemente para cada carga. El número de parche probablemente se restablecerá si aumenta la versión mayor o menor. El número de versión nunca debería, nunca podría restablecerse si carga la aplicación en Play Store con el mismo nombre de paquete.
just_user
40

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
}
Paul Cantrell
fuente
¿Dónde está la parte de crear el archivo de versión si no existe?
portfoliobuilder
4
if(versionPropsFile.exists())asegura que no explote si el archivo no está allí. versionProps.store(versionPropsFile.newWriter(), null) sobrescribe el archivo independientemente de si ya existe.
Paul Cantrell
Tenía que comprobar qué ?:significaba en Groovy. El operador de Elvis es una abreviatura del operador ternario.
Daniel
30

Miré algunas opciones para hacer esto, y finalmente decidí que era más sencillo usar la hora actual para el versionCode en lugar de intentar incrementar automáticamente el versionCode y registrarlo 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 cargar compilaciones posteriores al año 2696, es posible que desee utilizar una solución diferente.

emmby
fuente
2
Si está leyendo esto ahora y comienza con una nueva aplicación, puede restar 1510351294:))
Entreco
no entiendo esto !! ¿No utiliza analíticas o crashlytics o cualquier otro servicio que proporcione datos con códigos de versión y nombres? y estás jugando con estos tan fácilmente?
Amir Ziarati
Si tiene nombres de versión razonables, creo que está bien. Crashalytics también proporciona el nombre de la versión.
netcyrax
@emmby ¿de dónde sacas el número '1451606400'? o el '1510351294' de #Entreco ¡He estado intentando calcular en vano!
Joseph Wambura
18

Otra forma de obtener una versionCodeautomáticamente es establecer versionCodeel número de confirmaciones en la gitrama extraída. Cumple los siguientes objetivos:

  1. versionCodese genera de forma automática y coherente en cualquier máquina (incluido un servidor Continuous Integrationy / o un Continuous Deploymentservidor).
  2. La aplicación con esto versionCodese puede enviar a GooglePlay.
  3. No depende de ningún archivo fuera del repositorio.
  4. No envía nada al repositorio
  5. Se puede anular manualmente, si es necesario

Usar la biblioteca gradle-git para lograr los objetivos anteriores. Agregue el siguiente código a su build.gradlearchivo el /appdirectorio:

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
}

NOTA: Para que este método funcione, es mejor implementar solo en Google Play Store desde la misma sucursal (p. Ej. master).

C0D3LIC1OU5
fuente
Si bien en esencia es una solución elegante, puedo imaginar que esto ralentizaría drásticamente el tiempo de compilación, dependiendo de lo que esté sucediendo exactamente en las 2 líneas de git. ¿Alguna experiencia en eso?
HopefullyHelpful
1
No noto ninguna mejora en el rendimiento si este paso está desactivado. Hemos estado usando el método localmente y en nuestras máquinas de construcción durante más de un año y el rendimiento no ha sido un problema en absoluto. Si nota algún problema de rendimiento, ¡hágamelo saber!
C0D3LIC1OU5
Si bien su solución es elegante, podría dar algunas sorpresas desagradables e inesperadas. Es fundamental que los versionCodes sean siempre más grandes que en la versión anterior. ¿Qué sucede si tiene una rama con 50 confirmaciones y luego crea otra rama que es más nueva pero solo tiene 40 confirmaciones, tal vez debido a la eliminación de varias confirmaciones de alguna característica fusionada? Puedo ver muchas razones por las que su historial de confirmaciones no siempre sería un flujo lineal de confirmaciones incrementales.
JHH
@JHH Esos resultados no son inesperados. Como mencioné en una nota, este método funciona mejor cuando se implementa desde la misma rama.
C0D3LIC1OU5
13

Recientemente, estaba trabajando en un complemento de Gradle para Android que hace que la generación de versionCode y versionName se genere automáticamente. hay mucha personalización. aquí puede encontrar más información al respecto https://github.com/moallemi/gradle-advanced-build-version

moallemi
fuente
¡Este es un gran complemento! Gracias por compartir 🙂
Cory Robinson
10

Otra opción, para incrementar el versionCodey el versionName, es usar 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') supera la capacidad de Integers

carvaq
fuente
1
La persona quería un número de compilación de incremento automático
peter_pilgrim
6
@peter_pilgrim Caro es el OP.
Mateo Leer
Creo que esta es una solución elegante, no depende de archivos que puedan desaparecer o no o que aparezcan constantemente en git. También le ayuda a identificar de forma única cada compilación durante al menos los próximos 22 años.
HopefullyHelpful
citando developer.android.com:"Warning: El mayor valor de Google Play permite versionCode es 2100000000. "Por lo tanto, el punto de corte es en realidad 2021.
THS
Corrección del límite int: omita los minutos y use el formato de fecha 'yyMMddHH', el código de la versión contendrá al menos horas.
Puntero nulo
10

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

espera un c://YourProject/app/version.propertiesarchivo existente , que crearía a mano antes de la primera compilación para tenerVERSION_CODE=8

Archivo version.properties:

VERSION_CODE=8

NickUnuchek
fuente
Más bien, colóquelo dentro de una tarea y haga que generateReleaseBuildConfig dependa de esa tarea.
lagos
versionName "1.0." + getSvnRevision () provoca un error. ¿A dónde hace referencia el método getSvnRevision ()? ¿Está seguro de que no debería ser versionName "1.0." + Código (el nombre de la versión aumentará con su código de versión)?
portfoliobuilder
1
@portfoliobuilder, reemplace getSvnRevision () al código
NickUnuchek
4

Crea un archivo version.properties

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

Cambio 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

Ahmad Aghazadeh
fuente
Gracias. ¿Y por qué ha insertado un versionCode en versionName? Incluso en la segunda posición.
CoolMind
Pero se verá como 1.71.3.76, por ejemplo. Creo que mejor es 1.3.76, separándolo del código de versión.
CoolMind
Si . puede cambiar a "$ {_ major} .. $ {_ minor}. $ {_ patch}. $ {_ versionCode}" o eliminar el parche
Ahmad Aghazadeh
if (_major == 99) debería ser if (_minor == 99) ??
Anirudh Bagri
2

Definir versionName enAndroidManifest.xml

android:versionName="5.1.5"

Dentro del android{...}bloque build.gradledel nivel de la aplicación:

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

android{...}Bloqueo exterior build.gradledel nivel de la aplicación:

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
}

Después de crear 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 las partes .

Sergey Shustikov
fuente
1

Los ejemplos que se muestran arriba no funcionan por diferentes razones

Aquí está mi variante lista para usar basada en ideas de este artículo:

android {
    compileSdkVersion 28

    // /programming/21405457

    def propsFile = file("version.properties")
    // Default values would be used if no file exist or no value defined
    def customAlias = "Alpha"
    def customMajor = "0"
    def customMinor = "1"
    def customBuild = "1" // To be incremented on release

    Properties props = new Properties()
    if (propsFile .exists())
        props.load(new FileInputStream(propsFile ))

    if (props['ALIAS'] == null) props['ALIAS'] = customAlias else customAlias = props['ALIAS']
    if (props['MAJOR'] == null) props['MAJOR'] = customMajor else customMajor = props['MAJOR']
    if (props['MINOR'] == null) props['MINOR'] = customMinor else customMinor = props['MINOR']
    if (props['BUILD'] == null) props['BUILD'] = customBuild else customBuild = props['BUILD']

    if (gradle.startParameter.taskNames.join(",").contains('assembleRelease')) {
        customBuild = "${customBuild.toInteger() + 1}"
        props['BUILD'] = "" + customBuild

        applicationVariants.all { variant ->
            variant.outputs.all { output ->
                if (output.outputFile != null && (output.outputFile.name == "app-release.apk"))
                    outputFileName = "app-${customMajor}-${customMinor}-${customBuild}.apk"
            }
        }
    }

    props.store(propsFile.newWriter(), "Incremental Build Version")

    defaultConfig {
        applicationId "org.example.app"
        minSdkVersion 21
        targetSdkVersion 28
        versionCode customBuild.toInteger()
        versionName "$customAlias $customMajor.$customMinor ($customBuild)"

        ...
    }
...
}
Alexander Gavriliuk
fuente
0

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 reuní todas sus ideas y se me ocurrió esto. Esta es la solución de arrastrar y soltar para exactamente lo que pidió la primera publicación.

Actualizará automáticamente el versionCode y 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<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
}
Thunderstick
fuente
0

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

La idea básica es incrementar el versionCode en cada compilación. En Cada construye un contador almacenado en el archivo version.properties . Se mantendrá actualizado en cada nueva compilació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 el script 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!

Jayakrishnan
fuente
0

El primer código comentado incrementará el número mientras cada "Proyecto de reconstrucción" y guardará el valor en el archivo "Propiedad de la versión".

El segundo código comentado generará un nuevo nombre de versión del archivo APK mientras se "compila APK".

android {
    compileSdkVersion 28
    buildToolsVersion "29.0.0"
    //==========================START==================================
    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)
    //===========================END===================================
    defaultConfig {
        applicationId "com.example.myapp"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "0.19"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            //=======================================START===============================================
            android.applicationVariants.all { variant ->
                variant.outputs.all {
                    def appName = "MyAppSampleName"
                    outputFileName = appName+"_v${variant.versionName}.${versionProps['VERSION_CODE']}.apk"
                }
            }
            //=======================================END===============================================
        }
    }
}
Radha Krishna Eedulakanti
fuente
Agregue un texto que muestre lo que ha cambiado. y por qué
Matthew Kerian
0

en la versión de Gradle 5.1.1 en mac ive cambió la forma en que se recuperaron los nombres de las tareas, aunque intenté obtener el sabor / tipo de compilación a partir de la compilación, pero fui perezoso para dividir el nombre de la tarea:

def versionPropsFile = file('version.properties')
if (versionPropsFile.canRead()) {
    def Properties versionProps = new Properties()

    versionProps.load(new FileInputStream(versionPropsFile))

    def value = 0

    def runTasks = gradle.getStartParameter().getTaskRequests().toString()

    if (runTasks.contains('assemble') || runTasks.contains('assembleRelease') || runTasks.contains('aR')) {
        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 {
        applicationId "de.evomotion.ms10"
        minSdkVersion 21
        targetSdkVersion 28
        versionCode versionNumber
        versionName "${versionMajor}.${versionMinor}.${versionPatch} (${versionBuild})"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        signingConfig signingConfigs.debug
    }

} else {
    throw new GradleException("Could not read version.properties!")
}

el código es de @just_user este

Basur
fuente
0

Hay dos soluciones que me gustan mucho. El primero depende de Play Store y el otro depende de Git.

Con Play Store, puede incrementar el código de versión mirando el código de versión cargado más alto disponible . El beneficio de esta solución es que la carga de un APK nunca fallará, ya que el código de su versión es siempre uno más alto que el de Play Store. La desventaja es que distribuir tu APK fuera de Play Store se vuelve más difícil. Puede configurar esto usando Gradle Play Publisher siguiendo la guía de inicio rápido y diciéndole al complemento que resuelva los códigos de versión automáticamente :

plugins {
    id 'com.android.application'
    id 'com.github.triplet.play' version 'x.x.x'
}

android {
    ...
}

play {
    serviceAccountCredentials = file("your-credentials.json")
    resolutionStrategy = "auto"
}

Con Git, puedes incrementar el código de la versión según la cantidad de confirmaciones y etiquetas que tenga tu repositorio. El beneficio aquí es que su salida es reproducible y no depende de nada fuera de su repositorio. La desventaja es que tienes que hacer una nueva confirmación o etiqueta para aumentar tu código de versión. Puede configurar esto agregando el complemento Version Master Gradle :

plugins {
    id 'com.android.application'
    id 'com.supercilex.gradle.versions' version 'x.x.x'
}

android {
    ...
}
SUPERCILEX
fuente