Autoincrement VersionCode com propriedades extras gradle

121

Estou construindo um aplicativo Android com o gradle. Até agora usei o arquivo Manifest para aumentar o versionCode, mas gostaria de ler o versionCode de um arquivo externo e dependendo se é a versão de lançamento ou a versão de depuração, aumente o versionCode. Tentei as propriedades extras, mas você não consegue salvá-las, o que significa que da próxima vez que eu construir, estou obtendo o mesmo versionCode. Qualquer ajuda seria muito bem vinda!

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
fonte
Veja minha resposta aqui: stackoverflow.com/a/33637600/348189
TacB0sS
Outra opção (uma abordagem de definir e esquecer): medium.com/@passsy/…
Simon B.
One-liner com sua escolha de plug-ins Gradle: stackoverflow.com/a/61718437/4548500
SUPERCILEX

Respostas:

207

Eu gostaria de ler o versionCode de um arquivo externo

Estou certo de que existem inúmeras soluções possíveis; Aqui está um:

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 um version.propertiesarquivo existente , que você criaria manualmente antes de ter o primeiro build VERSION_CODE=8.

Este código simplesmente altera o código de versão em cada compilação - você precisaria estender a técnica para lidar com seu código de versão por variação.

Você pode ver o projeto de amostra de controle de versão que demonstra esse código.

CommonsWare
fonte
4
Como habilitar o incremento desta versão apenas ao fazer compilações de lançamento?
Piotr
@Piotr: Se você quer dizer "apenas incrementar o número em uma compilação de lançamento", isso deveria ser possível, embora eu não saiba os detalhes. Pessoalmente, uma vez que existem cerca de 2 bilhões de códigos de versão disponíveis, estou assumindo que não vou acabar. :-)
CommonsWare
3
@Piotr você criaria uma tarefa que incrementa separadamente o código de versão e então faria algo parecido assembleRelease.finalizedBy incrementVersionou semelhante. Vou postar meu código depois de arrumá-lo.
Chris.Jenkins
Usando uma tarefa personalizada, você pode simplesmente fazer algo como ./gradlew incrementVersionCode build. As tarefas chamadas sequencialmente dessa maneira serão interrompidas assim que qualquer uma das tarefas falhar.
Dori
3
Como @ chris.jenkins ainda está lendo seu código: p Aqui está o acima no formulário de tarefa e método gist.github.com/doridori/544c24509be236c11fd5 que pode ser usado dentro do DSL Android comversionCode getIncrementingVersionCode()
Dori
83

Aí vem uma modernização da minha resposta anterior, que pode ser vista abaixo. Este está sendo executado com Gradle 4.4 e Android Studio 3.1.1 .

O que este script faz:

  • Cria um arquivo version.properties se não houver nenhum (vote na resposta de Paul Cantrell abaixo, que é de onde eu tirei a ideia se você gostar desta resposta)
  • Para cada versão, versão de depuração ou sempre que você pressiona o botão de execução no Android Studio, o número VERSION_BUILD aumenta.
  • Cada vez que você monta um lançamento, seu código de versão do Android para a play store aumenta e o número do patch aumenta.
  • Bônus: depois que a compilação for concluída, copie seu apk para projectDir/apkpara torná-lo mais acessível.

Este script criará um número de versão semelhante v1.3.4 (123)e construirá um arquivo apk como AppName-v1.3.4.apk .

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

Versão principal: deve ser alterado manualmente para alterações maiores.

Versão secundária: deve ser alterado manualmente para alterações um pouco menos grandes.

Versão do patch: aumenta durante a execuçãogradle assembleRelease

Versão de compilação: aumenta a cada compilação

Número da versão: igual à versão do patch , é para o código da versão que a Play Store precisa ter aumentado para cada novo upload do apk.

Basta alterar o conteúdo nos comentários marcados de 1 a 3 abaixo e o script fará o 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 {
        ...
    }
}

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

