Autoincrement VersionCode พร้อมคุณสมบัติพิเศษของ gradle


121

ฉันกำลังสร้างแอป Android ด้วย Gradle จนถึงตอนนี้ฉันใช้ไฟล์ 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.

One-Liner พร้อมปลั๊กอิน Gradle ที่คุณเลือก: stackoverflow.com/a/61718437/4548500
SUPERCILEX

คำตอบ:


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: ถ้าคุณหมายถึง "เพิ่มจำนวนในรุ่นที่วางจำหน่ายเท่านั้น" นั่นน่าจะเป็นไปได้แม้ว่าฉันจะไม่รู้รายละเอียดก็ตาม โดยส่วนตัวแล้วเนื่องจากมีรหัสเวอร์ชันประมาณ 2 พันล้านรหัสฉันจึงคิดว่าจะไม่หมด :-)
CommonsWare

3
@Piotr คุณจะสร้างงานที่เพิ่มรหัสเวอร์ชันแยกจากกันจากนั้นทำสิ่งที่เหมือนassembleRelease.finalizedBy incrementVersionหรือคล้ายกัน ฉันจะโพสต์รหัสของฉันเมื่อจัดการเรียบร้อยแล้ว
ริสเจนคินส์

การใช้งานที่กำหนดเองคุณสามารถทำสิ่งที่ต้องการ./gradlew incrementVersionCode buildได้ งานที่เรียกตามลำดับในลักษณะนี้จะหยุดลงทันทีที่งานใด ๆ ล้มเหลว
Dori

3
เนื่องจาก @ chris.jenkins ยังคงหลอกรหัสของเขาอยู่: p นี่คือสิ่งที่กล่าวมาข้างต้นในรูปแบบงานและวิธีการgist.github.com/doridori/544c24509be236c11fd5ซึ่งสามารถใช้ใน Android DSL ด้วยversionCode getIncrementingVersionCode()
Dori

83

นี่คือความทันสมัยของคำตอบก่อนหน้านี้ซึ่งสามารถดูได้ด้านล่าง หนึ่งนี้จะทำงานด้วยGradle 4.4และAndroid 3.1.1

สิ่งที่สคริปต์นี้ทำ:

  • สร้างไฟล์version.propertiesหากไม่มีอยู่ (โหวตคำตอบของ Paul Cantrell ด้านล่างซึ่งเป็นที่ที่ฉันได้แนวคิดมาหากคุณชอบคำตอบนี้)
  • สำหรับแต่ละรุ่นแก้ไขข้อบกพร่องหรือเมื่อใดก็ตามที่คุณกดปุ่มเรียกใช้ใน Android Studio จำนวน VERSION_BUILD จะเพิ่มขึ้น
  • ทุกครั้งที่คุณรวบรวมรุ่น Android versionCodeสำหรับ play store จะเพิ่มขึ้นและจำนวนแพตช์ของคุณจะเพิ่มขึ้น
  • โบนัส: หลังจากสร้างเสร็จแล้วให้คัดลอก apk ของคุณprojectDir/apkเพื่อให้สามารถเข้าถึงได้มากขึ้น

สคริปต์นี้จะสร้างหมายเลขรุ่นซึ่งมีลักษณะเหมือนv1.3.4 (123)และสร้างไฟล์ APK เช่นAppName-v1.3.4.apk

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

เวอร์ชันหลัก:ต้องเปลี่ยนแปลงด้วยตนเองเพื่อการเปลี่ยนแปลงที่ใหญ่ขึ้น

รุ่นรอง:ต้องเปลี่ยนด้วยตนเองสำหรับการเปลี่ยนแปลงที่ใหญ่น้อยกว่าเล็กน้อย

เวอร์ชันแพตช์:เพิ่มขึ้นเมื่อทำงานgradle assembleRelease

สร้างเวอร์ชัน:เพิ่มทุก

หมายเลขเวอร์ชัน:เหมือนกับเวอร์ชันแพทช์ซึ่งเป็นรหัสเวอร์ชันที่ Play Store ต้องเพิ่มขึ้นสำหรับการอัปโหลด apk ใหม่แต่ละครั้ง

เพียงแค่เปลี่ยนเนื้อหาในความคิดเห็นที่มีข้อความ 1 - 3 ด้านล่างแล้วสคริปต์ก็ควรดำเนินการที่เหลือ :)

