BuildConfig.VERSION_CODE is missing after update to 'com.android.tools.build:gradle:4.1.0'

Solution 1:

add buildConfigField to buildTypes in module build.gradle file

buildConfigField("long", "VERSION_CODE", "${defaultConfig.versionCode}")        
buildConfigField("String","VERSION_NAME","\"${defaultConfig.versionName}\"")

example,

buildTypes {
    debug{
        buildConfigField("long", "VERSION_CODE", "${defaultConfig.versionCode}")
        buildConfigField("String","VERSION_NAME","\"${defaultConfig.versionName}\"")

        //..
    }
    release {
        buildConfigField("long", "VERSION_CODE", "${defaultConfig.versionCode}")
        buildConfigField("String","VERSION_NAME","\"${defaultConfig.versionName}\"")

        //...
    }
}

the defaultConfig.versionCode and defaultConfig.versionName value is

defaultConfig {
    minSdkVersion 16
    targetSdkVersion 29
    versionCode 1
    versionName "1.0"

    //..
}

in your module build.gradle

you can create field in BuildConfig by writing buildConfigField method in module build.gradle. The method first parameter is create field type, second is field name, third is value.

Android Studio 4.1

Solution 2:

I have a multi modular app and for some reason VERSION_CODE generated field has disappeared from all modules except the root one

That appears to be related to this reported issue. In that case, it was VERSION_NAME that was missing from library modules. See this specific comment for their rationale. Apparently, they fixed VERSION_NAME but did not fix VERSION_CODE. When I test this, I do not get either VERSION_NAME or VERSION_CODE, so I cannot explain how your module gets VERSION_NAME.

You should be able to switch to using buildConfigField to supply your version code:

 buildConfigField "long", "VERSION_CODE", global["versionString"]

Solution 3:

We also have a multi-module setup and we were able to workaround with minimal changes by adding the following lines to every module's build.gradle

buildConfigField 'int', 'VERSION_CODE', "${rootProject.appVersionCode}"
buildConfigField 'String', 'VERSION_NAME', "\"${rootProject.appVersionName}\""

Solution 4:

You can use the other answers here as a workaround, but this answer is just to inform you of the official reply from the people working on the bug. This will not be fixed as it is an intended behaviour.

Here's what the Google engineers say:

Status: Won't Fix (Intended Behavior) Hi all,

Yes, we should have deprecated this first. Since this happened (several months ago), we have put in place better policies for deprecation/removal of properties. This happened kind of late for 4.1 though, and this particular issue fell through the cracks so we did not get a chance to decide whether to revert this change (and we even missed putting this change in the release notes at first). We apologize for this.

Some of the motivation behind this were to reduce/remove the confusion around 2 points:

Users accessing the BuildConfig fields but not setting them in the DSL. This would definitively be broken and not do what one would expect (ie these are static values, and won't magically reflect the version of the app the library is embedded in) The library AndroidManifest.xml file contains the values set in the DSL, but these values are completely ignored by the consuming app(s) during manifest merging (they are also overridden) If you want to keep injecting the values from a common place into all your library project's BuildConfig fields, you could continue to do this manually with your own custom fields. These fields will only exist if you set them via the DSL (therefore preventing problem #1 above), and will not impact the library manifest (problem #2 above).

However, if you have a large setup with many library projects, this pattern will generate a lot of duplicates. It would make more sense to have a single module that generates a similar class, and have all your library projects (or at least the ones that need the info) depend on it.

Solution 5:

Was unable to find a clean solution, so added a workaround:

buildConfigField "int", "VERSION_CODE1", String.valueOf(global["versionString"])