Kod wersji Autoincrement z dodatkowymi właściwościami gradle

121

Tworzę aplikację na Androida za pomocą Gradle. Do tej pory używałem pliku Manifest do zwiększenia versionCode, ale chciałbym odczytać versionCode z pliku zewnętrznego i w zależności od tego, czy jest to smak wydania, czy smak debugowania, zwiększyć versionCode. Wypróbowałem dodatkowe właściwości, ale nie możesz ich zapisać, co oznacza, że ​​następnym razem, gdy go zbuduję, otrzymam ten sam versionCode. Każda pomoc byłaby bardzo mile widziana!

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
źródło
Zobacz moją odpowiedź tutaj: stackoverflow.com/a/33637600/348189
TacB0sS
Inna opcja (podejście „ustaw i zapomnij”): medium.com/@passsy/…
Simon B.
Jedna linijka z wybranymi wtyczkami Gradle: stackoverflow.com/a/61718437/4548500
SUPERCILEX

Odpowiedzi:

207

Chciałbym odczytać versionCode z zewnętrznego pliku

Jestem przekonany, że istnieje wiele możliwych rozwiązań; tutaj jest jeden:

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
}

Ten kod oczekuje istniejącego version.propertiespliku, który należy utworzyć ręcznie przed pierwszą kompilacją VERSION_CODE=8.

Ten kod po prostu wpływa na kod wersji w każdej kompilacji - musisz rozszerzyć technikę, aby obsłużyć kod wersji dla każdego smaku.

Możesz zobaczyć przykładowy projekt kontroli wersji, który demonstruje ten kod.

CommonsWare
źródło
4
Jak włączyć inkrementację tej wersji tylko podczas tworzenia wersji wydania?
Piotr
@Piotr: Jeśli masz na myśli „tylko zwiększaj numer w kompilacji wydania”, powinno to być możliwe, chociaż nie znam szczegółów. Osobiście, ponieważ dostępnych jest około 2 miliardy kodów wersji, zakładam, że nie zabraknie mi ich. :-)
CommonsWare
3
@Piotr utworzyłbyś zadanie, które osobno zwiększa kod wersji, a następnie wykonaj coś podobnego assembleRelease.finalizedBy incrementVersionlub podobnego. Wyślę swój kod, gdy go uporządkuję.
Chris.Jenkins
Korzystając z zadania niestandardowego, możesz po prostu zrobić coś takiego ./gradlew incrementVersionCode build. Zadania nazwane w ten sposób sekwencyjnie zatrzymają się, gdy tylko jedno z zadań zakończy się niepowodzeniem.
Dori,
3
Ponieważ @ chris.jenkins wciąż pracuje nad swoim kodem: p Oto powyższe w formularzu zadań i metod gist.github.com/doridori/544c24509be236c11fd5, które mogą być używane wewnątrz androidowego DSL zversionCode getIncrementingVersionCode()
Dori
83

Oto unowocześnienie mojej poprzedniej odpowiedzi, które można zobaczyć poniżej. Ten działa z Gradle 4.4 i Android Studio 3.1.1 .

Co robi ten skrypt:

  • Tworzy plik version.properties , jeśli żaden nie istnieje (zagłosuj poniżej na odpowiedź Paula Cantrella, skąd wziąłem pomysł, jeśli podoba ci się ta odpowiedź)
  • W przypadku każdej kompilacji, wersji debugowania lub dowolnego naciśnięcia przycisku uruchamiania w Android Studio liczba VERSION_BUILD wzrasta.
  • Za każdym razem, gdy tworzysz wydanie, Twój kod wersji Androida dla sklepu Play rośnie, a numer poprawki rośnie.
  • Bonus: po zakończeniu kompilacji kopiuje Twój apk, projectDir/apkaby był bardziej dostępny.

Ten skrypt utworzy numer wersji, który wygląda jak v1.3.4 (123)i zbuduje plik apk, taki jak AppName-v1.3.4.apk .

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