RESPOSTA INICIAL:

Quero que o versionName aumente automaticamente também. Portanto, este é apenas um acréscimo à resposta do CommonsWare que funcionou perfeitamente para mim. Isto é o que funciona para mim

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

EDITAR:

Como sou um pouco preguiçoso, quero que meu controle de versão funcione da forma mais automática possível. O que eu quero é ter uma versão de compilação que aumente com cada compilação, enquanto o número da versão e o nome da versão só aumentam quando eu faço uma compilação de lançamento.

Isso é o que tenho usado no ano passado, o básico é da resposta de CommonsWare e minha resposta anterior, além de mais algumas. Isso resulta no seguinte controle de versão:

Nome da versão: 1.0.5 (123) -> Major.Minor.Patch (Build), Major e Minor são alterados manualmente.

Em 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 e versionCode aumentam se você montar seu projeto por meio do terminal com 'assemble' , 'assembleRelease' ou 'aR' que cria uma nova pasta na raiz do seu projeto chamada apk / RELEASE para que você não tenha que olhar para build / outputs / mais / mais / mais para encontrar seu apk.

As propriedades de sua versão precisam ser assim:

VERSION_NUMBER=1
VERSION_BUILD=645
VERSION_PATCH=1

Obviamente, comece com 0. :)

just_user
fonte
2
O segundo 'variant.outputs.each {output ->' pode ser removido, com o '}' correspondente.
redocoder
Isso está fazendo com que todas as minhas compilações estejam apenas em código nativo x86_64
Chisko
@Chisko Duvido que essa parte do código do Gradle seja a causa. Faça uma nova pergunta e compartilhe seu código do Gradle para que possamos tentar descobrir o que está errado. :)
just_user
1
Agora posso confirmar que essa não foi a causa raiz. Me desculpe.
Chisko,
1
@AlexanderGavriliuk é o código da versão usado pela play store que precisa aumentar constantemente a cada upload. O número do patch provavelmente será redefinido se você aumentar a versão principal ou secundária. O número da versão nunca deve ser redefinido se você carregar o aplicativo na Play Store com o mesmo nome de pacote.
just_user
40

Uma versão um pouco mais restrita da excelente resposta do CommonsWare cria o arquivo de versão se ele não existir:

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
fonte
onde está a parte sobre como criar o arquivo de versão se ele não existir?
portfólio
4
if(versionPropsFile.exists())garante que ele não exploda se o arquivo não estiver lá. versionProps.store(versionPropsFile.newWriter(), null) substitui o arquivo, independentemente de ele já existir.
Paul Cantrell,
Tive que verificar o que ?:significava em Groovy. O operador Elvis é um encurtamento do operador ternário.
Daniel
30

Observei algumas opções para fazer isso e, no final das contas, decidi que era mais simples usar apenas a hora atual para o versionCode em vez de tentar incrementar automaticamente o versionCode e fazer o check-in em meu sistema de controle de revisão.

Adicione o seguinte ao seu 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
    }
}

No entanto, se você espera fazer upload de compilações além do ano 2696, pode usar uma solução diferente.

embrulhar
fonte
2
Se você está lendo isso agora e começando com um novo aplicativo, você pode subtrair 1510351294:))
Entreco
eu não entendo isso! você não usa análises ou crashlytics ou qualquer outro serviço que forneça dados com códigos de versão e nomes? e você está brincando com isso facilmente?
Amir Ziarati de
Se você tiver nomes de versão razoáveis, acho que está tudo bem. O Crashalytics também fornece o nome da versão.
netcyrax
@emmby de onde você tira o número '1451606400'? ou o '1510351294' da #Entreco que tenho tentado calcular em vão!
Joseph Wambura
18

