Gradle 추가 속성을 사용하여 VersionCode 자동 증가


121

Gradle로 Android 앱을 만들고 있습니다. 지금까지는 Manifest 파일을 사용하여 versionCode를 높였지만 외부 파일에서 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'
}

여기 내 대답을 참조하십시오 : stackoverflow.com/a/33637600/348189
TacB0sS

또 다른 옵션 (설정 후 삭제 접근 방식) : medium.com/@passsy/…
Simon B.

선택한 Gradle 플러그인이있는 한
줄짜리

답변:


207

외부 파일에서 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.

이 코드는 단순히 각 빌드의 버전 코드를 범프합니다. 각 버전 코드를 처리하려면 기술을 확장해야합니다.

이 코드를 보여주는 버전 관리 샘플 프로젝트 를 볼 수 있습니다 .


4
릴리스 빌드를 만드는 동안에 만이 버전 증가를 활성화하는 방법은 무엇입니까?
Piotr

@Piotr : "릴리스 빌드에서 숫자 만 증가"를 의미한다면, 세부 사항은 모르지만 가능해야합니다. 개인적으로 사용 가능한 버전 코드가 20 억 개에 달하기 때문에 다 떨어지지 않을 것이라고 가정합니다. :-)
CommonsWare 2014

3
@Piotr 당신은 버전 코드를 별도로 증가시키는 작업을 만든 다음 assembleRelease.finalizedBy incrementVersion비슷한 작업을 수행합니다 . 정리가 끝나면 코드를 게시하겠습니다.
Chris.Jenkins 2014 년

사용자 지정 작업을 사용하면 다음과 같은 작업을 수행 할 수 있습니다 ./gradlew incrementVersionCode build. 이러한 방식으로 순차적으로 호출 된 작업은 작업이 실패하는 즉시 중지됩니다.
Dori

3
@ chris.jenkins가 여전히 자신의 코드를 알려주고 있습니다. p 다음은 위의 작업 및 메서드 양식 gist.github.com/doridori/544c24509be236c11fd5입니다. 이는 Android DSL 내부에서 사용할 수 있습니다.versionCode getIncrementingVersionCode()
Dori

83

아래에서 볼 수있는 이전 답변의 현대화가 있습니다. 이것은 Gradle 4.4Android Studio 3.1.1에서 실행됩니다 .

이 스크립트의 기능 :

  • 존재하지 않는 경우 version.properties 파일을 생성 합니다 (이 답변이 마음에 들면 아이디어를 얻은 아래 Paul Cantrell의 답변에 찬성 투표)
  • 각 빌드, 디버그 릴리스 또는 Android 스튜디오에서 실행 버튼을 누를 때마다 VERSION_BUILD 번호가 증가합니다.
  • 릴리스를 조립할 때마다 플레이 스토어 의 Android 버전 코드 가 증가하고 패치 번호가 증가합니다.
  • 보너스 : 빌드가 완료되면 APK를 projectDir/apk에 복사하여 더 쉽게 액세스 할 수 있습니다.

이 스크립트는 AppName-v1.3.4.apkv1.3.4 (123) 와 같은 apk 파일을 빌드하는 버전 번호를 생성합니다 .

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

메이저 버전 : 더 큰 변경을 위해 수동으로 변경해야합니다.

부 버전 : 약간 덜 큰 변경을 위해 수동으로 변경해야합니다.

패치 버전 : 실행시 증가gradle assembleRelease

빌드 버전 : 모든 빌드를 늘립니다.

버전 번호 : 패치 버전 과 동일하며 , 새 APK 업로드마다 Play 스토어에서 증가시켜야하는 버전 코드입니다.

아래의 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 {
        ...
    }
}

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

초기 답변 :

versionName도 자동으로 증가하기를 원합니다. 그래서 이것은 저에게 완벽하게 작동하는 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!")
    }

    ...
}

...

'assemble' , 'assembleRelease' 또는 'aR' 을 사용 하여 터미널을 통해 프로젝트를 어셈블하면 패치 및 버전 코드가 증가 하여 프로젝트 루트에 apk / RELEASE라는 새 폴더를 생성하므로 빌드 / 출력을 살펴볼 필요가 없습니다. / more / more / more에서 APK를 찾으세요.

버전 속성은 다음과 같아야합니다.

VERSION_NUMBER=1
VERSION_BUILD=645
VERSION_PATCH=1

