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

121

Я создаю приложение для Android с помощью gradle. До сих пор я использовал файл манифеста для увеличения 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'
}
carvaq
источник
См. Мой ответ здесь: stackoverflow.com/a/33637600/348189
TacB0sS
Другой вариант (подход «поставил и забыл»): medium.com/@passsy/…
Саймон Б.
Однострочник

Ответы:

207

Я хочу прочитать код версии из внешнего файла

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

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.

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

Вы можете увидеть образец проекта управления версиями , демонстрирующий этот код.

CommonsWare
источник
4
Как включить приращение этой версии только при создании релизных сборок?
Петр
@Piotr: Если вы имеете в виду «увеличивать число только в сборке релиза», это должно быть возможно, хотя я не знаю подробностей. Лично, поскольку доступно ~ 2 миллиарда кодов версий, я предполагаю, что у меня не закончится. :-)
CommonsWare
3
@Piotr, вы должны создать задачу, которая отдельно увеличивает код версии, а затем делает что-то вроде assembleRelease.finalizedBy incrementVersionили что-то подобное. Я отправлю свой код, как только приведу его в порядок.
Chris.Jenkins
Используя настраиваемую задачу, вы можете просто сделать что-то вроде ./gradlew incrementVersionCode build. Задачи, вызываемые таким образом последовательно, будут остановлены, как только какая-либо из задач завершится ошибкой.
Dori
3
Поскольку @ chris.jenkins все еще работает над своим кодом: p Вот приведенное выше в форме задачи и метода gist.github.com/doridori/544c24509be236c11fd5, которую можно использовать внутри Android DSL сversionCode getIncrementingVersionCode()
Дори
83

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

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

  • Создает файл version.properties, если он не существует (ответ Пола Кантрелла «за» ниже, откуда я получил идею, если вам нравится этот ответ)
  • Для каждой сборки, отладочной версии или при каждом нажатии кнопки запуска в Android Studio число VERSION_BUILD увеличивается.
  • Каждый раз, когда вы собираете релиз, ваш код версии Android для магазина воспроизведения увеличивается, а номер патча увеличивается.
  • Бонус: после завершения сборки скопируйте ваш 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 {
        ...
    }
}

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

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

Я хочу, чтобы имя версии также увеличивалось автоматически. Так что это просто дополнение к ответу 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 увеличиваются , если вы собираете свой проект через терминал «сборка» , «assembleRelease» или «Аr» , который создает новую папку в корневом каталоге проекта под названием APK / RELEASE , поэтому вам не нужно просматривать сборки / выходы / more / more / more, чтобы найти свой apk.

Свойства вашей версии должны выглядеть так:

VERSION_NUMBER=1
VERSION_BUILD=645
VERSION_PATCH=1

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

just_user
источник
2
Второй вариант 'option.outputs.each {output ->' можно удалить с помощью соответствующего '}'.
редокодер
Это вызывает все мои строит быть в только x86_64 нативный код
Chisko
@Chisko Я сомневаюсь, что этот фрагмент кода Gradle является причиной. Задайте новый вопрос и поделитесь своим кодом Gradle, и мы попытаемся выяснить, что не так. :)
just_user
1
Теперь я могу подтвердить, что это не было основной причиной. Мои извинения.
Chisko
1
@AlexanderGavriliuk - это код версии, используемый игровым магазином, который постоянно должен увеличиваться при каждой загрузке. Номер патча, вероятно, будет сброшен, если вы увеличите основную или вспомогательную версию. Номер версии никогда, никогда не может быть сброшен, если вы загрузите приложение в магазин воспроизведения с тем же именем пакета.
just_user
40

Слегка усиленная версия отличного ответа 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
}
Пол Кантрелл
источник
где находится часть создания файла версии, если он не существует?
Создатель портфолио
4
if(versionPropsFile.exists())гарантирует, что он не взорвется, если файла нет. versionProps.store(versionPropsFile.newWriter(), null) перезаписывает файл независимо от того, существует ли он уже.
Пол Кантрелл
Пришлось проверить, что имеется в ?:виду в Groovy. Оператор Элвиса - это сокращение от тернарного оператора.
Дэниел
30

Я рассмотрел несколько вариантов, чтобы сделать это, и в конечном итоге решил, что проще просто использовать текущее время для 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 года, вы можете использовать другое решение.

