Android Studio 4.1, Library Modules, and VERSION_CODE
Android Studio 4.1 — or, more accurately, version 4.1.0
of the Android Gradle Plugin —
has a breaking change: it no longer adds VERSION_CODE
(and, sometimes, VERSION_NAME
),
to BuildConfig
.
This was originally reported back in June, with Canary 4, but despite being a P1 ticket, it did not get resolved before AS 4.1 shipped. I found out about it from Stack Overflow. And, since it was mentioned in the release notes, this might not change.
If you create a scrap AS 4.1 project, your app
module will have typical
versionCode
and versionName
properties:
defaultConfig {
applicationId "com.commonsware.android.myapplication"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
That module uses the com.android.application
plugin, and it generates a
BuildConfig
that contains VERSION_CODE
and VERSION_NAME
:
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "com.commonsware.android.myapplication";
public static final String BUILD_TYPE = "debug";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "1.0";
}
If you then add a library module to the same project, it too will come
with the same versionCode
and versionName
lines… but they do not get
reflected in the module’s BuildConfig
:
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String LIBRARY_PACKAGE_NAME = "com.commonsware.android.mylibrary";
public static final String BUILD_TYPE = "debug";
}
I am somewhat surprised that the ticket was not closed as “working as intended”, as this change was intentional
this was done on purpose as having a version for libraries (present in the manifest file or in code) does not make sense for libraries in Android. Only applications have an android version.
UPDATE: A few hours after I posted this, it was indeed closed as “intended behavior”. Somebody who I suspect is Xavier Ducrohet posted an extended explanation of how all this came about.
And the release notes
suggest that versionCode
and versionName
will be removed from the Gradle DSL
in the future.
What worked for me was to declare them manually, based on this issue comment:
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
buildConfigField 'int', 'VERSION_CODE', "1"
buildConfigField 'String', 'VERSION_NAME', "\"1.0\""
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}
In my case, I just hard-coded the values, but you could arrange to pull them from some common location.
Note that there may be varying behavior here. In the Stack Overflow question, SO user Void reported two differences from what I am seeing:
-
VERSION_NAME
was getting generated, but notVERSION_CODE
-
Using
buildConfigField
forVERSION_CODE
would not work, but using a unique name would
In light testing, I could not reproduce those findings, but be prepared for some variation in symptoms.
The safest thing to do, if you elect to go the buildConfigField
route, is to
not use VERSION_CODE
and VERSION_NAME
, but instead use your own unique
names, as Void did. Basically, consider VERSION_CODE
and VERSION_NAME
to be part of a Google-managed
namespace, and assume that Google might mess with them. If you use your own names,
with luck, they will be untouched by future changes to the Android Gradle Plugin.
UPDATE: In the aforementioned extended explanation, Google echoed this recommendation: use your own custom fields.