Outra maneira de obter um versionCodeautomaticamente é definir versionCodeo número de commits no gitbranch em check-out . Ele cumpre os seguintes objetivos:

  1. versionCodeé gerado automaticamente e de forma consistente em qualquer máquina (incluindo um Continuous Integratione / ou Continuous Deploymentservidor).
  2. O aplicativo pode versionCodeser submetido ao GooglePlay.
  3. Não depende de nenhum arquivo fora do repo.
  4. Não envia nada para o repo
  5. Pode ser substituído manualmente, se necessário

Usando a biblioteca gradle-git para cumprir os objetivos acima. Adicione o código abaixo ao diretório build.gradledo seu arquivo /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 <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, é melhor implantar apenas na Google Play Store da mesma filial (por exemplo, master ).

C0D3LIC1OU5
fonte
embora seja, em essência, uma solução elegante, posso imaginar que isso reduziria drasticamente o tempo de construção, dependendo do que exatamente está acontecendo nas 2 linhas do git. Alguma experiência nisso?
Esperançosamente
1
Não noto nenhuma melhora de desempenho se esta etapa for desativada. Temos usado o método localmente e em nossas máquinas de construção por mais de um ano e o desempenho não tem sido um problema. Se você notar qualquer problema de desempenho, me avise!
C0D3LIC1OU5
Embora sua solução seja elegante, ela pode trazer algumas surpresas inesperadas desagradáveis. É fundamental que versionCodes sejam sempre maiores do que na versão anterior. E se você tiver um branch com 50 commits, e então criar outro branch que é mais novo, mas tem apenas 40 commits, talvez devido a esmagar um número de commits de algum recurso mesclado. Eu posso ver muitos motivos pelos quais seu histórico de commits nem sempre seria um fluxo linear de commits incrementais.
JHH
@JHH Esses resultados não são inesperados. Como mencionei em uma nota, esse método funciona melhor ao implantar a partir do mesmo branch.
C0D3LIC1OU5
13

Recentemente, eu estava trabalhando em um plugin gradle para Android que torna a geração de versionCode e versionName automaticamente. há muita personalização. aqui você pode encontrar mais informações sobre ele https://github.com/moallemi/gradle-advanced-build-version

Moallemi
fonte
Este é um ótimo plugin! Obrigado por compartilhar 🙂
Cory Robinson
10

Outra opção, para incrementar o versionCodee o versionName, é usar um carimbo de data / hora.

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 de 1 de janeiro de 2022 formattedDate = date.format ('yyMMddHHmm') excede a capacidade de inteiros

carvaq
fonte
1
A pessoa queria um número de compilação de incremento automático
peter_pilgrim
6
@peter_pilgrim Caro é o OP.
Mateus leu
Eu acho que esta é uma solução elegante, ela não depende de arquivos que podem desaparecer ou não ou que irão aparecer constantemente no git. Também ajuda a identificar de forma única cada construção para, pelo menos, os próximos 22 anos.
Esperançosamente
citando developer.android.com:"Warning: O maior valor Google Play permite versionCode é 2100000000. "Então, o corte é realmente 2021.
ths
Correção para o limite interno: omite os minutos e use o formato de data 'aaMMddHH', o código da versão conterá pelo menos horas.
Pointer Null
10

Para incrementar versionCode apenas na versão de lançamento, faça isso:

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 um c://YourProject/app/version.propertiesarquivo existente , que você criaria manualmente antes da primeira construção para terVERSION_CODE=8

Arquivo version.properties:

VERSION_CODE=8

NickUnuchek
fonte
Em vez disso, coloque-o dentro de uma tarefa e faça com que generateReleaseBuildConfig dependa dessa tarefa.
lagos
versionName "1.0." + getSvnRevision () causa um erro. Onde o método getSvnRevision () está se referindo? Tem certeza de que não deve ser versionName "1.0." + Code (o nome da versão aumentará com o seu código de versão)?
portfólio
1
@portfoliobuilder, substitua getSvnRevision () pelo código
NickUnuchek 01 de
4

Criar arquivo version.properties

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

