Автоинкремент VersionCode с дополнительными свойствами gradle

Я создаю приложение для Android с Gradle. До сих пор я использовал файл Manifest для увеличения versionCode, но я хотел бы прочитать versionCode из внешнего файла и в зависимости от того, является ли это релизным или отладочным, увеличить versionCode. Я пробовал дополнительные свойства, но вы не можете их сохранить, а это значит, что в следующий раз, когда я создаю их, я получаю тот же код версии. Любая помощь будет очень высоко ценится!

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

17 ответов

Решение

Я хотел бы прочитать versionCode из внешнего файла

Я уверен, что существует множество возможных решений; вот один:

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
}

Этот код ожидает существующий version.properties файл, который вы создадите вручную до первой сборки VERSION_CODE=8,

Этот код просто изменяет код версии в каждой сборке - вам нужно будет расширить технику для обработки кода версии для каждого варианта.

Вы можете увидеть пример проекта Versioning, который демонстрирует этот код.

Здесь идет модернизация моего предыдущего ответа, который можно увидеть ниже. Этот работает с Gradle 4.4 и Android Studio 3.1.1.

Что делает этот скрипт:

  • Создает файл version.properties, если его нет (голосование Пола Кантрелла ниже, откуда я пришла идея, если вам нравится этот ответ)
  • Для каждой сборки, отладочной версии или любого нажатия кнопки запуска в Android Studio число VERSION_BUILD увеличивается.
  • Каждый раз, когда вы собираете релиз, ваш Android versionCode для магазина игр увеличивается, а номер вашего патча увеличивается.
  • Бонус: после завершения сборки скопируйте ваш apk в projectDir/apk чтобы сделать его более доступным.

Этот скрипт создаст номер версии, который выглядит как v1.3.4 (123) и создайте файл apk, такой как AppName-v1.3.4.apk.

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

Основная версия: должна быть изменена вручную для больших изменений.

Незначительная версия: должна быть изменена вручную для чуть менее значительных изменений.

Патч версия: увеличивается при запуске gradle assembleRelease

Версия сборки: увеличивает каждую сборку

Номер версии: То же, что и версия патча, это для кода версии, который Play Store должен увеличивать для каждой новой загрузки APK.

Просто измените содержимое в комментариях с пометкой 1 - 3 ниже, и скрипт должен сделать все остальное.:)

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

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

НАЧАЛЬНЫЙ ОТВЕТ:

Я хочу, чтобы version Name также увеличивался автоматически. Так что это всего лишь дополнение к ответу CommonsWare, который отлично сработал для меня. Это то, что работает для меня

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

РЕДАКТИРОВАТЬ:

Поскольку я немного ленив, я хочу, чтобы мои версии работали как можно более автоматически. Я хочу иметь версию сборки, которая увеличивается с каждой сборкой, тогда как номер версии и имя версии увеличиваются только тогда, когда я делаю сборку выпуска.

Это то, что я использовал в течение прошлого года, основы взяты из ответа CommonsWare и моего предыдущего ответа, а также некоторых других. Это приводит к следующей версии:

Название версии: 1.0.5 (123) -> Major.Minor.Patch (Build), Major и Minor изменяются вручную.

В 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 и versionCode увеличиваются, если вы собираете свой проект через терминал с помощью " assembly", "assemblyRelease " или "aR", которое создает новую папку в корневом каталоге вашего проекта с именем apk/RELEASE, поэтому вам не нужно просматривать build/output /more/more/more, чтобы найти ваш apk.

Свойства вашей версии должны выглядеть следующим образом:

VERSION_NUMBER=1
VERSION_BUILD=645
VERSION_PATCH=1

Очевидно, начать с 0.:)

Слегка затянутая версия превосходного ответа CommonsWare создает файл версии, если он не существует:

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
}

Я посмотрел на несколько вариантов, чтобы сделать это, и в итоге решил, что проще использовать текущее время для versionCode, а не пытаться автоматически увеличивать versionCode и проверять его в моей системе контроля версий.

Добавьте следующее к вашему 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
    }
}

Однако, если вы планируете загружать сборки после 2696 года, вы можете использовать другое решение.

Еще один способ получить versionCode автоматически устанавливается versionCode на количество коммитов в проверенном git ветка. Он решает следующие задачи:

  1. versionCode генерируется автоматически и последовательно на любой машине (включая Continuous Integration и / или Continuous Deployment сервер).
  2. Приложение с этим versionCode можно отправить в GooglePlay.
  3. Не полагается ни на какие файлы вне репо.
  4. Ничего не подталкивает к репо
  5. При необходимости может быть переопределено вручную

Использование библиотеки Gradle-Git для достижения вышеуказанных целей. Добавьте код ниже к вашему build.gradle подать /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
}

ПРИМЕЧАНИЕ. Чтобы этот метод работал, лучше всего развертывать его в магазине Google Play из той же ветки (например, master).

Создать файл version.properties

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

+ Изменить 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
}

}

Выход: 1.1.3.6

Недавно я работал над плагином Gradle для Android, который автоматически генерирует versionCode и versionName. Есть много настроек. здесь вы можете найти больше информации об этом https://github.com/moallemi/gradle-advanced-build-version

Для увеличения versionCode только в версии выпуска сделайте это:

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
    }

