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

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



답변

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

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

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


답변

아래에서 볼 수있는 이전 답변의 현대화가 있습니다. 이것은 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으로 시작합니다. 🙂


답변

CommonsWare의 우수한 답변의 약간 강화 된 버전이 존재하지 않는 경우 버전 파일을 생성합니다.

def Properties versionProps = new Properties()
def versionPropsFile = file('version.properties')
if(versionPropsFile.exists())
    versionProps.load(new FileInputStream(versionPropsFile))
def code = (versionProps['VERSION_CODE'] ?: "0").toInteger() + 1
versionProps['VERSION_CODE'] = code.toString()
versionProps.store(versionPropsFile.newWriter(), null)

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


답변

이 작업을 수행하기위한 몇 가지 옵션을 살펴본 결과, versionCode를 자동으로 증가시켜 수정 관리 시스템에 체크인하는 대신 versionCode에 현재 시간을 사용하는 것이 더 간단하다고 결정했습니다.

에 다음을 추가하십시오 build.gradle.

/**
 * Use the number of seconds/10 since Jan 1 2016 as the versionCode.
 * This lets us upload a new build at most every 10 seconds for the
 * next 680 years.
 */
def vcode = (int)(((new Date().getTime()/1000) - 1451606400) / 10)

android {
    defaultConfig {
        ...
        versionCode vcode
    }
}

그러나 2696 년 이후에 빌드를 업로드하려는 경우 다른 솔루션을 사용할 수 있습니다.


답변

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

  1. versionCode모든 컴퓨터 ( Continuous Integration및 / 또는 Continuous Deployment서버 포함)에서 자동으로 일관되게 생성됩니다 .
  2. 이 앱 versionCode은 GooglePlay에 제출할 수 있습니다.
  3. 저장소 외부의 파일에 의존하지 않습니다.
  4. 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.


답변

최근에 나는 versionCodeversionName을 자동으로 생성하는 Android 용 gradle 플러그인을 작업하고있었습니다 . 많은 사용자 정의가 있습니다. 여기에서 자세한 정보를 찾을 수 있습니다
https://github.com/moallemi/gradle-advanced-build-version


답변

또 다른 옵션은 증가를 위해 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’)이 정수 용량을 초과합니다.