Wersja główna: W przypadku większych zmian należy ją zmienić ręcznie.

Wersja pomocnicza : W przypadku nieco mniejszych zmian konieczna jest ręczna zmiana.

Wersja poprawki: zwiększa się podczas pracygradle assembleRelease

Wersja kompilacji: zwiększa każdą kompilację

Numer wersji: taki sam jak wersja poprawki , dotyczy kodu wersji, który Sklep Play musi zwiększać przy każdym nowym przesłaniu pliku APK.

Po prostu zmień treść w komentarzach oznaczonych 1 - 3 poniżej, a skrypt zajmie się resztą. :)

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

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

WSTĘPNA ODPOWIEDŹ:

Chcę również, aby nazwa_wersji rosła automatycznie. Więc to tylko dodatek do odpowiedzi autorstwa CommonsWare, która działała idealnie dla mnie. To właśnie działa dla mnie

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

EDYTOWAĆ:

Ponieważ jestem trochę leniwy, chcę, aby moje wersjonowanie działało tak automatycznie, jak to tylko możliwe. Chcę mieć wersję kompilacji, która rośnie wraz z każdą kompilacją, podczas gdy numer wersji i nazwa wersji zwiększają się tylko wtedy, gdy tworzę wersję wydania.

To jest to, czego używam przez ostatni rok, podstawy pochodzą z odpowiedzi CommonsWare i mojej poprzedniej odpowiedzi, a także kilka innych. Powoduje to następującą wersję:

Nazwa wersji: 1.0.5 (123) -> Major.Minor.Patch (Build), Major i Minor są zmieniane ręcznie.

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

    ...
}

...

Łata i versionCode zwiększa się, jeśli można zbudować swój projekt poprzez terminal z „zmontować” , „assembleRelease” lub „AR” , który tworzy nowy folder w katalogu głównym projektu o nazwie apk / release, więc nie trzeba patrzeć przez build / wyjść / more / more / more, aby znaleźć swój apk.

Właściwości Twojej wersji powinny wyglądać następująco:

VERSION_NUMBER=1
VERSION_BUILD=645
VERSION_PATCH=1

Oczywiście zacznij od 0. :)

just_user
źródło
2
Drugi „variant.outputs.each {output ->” może zostać usunięty za pomocą odpowiedniego „}”.
redocoder
Powoduje to, że wszystkie moje kompilacje mają tylko natywny kod x86_64
Chisko
@Chisko Wątpię, czy przyczyną jest ten fragment kodu gradle. Zadaj nowe pytanie i udostępnij swój kod gradle, a my spróbujemy dowiedzieć się, co jest nie tak. :)
just_user
1
Mogę teraz potwierdzić, że to nie była główna przyczyna. Przepraszam.
Chisko
1
@AlexanderGavriliuk to kod wersji używany przez sklep Play, który musi być stale zwiększany przy każdym załadowaniu. Numer poprawki prawdopodobnie zostanie zresetowany, jeśli zwiększysz wersję główną lub pomocniczą. Numer wersji nie powinien nigdy, nigdy nie mógł zostać zresetowany, jeśli prześlesz aplikację do sklepu Play z tą samą nazwą pakietu.
just_user
40

Nieznacznie zaostrzona wersja doskonałej odpowiedzi CommonsWare tworzy plik wersji, jeśli nie istnieje:

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
źródło
gdzie jest część dotycząca tworzenia pliku wersji, jeśli nie istnieje?
portfoliobuilder
4
if(versionPropsFile.exists())zapewnia, że ​​nie wybuchnie, jeśli pliku tam nie ma. versionProps.store(versionPropsFile.newWriter(), null) nadpisuje plik niezależnie od tego, czy już istnieje.
Paul Cantrell
Musiałem sprawdzić, co ?:oznacza Groovy. Operator Elvis jest skrócenie operatora potrójnego.
Daniel,
30