android {
    compileSdkVersion 27
    buildToolsVersion '27.0.3'

    def versionPropsFile = file('version.properties')
    def value = 0
    Properties versionProps = new Properties()
    if (!versionPropsFile.exists()) {
        versionProps['VERSION_PATCH'] = "0"
        versionProps['VERSION_NUMBER'] = "0"
        versionProps['VERSION_BUILD'] = "-1" // I set it to minus one so the first build is 0 which isn't super important. 
        versionProps.store(versionPropsFile.newWriter(), null)
    }

    def runTasks = gradle.startParameter.taskNames
    if ('assembleRelease' in runTasks) {
        value = 1
    }

    def mVersionName = ""
    def mFileName = ""

    if (versionPropsFile.canRead()) {
        versionProps.load(new FileInputStream(versionPropsFile))

        versionProps['VERSION_PATCH'] = (versionProps['VERSION_PATCH'].toInteger() + value).toString()
        versionProps['VERSION_NUMBER'] = (versionProps['VERSION_NUMBER'].toInteger() + value).toString()
        versionProps['VERSION_BUILD'] = (versionProps['VERSION_BUILD'].toInteger() + 1).toString()

        versionProps.store(versionPropsFile.newWriter(), null)

        // 1: change major and minor version here
        mVersionName = "v1.0.${versionProps['VERSION_PATCH']}"
        // 2: change AppName for your app name
        mFileName = "AppName-${mVersionName}.apk"

        defaultConfig {
            minSdkVersion 21
            targetSdkVersion 27
            applicationId "com.example.appname" // 3: change to your package name
            versionCode versionProps['VERSION_NUMBER'].toInteger()
            versionName "${mVersionName} Build: ${versionProps['VERSION_BUILD']}"
        }

    } else {
        throw new FileNotFoundException("Could not read version.properties!")
    }

    if ('assembleRelease' in runTasks) {
        applicationVariants.all { variant ->
            variant.outputs.all { output ->
                if (output.outputFile != null && output.outputFile.name.endsWith('.apk')) {
                    outputFileName = mFileName
                }
            }
        }
    }

    task copyApkFiles(type: Copy){
        from 'build/outputs/apk/release'
        into '../apk'
        include mFileName
    }

    afterEvaluate {
        assembleRelease.doLast {
            tasks.copyApkFiles.execute()
        }
    }

    signingConfigs {
        ...
    }

    buildTypes {
        ...
    }
}

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

คำตอบเริ่มต้น:

ฉันต้องการให้ 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!")
    }

    ...
}

...

Patch และ versionCode จะเพิ่มขึ้นหากคุณประกอบโปรเจ็กต์ของคุณผ่านเทอร์มินัลด้วย'Assemble' , 'AssembleRelease'หรือ'aR'ซึ่งจะสร้างโฟลเดอร์ใหม่ในรูทโปรเจ็กต์ของคุณที่เรียกว่า apk / RELEASE ดังนั้นคุณจึงไม่ต้องมองผ่าน build / outputs / เพิ่มเติม / เพิ่มเติม / อื่น ๆ เพื่อค้นหา apk ของคุณ

คุณสมบัติเวอร์ชันของคุณจะต้องมีลักษณะดังนี้:

VERSION_NUMBER=1
VERSION_BUILD=645
VERSION_PATCH=1

เห็นได้ชัดว่าเริ่มต้นด้วย 0 :)


2
"variant.outputs.each {output ->" ที่สองสามารถลบออกได้โดยใช้ "}" ที่เกี่ยวข้อง
redocoder

สิ่งนี้ทำให้งานสร้างทั้งหมดของฉันอยู่ในรหัสเนทีฟ x86_64 เท่านั้น
Chisko

@Chisko ฉันสงสัยว่าส่วนนี้ของ gradle code เป็นสาเหตุ ถามคำถามใหม่และแบ่งปันรหัสการเรียนรู้ของคุณและเราจะพยายามหาว่ามีอะไรผิดพลาด :)
just_user

1
ตอนนี้ฉันสามารถยืนยันได้ว่านี่ไม่ใช่สาเหตุที่แท้จริง ขอโทษด้วย.
Chisko

1
@AlexanderGavriliuk เป็นรหัสเวอร์ชันที่ Play Store ใช้ซึ่งต้องเพิ่มขึ้นอย่างต่อเนื่องสำหรับทุกการอัปโหลด หมายเลขแพตช์อาจถูกรีเซ็ตหากคุณเพิ่มเวอร์ชันหลักหรือเวอร์ชันรอง หมายเลขเวอร์ชันไม่ควรรีเซ็ตไม่ได้หากคุณอัปโหลดแอปไปยัง play store ด้วยชื่อแพ็กเกจเดียวกัน
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