ожидает существующий c://YourProject/app/version.properties файл, который вы создадите вручную до первой сборки VERSION_CODE=8

файл version.properties:

VERSION_CODE=8

Другой вариант, для увеличения versionCode и versionNameиспользует временную метку.

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
}

Начиная с 1 января 2022 г. formattedDate = date.format('yyMMddHHmm') превышает емкость целых чисел

Приведенные выше примеры не работают по разным причинам.

Вот мой готовый вариант, основанный на идеях из этой статьи:

android {
    compileSdkVersion 28

    // https://stackru.com/questions/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)"

        ...
    }
...
}

Определить versionName в AndroidManifest.xml

android:versionName="5.1.5"

внутри android{...} блокировать в build.gradle уровня приложения:

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

за пределами android{...} блокировать в build.gradle уровня приложения:

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
}

После создания подписанного APK:

android:versionName="5.1.6"

Примечание: если ваше versionName отличается от моего, вам нужно изменить регулярное выражение и извлечь логику частей.

Вместо того, чтобы указывать новую версию в файле свойств, я создал задачу Gradle, которая может обновлять текущую версию. versionName а также versionCode автоматически, а также может получить строку новой версии из командной строки (передав аргументы задаче с -Pза которым следует <argName> = <argValue>).

приложение build.gradle.kts:

      project.version = "1.2.3"

tasks.create("incrementVersion") {
    group = "versioning"
    description = "Increments the version to make the app ready for next release."
    doLast {
        var (major, minor, patch) = project.version.toString().split(".")
        val mode = project.properties["mode"]?.toString()?.toLowerCaseAsciiOnly()
        if (mode == "major") {
            major = (major.toInt() + 1).toString()
            minor = "0"
            patch = "0"
        } else if (mode == "minor") {
            minor = (minor.toInt() + 1).toString()
            patch = "0"
        } else {
            patch = (patch.toInt() + 1).toString()
        }
        var newVersion = "$major.$minor.$patch"

        val overrideVersion = project.properties["overrideVersion"]?.toString()?.toLowerCaseAsciiOnly()
        overrideVersion?.let { newVersion = it }

        val newBuild = buildFile
            .readText()
            .replaceFirst(Regex("version = .+"), "version = \"$newVersion\"")
            .replaceFirst(Regex("versionName = .+\""), "versionName = \"$newVersion\"")
            .replaceFirst(Regex("versionCode = \\d+"), "versionCode = ${(android.defaultConfig.versionCode ?: 0) + 1}")
        buildFile.writeText(newBuild)
    }
}

Применение:

      gradlew incrementVersion [-P[mode=major|minor|patch]|[overrideVersion=x.y.z]]

Примеры:

      gradlew :app:incrementVersion -Pmode=major
      gradlew :app:incrementVersion -PoverrideVersion=4.5.6

Кредиты для CommonsWare (Принятый ответ) Пол Кантрелл (Создать файл, если он не существует) Ахмад Агхазаде (Название версии и код)

Поэтому я собрал все их идеи вместе и придумал это. Это решение для перетаскивания в точности к тому, о чем говорилось в первом посте.

Он автоматически обновит versionCode и versionName в соответствии со статусом релиза. Конечно, вы можете перемещать переменные в соответствии со своими потребностями.

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
}

Мне очень нравятся два решения. Первый зависит от Play Store, а другой - от Git.

Используя Play Store, вы можете увеличить код версии, посмотрев на самый высокий доступный код загруженной версии. Преимущество этого решения в том, что загрузка APK никогда не завершится ошибкой, поскольку код вашей версии всегда на единицу выше, чем код версии в Play Store. Обратной стороной является то, что распространять APK за пределами Play Store становится сложнее. Вы можете настроить это с помощью Gradle Play Publisher, следуя руководству по быстрому запуску и указав плагину автоматически разрешать коды версий:

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

android {
    ...
}

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

Используя Git, вы можете увеличивать код версии в зависимости от того, сколько коммитов и тегов имеет ваш репозиторий. Преимущество здесь в том, что ваш результат воспроизводится и не зависит от чего-либо, кроме вашего репо. Обратной стороной является то, что вам нужно сделать новую фиксацию или тег, чтобы увеличить код версии. Вы можете настроить это, добавив плагин Version Master Gradle:

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

android {
    ...
}

Используя Gradle Task Graph, мы можем проверить / переключить тип сборки.

Основная идея заключается в увеличении кода версии для каждой сборки. Счетчик каждой сборки хранится в файле version.properties. Он будет обновляться при каждой новой сборке APK и заменять строку versionCode в файле build.gradle этим увеличенным значением счетчика.

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

Поместите приведенный выше скрипт в файл build.gradle основного модуля.

Справочный веб-сайт: http://devdeeds.com/auto-increment-build-number-using-gradle-in-android/

С уважением!

Первый прокомментированный код будет увеличивать число при каждом "перестроении проекта" и сохранять значение в файле "Свойство версии".

Второй закомментированный код сгенерирует имя новой версии APK-файла во время "сборки 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===============================================
        }
    }
}

В версии Gradle 5.1.1 на Mac ive изменил способ получения имен задач, хотя я пытался получить тип / тип сборки из сборки, но мне было лениво разделить имя задачи:

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

код от @just_user этот

Другие вопросы по тегам