Przyjrzałem się kilku opcjom, aby to zrobić, i ostatecznie zdecydowałem, że łatwiej będzie po prostu użyć bieżącego czasu dla versionCode, zamiast próbować automatycznie zwiększać versionCode i sprawdzać go w moim systemie kontroli wersji.

Dodaj do swojego 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
    }
}

Jeśli jednak spodziewasz się przesłać kompilacje po 2696 roku, możesz użyć innego rozwiązania.

emmby
źródło
2
Jeśli czytasz to teraz i zaczynasz od nowej aplikacji, możesz odjąć 1510351294:))
Entreco
nie rozumiem tego !! Czy nie korzystasz z narzędzi analitycznych, crashlytics ani żadnej innej usługi, która dostarcza dane z kodami wersji i nazwami? i tak łatwo się nimi bawisz?
Amir Ziarati
Jeśli masz rozsądne nazwy wersji, myślę, że jest w porządku. Crashalytics udostępnia również nazwę wersji.
netcyrax
@emmby skąd masz numer „1451606400”? lub „1510351294” z #Entreco, które próbowałem obliczyć na próżno!
Joseph Wambura
18

Innym sposobem versionCodeautomatycznego uzyskania wyniku jest ustawienie versionCodeliczby zatwierdzeń w pobranej gitgałęzi. Realizuje następujące cele:

  1. versionCodejest generowany automatycznie i konsekwentnie na dowolnym komputerze (w tym na serwerze Continuous Integrationi / lub Continuous Deploymentserwerze).
  2. Aplikację z tym versionCodemożna przesłać do Google Play.
  3. Nie opiera się na żadnych plikach poza repozytorium.
  4. Nie przesyła niczego do repozytorium
  5. W razie potrzeby można zmienić ręcznie

Wykorzystanie biblioteki gradle-git do osiągnięcia powyższych celów. Dodaj poniższy kod do swojego build.gradlepliku w /appkatalogu:

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
}

UWAGA: Aby ta metoda zadziałała, najlepiej wdrożyć tylko w sklepie Google Play z tej samej gałęzi (np. master).

C0D3LIC1OU5
źródło
chociaż w istocie jest to eleganckie rozwiązanie, mogę sobie wyobrazić, że spowodowałoby to drastyczne spowolnienie czasu kompilacji, w zależności od tego, co dokładnie dzieje się w 2 liniach gita. Jakieś doświadczenie w tej sprawie?
Mam nadzieję, że
1
Nie zauważam żadnej poprawy wydajności, jeśli ten krok jest wyłączony. Używam metody lokalnie i na naszych maszynach konstrukcyjnych od ponad roku, a wydajność nie stanowi żadnego problemu. Jeśli zauważysz jakiekolwiek problemy z wydajnością, daj mi znać!
C0D3LIC1OU5
Chociaż Twoje rozwiązanie jest eleganckie, może dać niemiłe, nieoczekiwane niespodzianki. Ważne jest, aby kody wersji były zawsze większe niż w poprzedniej wersji. Co jeśli masz jedną gałąź z 50 zatwierdzeniami, a następnie utworzysz inną gałąź, która jest nowsza, ale ma tylko 40 zatwierdzeń, być może z powodu zgniatania liczby zatwierdzeń z jakiejś scalonej funkcji. Widzę wiele powodów, dla których twoja historia zmian nie zawsze byłaby liniowym strumieniem przyrostowych zatwierdzeń.
JHH
@JHH Te wyniki nie są nieoczekiwane. Jak wspomniałem w notatce, ta metoda działa najlepiej podczas wdrażania z tej samej gałęzi.
C0D3LIC1OU5
13

Ostatnio pracowałem nad wtyczką Gradle dla Androida, która automatycznie generuje kod_wersji i nazwę_wersji . istnieje wiele dostosowań. tutaj możesz znaleźć więcej informacji na ten temat https://github.com/moallemi/gradle-advanced-build-version