ต้องตรวจสอบ?:ความหมายใน 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' จากที่ไหน หรือ '1510351294' จาก #Entreco ฉันพยายามคำนวณโดยเปล่าประโยชน์!
Joseph Wambura

18

อีกวิธีหนึ่งในการรับversionCodeอัตโนมัติคือการตั้งค่าversionCodeจำนวนคอมมิตในgitสาขาที่เช็คเอาต์ บรรลุวัตถุประสงค์ดังต่อไปนี้:

  1. versionCodeถูกสร้างขึ้นโดยอัตโนมัติและสม่ำเสมอบนเครื่องใด ๆ (รวมถึงเครื่องContinuous Integrationและ / หรือContinuous Deploymentเซิร์ฟเวอร์)
  2. แอพนี้versionCodeสามารถส่งไปยัง GooglePlay ได้
  3. ไม่ต้องพึ่งพาไฟล์ใด ๆ ที่อยู่นอก repo
  4. ไม่ผลักดันอะไรไปที่ repo
  5. สามารถลบล้างได้ด้วยตนเองหากจำเป็น

การใช้ไลบรารี gradle-gitเพื่อบรรลุวัตถุประสงค์ข้างต้น เพิ่มโค้ดด้านล่างลงbuild.gradleใน/appไดเร็กทอรีไฟล์ของคุณ:

import org.ajoberstar.grgit.Grgit

repositories {
    mavenCentral()
}

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'org.ajoberstar:grgit:1.5.0'
    }
}

android {
/*
    if you need a build with a custom version, just add it here, but don't commit to repo,
    unless you'd like to disable versionCode to be the number of commits in the current branch.

    ex. project.ext.set("versionCodeManualOverride", 123)
*/
    project.ext.set("versionCodeManualOverride", null)

    defaultConfig {
        versionCode getCustomVersionCode()
    }
}

def getCustomVersionCode() {

    if (project.versionCodeManualOverride != null) {
        return project.versionCodeManualOverride
    }

    // current dir is <your proj>/app, so it's likely that all your git repo files are in the dir
    // above.
    ext.repo = Grgit.open(project.file('..'))

    // should result in the same value as running
    // git rev-list <checked out branch name> | wc -l
    def numOfCommits = ext.repo.log().size()
    return numOfCommits
}

หมายเหตุ: เพื่อให้วิธีนี้ได้ผลดีที่สุดคือปรับใช้กับ Google Play Store จากสาขาเดียวกันเท่านั้น (เช่นmaster)


ในขณะที่หลักการแก้ปัญหาที่หรูหราฉันสามารถจินตนาการได้ว่าสิ่งนี้จะทำให้เวลาในการสร้างช้าลงอย่างมากขึ้นอยู่กับสิ่งที่เกิดขึ้นใน 2 บรรทัดคอมไพล์ มีประสบการณ์อะไรบ้าง?
หวังว่าจะเป็นประโยชน์ใน

1
ฉันไม่สังเกตเห็นการปรับปรุงประสิทธิภาพใด ๆ หากปิดใช้ขั้นตอนนี้ ใช้วิธีการในพื้นที่และในเครื่องสร้างของเรามานานกว่าหนึ่งปีแล้วและประสิทธิภาพก็ไม่ได้เป็นปัญหา แต่อย่างใด หากคุณสังเกตเห็นปัญหาด้านประสิทธิภาพโปรดแจ้งให้เราทราบ!
C0D3LIC1OU5

แม้ว่าโซลูชันของคุณจะสวยงาม แต่ก็อาจทำให้เกิดความประหลาดใจที่ไม่คาดคิดได้ เป็นสิ่งสำคัญที่ versionCodes จะมีขนาดใหญ่กว่ารุ่นก่อนหน้าเสมอ จะเกิดอะไรขึ้นถ้าคุณมีสาขาหนึ่งที่มี 50 คอมมิทแล้วคุณสร้างอีกสาขาที่ใหม่กว่า แต่มีคอมมิทเพียง 40 คอมมิทบางทีอาจเกิดจากการบีบคอมมิทจำนวนหนึ่งจากคุณสมบัติที่ผสาน ฉันเห็นเหตุผลมากมายที่ประวัติการคอมมิตของคุณจะไม่ใช่กระแสเชิงเส้นของการคอมมิตที่เพิ่มขึ้นเสมอไป
JHH

