简体   繁体   中英

Use different VersionCode for Debug/Release android gradle build

I'd like to apply different VersionCode to make apk file. For debug only fix it to 1 , and for release whatever number specified in defaultConfig.

Below code gives mypackage-release-1.apk file as assembleRelease artifact, which is not expected. I expected mypackage-release-10111.apk for that.

why the line debug { defaultConfig.versionCode=1 } affects assembleRelease artifact?

defaultConfig {
    versionCode 10111
    versionName '2.5.4'
    minSdkVersion 10
    targetSdkVersion 21
}
signingConfigs {
    debug {
        project.ext.loadSign = false
        defaultConfig.versionCode = 1 // Why this value applied to assembleRelease?
    }
    release {
        project.ext.loadSign = true
        applicationVariants.all { variant ->
            variant.outputs.each { output ->
                def file = output.outputFile
                output.outputFile = new File(file.parent, file.name.replace(".apk", "-" + defaultConfig.versionCode + ".apk"))
            }
        }
    }
}
buildTypes {
    debug {
        signingConfig signingConfigs.debug
    }
    release {
        signingConfig signingConfigs.release
    }
}

Me too, but I think defaultConfig.versionCode was set when build.gradle be compiling. It's global static variable, and assigned at compiletime, not runtime.

I think we can intercept gradle task execution, and modify defaultConfig.versionCode at runtime.


After goooooooogle, I found this one works for me: https://gist.github.com/keyboardsurfer/a6a5bcf2b62f9aa41ae2

Late on the party...

The entire gradle file evaluated before any task execution, so you are basically changing the default versionCode while declaring debug configs. There is no direct way to reset versionCode from buildType , but the link on the other answer do the trick by declaring a task on build variants.

android {
    ...
    defaultConfig {
         ...
    }
    buildTypes {
         ...
    }
    applicationVariants.all { variant ->
        def flavor = variant.mergedFlavor
        def versionCode = flavor.versionCode
        if (variant.buildType.isDebuggable()) {
            versionCode += 1
        }
        flavor.versionCode = versionCode
    }
}

Here's an updated version:

android {
  defaultConfig { ... }

  applicationVariants.all { variant ->
    if (variant.name == 'debug') {
      variant.outputs.each { output ->
        output.versionCodeOverride = 1
      }
    }
  }
}

To use with Flavors:

applicationVariants.all { variant ->
    def flavor = variant.mergedFlavor
    def name = flavor.getVersionName()
    def code = flavor.getVersionCode()

    if (variant.buildType.isDebuggable()) {
        name += '-d'
        code = 1
    }

    variant.outputs.each { output ->
        output.versionNameOverride = name
        output.versionCodeOverride = code
    }
}

The easiest solution is moving versionCode and versionName variables from defaultConfig to debug and release respectively.

android {
    ...
    defaultConfig {
         // without versionCode and versionName
         ...
    }
    buildTypes {
        debug {
            defaultConfig.versionCode X
            defaultConfig.versionName 'X.Y.Z'
        }
        release {
            defaultConfig.versionCode A
            defaultConfig.versionName 'A.B.C'
        }
    }
    ...
}
applicationVariants.all { variant ->
    variant.outputs.each { output ->
        if (variant.buildType.isDebuggable()) {
            output.versionCodeOverride = 26
            output.versionNameOverride = "2.2.6"
        }
    }
}

put it in android{}

So recently I had to deal with the same scenario and all the examples I could find use the applicationVariants property which is ill-documented imo.

So after some digging through the source code a bit, I realized that in the end versionCode and versionName properties from ProductFlavor get merged into the AndroidManifest which got me thinking: couldn't we just inject them by ourselves, cause we have manifestPlaceholders property on ProductFlavor AND on BuildType DSL objects, so I came up with this -- don't hesitate to give feedback and tell me why it's wrong

In build.gradle(app)

android {
    ...
    buildTypes {
        debug {
            manifestPlaceholder = [versionCode: X, versionName: "X.Y.Z"]
        }
        release {
            manifestPlaceholder = [versionCode: A, versionName: "A.B.C"]
        }
    }
    ...
}

In AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="..."
    android:versionCode="${versionCode}"
    android:versionName="${versionName}">
    ...
</manifest>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM