์นดํ…Œ๊ณ ๋ฆฌ ๋ณด๊ด€๋ฌผ: Android

Android

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.4 ๋ฐ Android 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.


๋‹ต๋ณ€

์ตœ๊ทผ์— ๋‚˜๋Š” versionCode ์™€ versionName์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” 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โ€™)์ด ์ •์ˆ˜ ์šฉ๋Ÿ‰์„ ์ดˆ๊ณผํ•ฉ๋‹ˆ๋‹ค.


์ด ๊ธ€์€ Android ์นดํ…Œ๊ณ ๋ฆฌ๋กœ ๋ถ„๋ฅ˜๋˜์—ˆ๊ณ  ๋‹˜์— ์˜ํ•ด ์— ์ž‘์„ฑ๋์Šต๋‹ˆ๋‹ค.