@JHH ผลลัพธ์เหล่านั้นไม่ได้คาดไม่ถึง ดังที่ฉันได้กล่าวไว้ในบันทึกวิธีนี้จะได้ผลดีที่สุดเมื่อปรับใช้จากสาขาเดียวกัน
C0D3LIC1OU5

13

เมื่อเร็ว ๆ นี้ฉันกำลังทำงานกับปลั๊กอิน gradle สำหรับ Android ที่สร้างversionCodeและversionNameโดยอัตโนมัติ มีการปรับแต่งมากมาย คุณสามารถค้นหาข้อมูลเพิ่มเติมได้ที่นี่ https://github.com/moallemi/gradle-advanced-build-version


นี่คือปลั๊กอินที่ยอดเยี่ยม! ขอบคุณสำหรับการแบ่งปัน🙂
Cory Robinson

10

อีกทางเลือกหนึ่งสำหรับการเพิ่มversionCodeและการversionNameใช้การประทับเวลา

defaultConfig {
   versionName "${getVersionNameTimestamp()}"
   versionCode getVersionCodeTimestamp()
}


def getVersionNameTimestamp() {
    return new Date().format('yy.MM.ddHHmm')
}

def getVersionCodeTimestamp() {
    def date = new Date()
    def formattedDate = date.format('yyMMddHHmm')
    def code = formattedDate.toInteger()
    println sprintf("VersionCode: %d", code)
    return code
}

ตั้งแต่วันที่ 1 มกราคม 2022 formattedDate = date.format ('yyMMddHHmm') เกินความจุของจำนวนเต็ม


1
บุคคลนั้นต้องการหมายเลข
บิวด์ที่

6
@peter_pilgrim Caro เป็น OP
Matthew อ่าน

ฉันคิดว่านี่เป็นวิธีแก้ปัญหาที่ยอดเยี่ยมไม่ต้องพึ่งพาไฟล์ที่อาจหายไปหรือไม่หรือจะปรากฏในคอมไพล์ตลอดเวลา นอกจากนี้ยังช่วยให้คุณระบุแต่ละรุ่นโดยไม่ซ้ำกันเป็นเวลาอย่างน้อย 22 ปีข้างหน้า
หวังว่าจะเป็นประโยชน์

อ้าง developer.android.com:"Warning: มูลค่าที่ยิ่งใหญ่ที่สุด Google Play ช่วยให้การ versionCode เป็น 2100000000. "ดังนั้นการตัดเป็นจริง 2021
ths

แก้ไขขีด จำกัด int: ละเว้นนาทีและใช้รูปแบบวันที่ 'yyMMddHH' รหัสเวอร์ชันจะมีอย่างน้อยชั่วโมง
Pointer Null

10

ในการเพิ่ม versionCode เฉพาะในเวอร์ชันรีลีสให้ทำ:

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    def versionPropsFile = file('version.properties')
    def code = 1;
    if (versionPropsFile.canRead()) {
        def Properties versionProps = new Properties()

        versionProps.load(new FileInputStream(versionPropsFile))
        List<String> runTasks = gradle.startParameter.getTaskNames();
        def value = 0
        for (String item : runTasks)
        if ( item.contains("assembleRelease")) {
            value = 1;
        }
        code = Integer.parseInt(versionProps['VERSION_CODE']).intValue() + value
        versionProps['VERSION_CODE']=code.toString()
        versionProps.store(versionPropsFile.newWriter(), null)
    }
    else {
        throw new GradleException("Could not read version.properties!")
    }

    defaultConfig {
        applicationId "com.pack"
        minSdkVersion 14
        targetSdkVersion 21
        versionName "1.0."+ code
        versionCode code
    }

คาดว่าc://YourProject/app/version.propertiesไฟล์ที่มีอยู่ซึ่งคุณจะสร้างขึ้นด้วยมือก่อนที่จะสร้างไฟล์แรกVERSION_CODE=8

ไฟล์ version.properties:

VERSION_CODE=8


แทนที่จะใส่ไว้ในงานและทำให้ createReleaseBuildConfig ขึ้นอยู่กับงานนั้น
ลากอส

versionName "1.0." + getSvnRevision () ทำให้เกิดข้อผิดพลาด getSvnRevision () วิธีการอ้างอิงถึงอยู่ที่ไหน แน่ใจหรือว่าไม่ควรเป็น versionName "1.0." + code (ชื่อเวอร์ชันจะเพิ่มขึ้นตามรหัสเวอร์ชันของคุณ)
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

ถ้า (_major == 99) ควรเป็น if (_minor == 99) ??
Anirudh Bagri

2

กำหนดversionNameในAndroidManifest.xml

android:versionName="5.1.5"

android{...}บล็อกภายในbuild.gradleของระดับแอป:

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

android{...}บล็อกภายนอกในbuild.gradleระดับแอป:

def getIncrementedVersionName() {
    List<String> runTasks = gradle.startParameter.getTaskNames();

    //find version name in manifest
    def manifestFile = file('src/main/AndroidManifest.xml')
    def matcher = Pattern.compile('versionName=\"(\\d+)\\.(\\d+)\\.(\\d+)\"').matcher(manifestFile.getText())
    matcher.find()

    //extract versionName parts
    def firstPart = Integer.parseInt(matcher.group(1))
    def secondPart = Integer.parseInt(matcher.group(2))
    def thirdPart = Integer.parseInt(matcher.group(3))

    //check is runTask release or not
    // if release - increment version
    for (String item : runTasks) {
        if (item.contains("assemble") && item.contains("Release")) {
            thirdPart++
            if (thirdPart == 10) {
                thirdPart = 0;
                secondPart++
                if (secondPart == 10) {
                    secondPart = 0;
                    firstPart++
                }
            }
        }
    }

    def versionName = firstPart + "." + secondPart + "." + thirdPart

    // update manifest
    def manifestContent = matcher.replaceAll('versionName=\"' + versionName + '\"')
    manifestFile.write(manifestContent)

    println "incrementVersionName = " + versionName

    return versionName
}

หลังจากสร้าง APK ที่ร้องเพลงแล้ว:

android:versionName="5.1.6"

หมายเหตุ: หากversionNameของคุณแตกต่างจาก my คุณต้องเปลี่ยนregexและแยกตรรกะส่วนต่างๆ


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 ใหม่และแทนที่สตริง versionCode ในไฟล์build.gradleด้วยค่าตัวนับที่เพิ่มขึ้นนี้

apply plugin: 'com.android.application'

android {
compileSdkVersion 25
buildToolsVersion '25.0.2'

def versionPropsFile = file('version.properties')
def versionBuild

/*Setting default value for versionBuild which is the last incremented value stored in the file */
if (versionPropsFile.canRead()) {
    def Properties versionProps = new Properties()
    versionProps.load(new FileInputStream(versionPropsFile))
    versionBuild = versionProps['VERSION_BUILD'].toInteger()
} else {
    throw new FileNotFoundException("Could not read version.properties!")
}


/*Wrapping inside a method avoids auto incrementing on every gradle task run. Now it runs only when we build apk*/
ext.autoIncrementBuildNumber = {

    if (versionPropsFile.canRead()) {
        def Properties versionProps = new Properties()
        versionProps.load(new FileInputStream(versionPropsFile))
        versionBuild = versionProps['VERSION_BUILD'].toInteger() + 1
        versionProps['VERSION_BUILD'] = versionBuild.toString()
        versionProps.store(versionPropsFile.nminSdkVersion 14
        targetSdkVersion 21
        versionCode 1ewWriter(), null)
    } else {
        throw new FileNotFoundException("Could not read version.properties!")
    }
}


defaultConfig {
    minSdkVersion 16
    targetSdkVersion 21
    versionCode 1
    versionName "1.0.0." + versionBuild
}

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

// Hook to check if the release/debug task is among the tasks to be executed.
//Let's make use of it
gradle.taskGraph.whenReady {taskGraph ->
    if (taskGraph.hasTask(assembleDebug)) {  /* when run debug task */
        autoIncrementBuildNumber()
    } else if (taskGraph.hasTask(assembleRelease)) { /* when run release task */
        autoIncrementBuildNumber()
    }
  }
}

dependencies {
  compile fileTree(dir: 'libs', include: ['*.jar'])
  compile 'com.android.support:appcompat-v7:25.3.1'
}

วางสคริปต์ด้านบนไว้ในไฟล์ build.gradle ของโมดูลหลัก

เว็บไซต์อ้างอิง: http://devdeeds.com/auto-increment-build-number-using-gradle-in-android/

ขอขอบคุณและขอแสดงความนับถือ!


0

รหัสความคิดเห็นแรกจะเพิ่มจำนวนในขณะที่ "สร้างโครงการใหม่" และบันทึกค่าในไฟล์ "คุณสมบัติเวอร์ชัน"