emmby
источник
2
Если вы читаете это сейчас и начинаете с нового приложения, вы можете вычесть 1510351294:))
Entreco
я не понимаю !! Разве вы не используете аналитику, крашлитику или какой-либо другой сервис, который предоставляет данные с кодами версий и названиями? и ты с этим легко играешься?
Амир Зиарати
Если у вас есть разумные названия версий, думаю, ничего страшного. Crashalytics также предоставляет название версии.
netcyrax
@emmby откуда взять номер "1451606400"? или «1510351294» от #Entreco, которые я тщетно пытался вычислить!
Джозеф Вамбура,
18

Другой способ 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 Store только из той же ветки (например master).

C0D3LIC1OU5
источник
хотя по сути это элегантное решение, я могу представить, что это резко замедлит время сборки, в зависимости от того, что именно происходит в двух строках git. Есть опыт по этому поводу?
HopefullyHelpful
1
Я не замечаю улучшения производительности, если этот шаг отключен. Мы использовали метод локально и на наших сборочных машинах более года, и производительность не была проблемой. Если вы заметите какие-либо проблемы с производительностью, дайте мне знать!
C0D3LIC1OU5
Хотя ваше решение элегантно, оно может преподнести неприятные неожиданные сюрпризы. Очень важно, чтобы коды версий всегда были больше, чем в предыдущем выпуске. Что делать, если у вас есть одна ветка с 50 коммитами, а затем вы создаете другую ветку, более новую, но имеющую только 40 коммитов, возможно, из-за раздавливания количества коммитов из какой-то объединенной функции. Я вижу множество причин, по которым ваша история коммитов не всегда будет линейным потоком инкрементных коммитов.
JHH
@JHH Эти результаты не являются неожиданными. Как я уже упоминал в примечании, этот метод лучше всего работает при развертывании из одной и той же ветки.
C0D3LIC1OU5
13

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

moallemi
источник
Это отличный плагин! Спасибо, что поделились 🙂
Кори Робинсон
10

Другой вариант увеличения 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') превышает допустимую для целых чисел

carvaq
источник
1
Человек хотел номер сборки с автоинкрементом
peter_pilgrim
6
@peter_pilgrim Каро - ОП.
Мэтью Рид
Я думаю, что это элегантное решение, оно не полагается на файлы, которые могут исчезнуть или нет, или которые будут постоянно появляться в git. Это также поможет вам однозначно идентифицировать каждую сборку как минимум на ближайшие 22 года.
HopefullyHelpful
процитировать developer.android.com:"Warning: Наибольшее значение Google Play позволяет VersionCode это 2100000000. "Так, отсечка на самом деле 2021
тыс
Исправление для int limit: опускайте минуты и используйте формат даты «yyMMddHH», код версии будет содержать как минимум часы.
Pointer Null
10

Чтобы увеличить 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

NickUnuchek
источник
Скорее поместите его в задачу и сделайте generateReleaseBuildConfig зависимым от этой задачи.
Лагос,
versionName "1.0." + getSvnRevision () вызывает ошибку. На что ссылается метод getSvnRevision ()? Вы уверены, что это не должно быть versionName "1.0." + Code (имя версии будет увеличиваться с увеличением кода версии)?
portfoliobuilder
1
@portfoliobuilder, замените getSvnRevision () на код
NickUnuchek 01
4

Создать файл 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

Ахмад Агазаде
источник
Спасибо. И почему вы вставили versionCode в versionName? Даже на второй позиции.
CoolMind 01
Но, например, он будет выглядеть как 1.71.3.76. Думаю, лучше 1.3.76, отделив его от кода версии.
CoolMind 02
Да . вы можете изменить его на "$ {_ major} .. $ {_ minor}. $ {_ patch}. $ {_ versionCode}" или удалить патч
Ахмад Агазаде
if (_major == 99) должно быть if (_minor == 99) ??
Анируд Багри 02
2

Определить 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"

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

Сергей Шустиков
источник
1

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

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

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

        ...
    }
...
}
Александр Гаврилюк
источник
0

Кредиты для 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
}
Thunderstick
источник
0

Используя 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/

С уважением!

Джайякришнана
источник
0

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

Второй прокомментированный код сгенерирует новое имя версии файла 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===============================================
        }
    }
}
Радха Кришна Эедулаканти
источник
Добавьте текст, показывающий, что вы изменили. и почему
Мэтью Кериан
0

в версии 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 этот

Basur
источник
0

Мне очень нравятся два решения. Первый зависит от 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 {
    ...
}
SUPERCILEX
источник