moallemi
źródło
To świetna wtyczka! Dzięki za udostępnienie 🙂
Cory Robinson
10

Inną opcją do zwiększania wartości versionCodei versionNamejest użycie znacznika czasu.

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
}

Od 1 stycznia 2022 r. FormattedDate = date.format ('rrMMddHHmm') przekracza pojemność liczb całkowitych

carvaq
źródło
1
Osoba chciała mieć numer kompilacji z automatycznym zwiększaniem
peter_pilgrim
6
@peter_pilgrim Caro jest operatorem.
Matthew Przeczytaj
Myślę, że jest to eleganckie rozwiązanie, nie opiera się na plikach, które mogą zniknąć lub nie, lub które będą stale pojawiać się w git. Pomaga również w unikalnej identyfikacji każdej kompilacji na co najmniej następne dwanaście następnych 22 lat.
Miejmy nadzieję, że
powołując developer.android.com:"Warning: Największą wartość Google Play pozwala na versionCode jest 2100000000. "Tak, odcięcia jest faktycznie 2021
tys
Poprawka dla limitu int: pomiń minuty i użyj formatu daty „rrMMddHH”, kod wersji będzie zawierał co najmniej godziny.
Pointer Null
10

Aby zwiększyć versionCode tylko w wydaniu, zrób to:

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
    }

oczekuje istniejącego c://YourProject/app/version.properties pliku, który utworzyłbyś ręcznie przed pierwszą kompilacjąVERSION_CODE=8

Plik version.properties:

VERSION_CODE=8

NickUnuchek
źródło
Zamiast tego umieść go w zadaniu i spraw, aby generator generatedReleaseBuildConfig zależał od tego zadania.
Lagos
versionName "1.0." + getSvnRvision () powoduje błąd. Gdzie odwołuje się metoda getSvnRvdensja ()? Czy na pewno nie powinno to być nazwa_wersji „1.0.” + Kod (nazwa wersji będzie się zwiększać wraz z kodem wersji)?
portfoliobuilder
1
@portfoliobuilder, zamień getSvnRVision () na kod
NickUnuchek
4

Utwórz plik version.properties

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

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

}

Wynik : 1.1.3.6

Ahmad Aghazadeh
źródło
Dzięki. Dlaczego wstawiłeś kod wersji do nazwy_wersji? Nawet na drugiej pozycji.
CoolMind
Ale na przykład będzie wyglądać jak 1.71.3.76. Myślę, że lepszy jest 1.3.76, oddzielając go od kodu wersji.
CoolMind
Tak . możesz zmienić na „$ {_ major} .. $ {_ minor}. $ {_ patch}. $ {_ versionCode}” lub usunąć poprawkę
Ahmad Aghazadeh
if (_major == 99) powinno być if (_minor == 99) ??
Anirudh Bagri
2

Zdefiniuj nazwę wersji wAndroidManifest.xml

android:versionName="5.1.5"

Wewnątrz android{...}bloku na build.gradlepoziomie aplikacji:

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

Poza android{...}blokadą build.gradlepoziomu aplikacji:

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
}

Po utworzeniu podpisanego APK:

android:versionName="5.1.6"

Uwaga: Jeśli twoja nazwa_wersji różni się od my, musisz zmienić regex i wyodrębnić logikę części .

Sergey Shustikov
źródło
1

Przykłady pokazane powyżej nie działają z różnych powodów

Oto mój gotowy do użycia wariant oparty na pomysłach z tego artykułu:

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
źródło
0

Kredyty dla CommonsWare (zaakceptowana odpowiedź) Paul Cantrell (Utwórz plik, jeśli nie istnieje) ahmad aghazadeh (nazwa i kod wersji)

Więc zebrałem razem wszystkie ich pomysły i wymyśliłem to. To jest rozwiązanie typu „przeciągnij i upuść”, dokładnie o to, o co pytał pierwszy post.