รหัสความคิดเห็นที่สองจะสร้างชื่อเวอร์ชันใหม่ของไฟล์ APK ในขณะที่ "สร้าง APK"

android {
    compileSdkVersion 28
    buildToolsVersion "29.0.0"
    //==========================START==================================
    def Properties versionProps = new Properties()
    def versionPropsFile = file('version.properties')
    if(versionPropsFile.exists())
        versionProps.load(new FileInputStream(versionPropsFile))
    def code = (versionProps['VERSION_CODE'] ?: "0").toInteger() + 1
    versionProps['VERSION_CODE'] = code.toString()
    versionProps.store(versionPropsFile.newWriter(), null)
    //===========================END===================================
    defaultConfig {
        applicationId "com.example.myapp"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "0.19"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            //=======================================START===============================================
            android.applicationVariants.all { variant ->
                variant.outputs.all {
                    def appName = "MyAppSampleName"
                    outputFileName = appName+"_v${variant.versionName}.${versionProps['VERSION_CODE']}.apk"
                }
            }
            //=======================================END===============================================
        }
    }
}

โปรดเพิ่มข้อความที่แสดงสิ่งที่คุณเปลี่ยนแปลง และทำไม
Matthew Kerian

0

ในเวอร์ชัน Gradle 5.1.1 บน mac ive เปลี่ยนวิธีการดึงชื่องานแม้ว่าฉันจะไม่พยายามรับรส / ประเภทการสร้างจากบิลด์ แต่ขี้เกียจแยกชื่องาน:

def versionPropsFile = file('version.properties')
if (versionPropsFile.canRead()) {
    def Properties versionProps = new Properties()

    versionProps.load(new FileInputStream(versionPropsFile))

    def value = 0

    def runTasks = gradle.getStartParameter().getTaskRequests().toString()

    if (runTasks.contains('assemble') || runTasks.contains('assembleRelease') || runTasks.contains('aR')) {
        value = 1
    }

    def versionMajor = 1
    def versionMinor = 0
    def versionPatch = versionProps['VERSION_PATCH'].toInteger() + value
    def versionBuild = versionProps['VERSION_BUILD'].toInteger() + 1
    def versionNumber = versionProps['VERSION_NUMBER'].toInteger() + value

    versionProps['VERSION_PATCH'] = versionPatch.toString()
    versionProps['VERSION_BUILD'] = versionBuild.toString()
    versionProps['VERSION_NUMBER'] = versionNumber.toString()

    versionProps.store(versionPropsFile.newWriter(), null)

    defaultConfig {
        applicationId "de.evomotion.ms10"
        minSdkVersion 21
        targetSdkVersion 28
        versionCode versionNumber
        versionName "${versionMajor}.${versionMinor}.${versionPatch} (${versionBuild})"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        signingConfig signingConfigs.debug
    }

} else {
    throw new GradleException("Could not read version.properties!")
}

รหัสมาจาก @just_user อัน นี้


0

มีสองวิธีที่ฉันชอบมาก อย่างแรกขึ้นอยู่กับ Play Store และอีกอันขึ้นอยู่กับ Git

เมื่อใช้ Play Store คุณสามารถเพิ่มรหัสเวอร์ชันได้โดยดูจากการอัปโหลดสูงสุดที่มีรหัสรุ่น ข้อดีของโซลูชันนี้คือการอัปโหลด APK จะไม่มีวันล้มเหลวเนื่องจากรหัสเวอร์ชันของคุณจะสูงกว่าที่อยู่ใน Play Store เสมอ ข้อเสียคือการแจกจ่าย APK ของคุณนอก Play Store จะยากขึ้น คุณสามารถตั้งค่านี้โดยใช้ Gradle Play Publisher โดยทำตามคำแนะนำการเริ่มต้นใช้งานฉบับย่อและบอกให้ปลั๊กอินแก้ไขรหัสเวอร์ชันโดยอัตโนมัติ :

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

android {
    ...
}

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

เมื่อใช้ Git คุณสามารถเพิ่มโค้ดเวอร์ชันตามจำนวนคอมมิตและแท็กที่เก็บของคุณได้ ข้อดีคือผลลัพธ์ของคุณสามารถทำซ้ำได้และไม่ได้ขึ้นอยู่กับสิ่งใดนอก repo ของคุณ ข้อเสียคือคุณต้องทำการคอมมิตหรือแท็กใหม่เพื่อชนโค้ดเวอร์ชันของคุณ คุณสามารถตั้งค่าได้โดยการเพิ่มปลั๊กอิน 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.