Mudança 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
}

}

Resultado : 1.1.3.6

Ahmad Aghazadeh
fonte
Obrigado. E por que você inseriu um versionCode em versionName? Mesmo na segunda posição.
CoolMind 01 de
Mas será semelhante a 1.71.3.76, por exemplo. Acho que melhor é 1.3.76, separando-o do código da versão.
CoolMind
Sim . você pode mudar para "$ {_ major} .. $ {_ minor}. $ {_ patch}. $ {_ versionCode}" ou remover o patch
Ahmad Aghazadeh
if (_major == 99) deve ser if (_minor == 99) ??
Anirudh Bagri
2

Defina versionName emAndroidManifest.xml

android:versionName="5.1.5"

android{...}Bloco interno no build.gradlenível do aplicativo:

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

android{...}Bloco externo dentro build.gradledo nível do aplicativo:

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
}

Depois de criar o APK marcado:

android:versionName="5.1.6"

Nota: Se o seu versionName for diferente do meu, você precisa alterar o regex e extrair a lógica das partes .

Sergey Shustikov
fonte
1

Os exemplos mostrados acima não funcionam por diferentes razões

Aqui está minha variante pronta para uso com base nas ideias deste artigo:

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
fonte
0

Créditos para CommonsWare (resposta aceita) Paul Cantrell (Criar arquivo se ele não existir) ahmad aghazadeh (nome e código da versão)

Então eu juntei todas as suas ideias e cheguei a isso. Esta é a solução de arrastar e soltar exatamente para o que o primeiro post pediu.

Ele atualizará automaticamente o versionCode e versionName de acordo com o status da versão. Claro, você pode mover as variáveis ​​para atender às suas necessidades.

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
fonte
0

Usando o Gradle Task Graph , podemos verificar / alternar o tipo de compilação.

A ideia básica é incrementar o versionCode em cada construção. Em cada construção, um contador armazenado no arquivo version.properties . Ele será mantido atualizado a cada nova construção de APK e substituirá a string versionCode no arquivo build.gradle por 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 o script acima dentro do arquivo build.gradle do módulo principal.

Site de referência: http://devdeeds.com/auto-increment-build-number-using-gradle-in-android/

Obrigado e cumprimentos!

Jayakrishnan
fonte
0

O código do primeiro comentário incrementará o número a cada "Reconstruir projeto" e salvará o valor no arquivo "Propriedade da versão".

O código do segundo comentário gerará um novo nome de versão do arquivo APK enquanto "Constrói APKs".

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
fonte
Adicione algum texto mostrando o que você mudou. e por quê
Matthew Kerian
0

na versão Gradle 5.1.1 no mac ive mudou a forma como os nomes das tarefas são recuperados, eu embora tentei obter o tipo / tipo de compilação da compilação, mas estava com preguiça de dividir o nome da tarefa:

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

o código é de @just_user este aqui

Basur
fonte
0

Existem duas soluções de que gosto muito. O primeiro depende da Play Store e o outro depende do Git.

Usando a Play Store, você pode incrementar o código da versão observando o maior código de versão carregado disponível . O benefício desta solução é que o upload de um APK nunca falhará, pois o código da sua versão é sempre um maior do que o que está na Play Store. A desvantagem é que distribuir seu APK fora da Play Store se torna mais difícil. Você pode configurar isso usando o Gradle Play Publisher seguindo o guia de início rápido e dizendo ao plug-in para resolver os códigos de versão automaticamente :

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

android {
    ...
}

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

Usando Git, você pode incrementar o código da versão com base em quantos commits e tags seu repositório possui. O benefício aqui é que sua saída é reproduzível e não depende de nada fora do seu repo. A desvantagem é que você precisa fazer um novo commit ou tag para alterar seu código de versão. Você pode configurar isso adicionando o plug - in Version Master Gradle :

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

android {
    ...
}
SUPERCILEX
fonte