분명히 0으로 시작합니다. :)


2
두 번째 'variant.outputs.each {output->'는 해당 '}'로 제거 할 수 있습니다.
redocoder

이것은 내 빌드 모든 x86_64의 네이티브 코드에만있는 것으로 일으키는
Chisko

@Chisko 나는 gradle 코드 의이 부분이 원인이라고 의심합니다. 새로운 질문을하고 gradle 코드를 공유하면 무엇이 잘못되었는지 알아낼 수 있습니다. :)
just_user

1
이제 이것이 근본 원인이 아님을 확인할 수 있습니다. 죄송합니다.
Chisko 2017

1
@AlexanderGavriliuk는 업로드 할 때마다 지속적으로 증가해야하는 플레이 스토어에서 사용하는 버전 코드입니다. 주 버전 또는 부 버전을 늘리면 패치 번호가 재설정 될 수 있습니다. 동일한 패키지 이름으로 앱을 Play 스토어에 업로드하는 경우 버전 번호는 절대 재설정되지 않아야합니다.
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
}

존재하지 않는 경우 버전 파일을 만드는 부분은 어디에 있습니까?
Portfoliobuilder

4
if(versionPropsFile.exists())파일이 없으면 폭발하지 않도록합니다. versionProps.store(versionPropsFile.newWriter(), null) 파일이 이미 존재하는지 여부에 관계없이 파일을 덮어 씁니다.
Paul Cantrell 2015 년

?:Groovy에서 의미 하는 바를 확인해야 했습니다. 엘비스 연산자 원계 연산자의 단축이다.
Daniel

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 년 이후에 빌드를 업로드하려는 경우 다른 솔루션을 사용할 수 있습니다.


2
지금 읽고 있고 새 앱으로 시작하는 경우 1510351294
빼면됩니다.

나는 이것을 얻지 않는다! 분석이나 crashlytics 또는 버전 코드와 이름으로 데이터를 제공하는 기타 서비스를 사용하지 않습니까? 이것들을 쉽게 가지고 놀 수 있습니까?
Amir Ziarati

합리적인 버전 이름이 있으면 괜찮다고 생각합니다. Crashalytics는 버전 이름도 제공합니다.
netcyrax

@emmby '1451606400'번호는 어디서 얻습니까? 또는 #Entreco의 '1510351294'는 헛된 계산을 시도했습니다!
Joseph Wambura

18

versionCode자동으로 가져 오는 또 다른 방법은 versionCode체크 아웃 된 git분기 의 커밋 수를 설정 하는 것 입니다. 다음 목표를 달성합니다.

  1. versionCode모든 컴퓨터 ( Continuous Integration및 / 또는 Continuous Deployment서버 포함)에서 자동으로 일관되게 생성됩니다 .
  2. 이 앱 versionCode은 GooglePlay에 제출할 수 있습니다.
  3. 저장소 외부의 파일에 의존하지 않습니다.
  4. repo에 아무것도 푸시하지 않습니다.
  5. 필요한 경우 수동으로 재정의 할 수 있습니다.

사용 Gradle을-자식 도서관은 위의 목표를 달성합니다. 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.


본질적으로 우아한 솔루션이지만 2 git 라인에서 정확히 무슨 일이 일어나고 있는지에 따라 빌드 시간이 크게 느려질 것이라고 상상할 수 있습니다. 그것에 대한 경험이 있습니까?
HopefullyHelpful

1
이 단계를 비활성화하면 성능이 향상되지 않습니다. 1 년 이상 로컬 및 빌드 머신에서 메서드를 사용해 왔으며 성능은 전혀 문제가되지 않았습니다. 성능 문제가 발견되면 알려주세요!
C0D3LIC1OU5

귀하의 솔루션은 우아하지만 예상치 못한 놀라움을 줄 수 있습니다. versionCodes는 항상 이전 릴리스보다 더 큰 것이 중요합니다. 50 개의 커밋이있는 하나의 브랜치가 있고, 일부 병합 된 기능에서 여러 커밋을 스쿼시하기 때문에 더 새롭지 만 40 개의 커밋 만있는 다른 브랜치를 생성한다면 어떨까요? 커밋 내역이 항상 증분 커밋의 선형 스트림이 아닌 많은 이유를 알 수 있습니다.
JHH