Automatycznie zaktualizuje versionCode i versionName zgodnie ze stanem wydania. Oczywiście możesz przesuwać zmienne w zależności od swoich potrzeb.

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
}
Piorun
źródło
0

Korzystając z Gradle Task Graph możemy sprawdzić / zmienić typ kompilacji.

Podstawowym pomysłem jest inkrementacja versionCode przy każdej kompilacji. Na każdej kompilacji licznik przechowywany w pliku version.properties . Będzie aktualizowany przy każdej nowej kompilacji APK i zastąpi ciąg versionCode w pliku build.gradle tą zwiększoną wartością licznika.

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

Umieść powyższy skrypt w pliku build.gradle modułu głównego.

Witryna referencyjna: http://devdeeds.com/auto-increment-build-number-using-gradle-in-android/

Dziękuję i pozdrawiam!

Jayakrishnan
źródło
0

Kod z pierwszym komentarzem będzie zwiększał liczbę podczas każdego „Przebudowywania projektu” i zapisuje wartość w pliku „Właściwość wersji”.

Kod z drugim komentarzem wygeneruje nową nazwę wersji pliku APK podczas „Budowania plików APK”.

android {
    compileSdkVersion 28
    buildToolsVersion "29.0.0"
    //==========================START==================================
    def Properties versionProps = new Properties()
    def versionPropsFile = file('version.properties')
    if(versionPropsFile.exists())
        versionProps.load(new FileInputStream(versionPropsFile))
    def code = (versionProps['VERSION_CODE'] ?: "0").toInteger() + 1
    versionProps['VERSION_CODE'] = code.toString()
    versionProps.store(versionPropsFile.newWriter(), null)
    //===========================END===================================
    defaultConfig {
        applicationId "com.example.myapp"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "0.19"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            //=======================================START===============================================
            android.applicationVariants.all { variant ->
                variant.outputs.all {
                    def appName = "MyAppSampleName"
                    outputFileName = appName+"_v${variant.versionName}.${versionProps['VERSION_CODE']}.apk"
                }
            }
            //=======================================END===============================================
        }
    }
}
Radha Krishna Eedulakanti
źródło
Dodaj tekst pokazujący, co zmieniłeś. i dlaczego
Matthew Kerian
0

w wersji Gradle 5.1.1 na mac ive zmienił się sposób pobierania nazw zadań, chociaż próbowałem uzyskać smak / typ kompilacji z kompilacji, ale byłem zbyt leniwy, aby podzielić nazwę zadania:

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

kod pochodzi od @just_user tego

Basur
źródło
0

Są dwa rozwiązania, które bardzo mi się podobają. Pierwsza zależy od Sklepu Play, a druga od Gita.

Korzystając ze Sklepu Play, możesz zwiększyć kod wersji, patrząc na najwyższy dostępny przesłany kod wersji. Zaletą tego rozwiązania jest to, że przesyłanie APK nigdy się nie powiedzie, ponieważ kod wersji jest zawsze o jeden wyższy niż w Sklepie Play. Wadą jest to, że dystrybucja pakietu APK poza Sklep Play staje się trudniejsza. Możesz to ustawić za pomocą Gradle Play Publisher, postępując zgodnie z przewodnikiem szybkiego startu i informując wtyczkę, aby automatycznie rozwiązała kody wersji :

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

android {
    ...
}

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

Korzystając z Git, możesz zwiększać kod wersji w oparciu o liczbę zatwierdzeń i tagów w repozytorium. Zaletą jest to, że wynik jest odtwarzalny i nie zależy od niczego poza repozytorium. Wadą jest to, że musisz utworzyć nowe zatwierdzenie lub tag, aby podbić kod wersji. Możesz to ustawić, dodając wtyczkę Version Master Gradle :

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

android {
    ...
}
SUPERCILEX
źródło