@JHH 그 결과는 예상치 못한 것이 아닙니다. 메모에서 언급했듯이이 방법은 동일한 브랜치에서 배포 할 때 가장 잘 작동합니다.
C0D3LIC1OU5


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
}

2022 년 1 월부터 formattedDate = date.format ( 'yyMMddHHmm')이 정수 용량을 초과합니다.


1
그 사람은 자동 증가 빌드 번호를 원했습니다
peter_pilgrim

6
@peter_pilgrim Caro는 OP입니다.
마태 복음 읽기

나는 이것이 우아한 해결책이라고 생각하며 사라지거나 사라지거나 git에 지속적으로 표시되는 파일에 의존하지 않습니다. 또한 최소한 향후 22 년 동안 각 빌드를 고유하게 식별하는 데 도움이됩니다.
HopefullyHelpful

quoting developer.android.com : "경고 : Google Play에서 versionCode에 허용하는 가장 큰 값은 2100000000입니다."따라서 마감은 실제로 2021 년입니다.
ths

정수 제한 수정 : 분을 생략하고 날짜 형식 'yyMMddHH'를 사용하면 버전 코드에 최소 시간이 포함됩니다.
포인터 널

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


오히려 작업 안에 넣고 generateReleaseBuildConfig가 해당 작업에 의존하도록 만드십시오.
라고스

versionName "1.0."+ getSvnRevision ()은 오류를 발생시킵니다. getSvnRevision () 메서드는 어디를 참조합니까? versionName "1.0."+ 코드 (버전 코드와 함께 버전 이름이 증가 함)가 아니어야합니까?
Portfoliobuilder

1
@portfoliobuilder, 코드 getSvnRevision ()를 대체
NickUnuchek

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

그러나 예를 들어 1.71.3.76처럼 보일 것입니다. 1.3.76이 버전 코드와 분리 된 것이 더 낫다고 생각합니다.
CoolMind

예 . "$ {_ major} .. $ {_ minor}. $ {_ patch}. $ {_ versionCode}"로 변경하거나 패치를 제거 할 수 있습니다
Ahmad Aghazadeh

if (_major == 99)는 if (_minor == 99) ??
사진 제공 : Anirudh 바 그리

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
}

singed APK 생성 후 :

android:versionName="5.1.6"

참고 : versionName 이 my와 다른 경우 정규식을 변경 하고 부분 논리를 추출 해야합니다 .


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에 대한 크레딧 (허용 된 답변) Paul Cantrell (존재하지 않는 경우 파일 생성) ahmad aghazadeh (버전 이름 및 코드)

그래서 저는 그들의 모든 아이디어를 모아서 이것을 생각해 냈습니다. 이것은 첫 번째 게시물이 요청한 것과 정확히 일치하는 드래그 앤 드롭 솔루션입니다.

릴리스 상태에 따라 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
}

0

Gradle Task Graph를 사용하여 빌드 유형을 확인 / 전환 수 있습니다 .

기본 아이디어는 각 빌드 에서 versionCode 를 증가시키는 것입니다 . 각 빌드에서 version.properties 파일에 저장된 카운터를 만듭니다 . 모든 새 APK 빌드에서 계속 업데이트되고 build.gradle 파일의 versionCode 문자열 을이 증가 된 카운터 값으로 바꿉니다 .

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

First Commented 코드는 각 "Rebuild Project"동안 숫자를 증가시키고 "Version Property"파일에 값을 저장합니다.

Second Commented 코드는 "Build APKs"동안 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===============================================
        }
    }
}

변경 한 내용을 보여주는 텍스트를 추가하십시오. 왜
마 Kerian

0

Mac ive의 Gradle 5.1.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.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에서 가져온 것입니다.


0

내가 정말 좋아하는 두 가지 솔루션이 있습니다. 첫 번째는 Play 스토어에 의존하고 다른 하나는 Git에 의존합니다.

Play 스토어를 사용하면 사용 가능한 가장 높은 업로드 버전 코드를 확인 하여 버전 코드를 늘릴 수 있습니다 . 이 솔루션의 장점은 버전 코드가 항상 Play 스토어에있는 것보다 하나 높기 때문에 APK 업로드가 실패하지 않는다는 것입니다. 단점은 Play 스토어 외부에서 APK를 배포하는 것이 더 어려워진다는 것입니다. 빠른 시작 가이드 에 따라 버전 코드를 자동으로 해결 하도록 플러그인에 지시 하여 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 {
    ...
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.