One recommended practice with Android app development is upgrading app version code and name in gradle file for every code change. We have been doing this manually all this time, there is an additional overhead (time) of gradle syncing for every change that happens in build gradle files. This trick automates that process using simple gradle methods and logic. Even if you forget to upgrade the version, this trick will take care of it.
It is not mandatory but I recommend going through the basics of product flavours in Android. We will be upgrading versions of default config and all the flavours. You can Google it up or check out this link.
Android apps version code and name are defined in the module’s build.gradle file. Same goes for all the product flavours. All are defined inside Android block. Here is a sample:
android {
...
defaultConfig {
applicationId "app.package.default"
versionCode 1
versionName '1.0'
...
}
productFlavors {
free {
applicationId "app.package.free"
versionCode 101
versionName '1.101.1'
...
}
pro {
applicationId "app.package.pro"
versionCode 301
versionName '1.301.3'
...
}
freemium {
applicationId "app.package.freemium"
versionCode 501
versionName '1.501.5'
...
}
}
...
}
FYI, version code and name can be overridden in flavours as shown above. In fact, any property of default config can be overriden in flavours. Both use the same DSL object for configuration.
As you can see, we have to manually write “1.0” and 1 in version name and code respectively. And when we change that, we need to wait for gradle sync to finish. Now let’s see how to automate this process.
We are going to create a method that calculates an upgraded number and we will use this method in version name and code. Like this:
versionCode getCustomNumber() versionName "1.0." + getAnotherOrSameCustomNumber()
This method in defined in project level build.gradle file. You can use any logic in getCustomNumber() and getAnotherOrSameCustomNumber() that returns an upgraded number every time it is called. When you define this, make sure it returns an upgraded number as a lower version code will not upgrade your app. A simple logic based on timestamp is defined below.
def getCustomNumber() {
def date = new Date()
def formattedDate = date.format('yyMMddHHmm')
def code = formattedDate.toInteger()
return code
}
allprojects {
version = '1.0.' + getCustomVersionCode()
repositories {
jcenter()
mavenCentral()
}
}
Defining the base version in allProjects block is important, or else you will see a null version code and name and may result in build failure. Here’s how we can use the above defined method in app level’s build.gradle file (including product flavours).
android {
...
defaultConfig {
applicationId "app.package.default"
versionCode getCustomVersionCode()
versionName '1.0.' + getCustomVersionCode()
...
}
productFlavors {
free {
applicationId "app.package.free"
versionName '1.101.' + getCustomVersionCode()
...
}
pro {
applicationId "app.package.pro"
versionName '1.301.' + getCustomVersionCode()
...
}
freemium {
applicationId "app.package.freemium"
versionName '1.501.' + getCustomVersionCode()
...
}
...
}
}
You can even use the revision of the source control you use in your project, just need to find the right gradle plugin your source control.
If you remove the base version in allProject block of project level build.gradle file, you will see a “null” in version code in generated manifest. And your app may or may not run. So please avoid it.
Let me know what you think.
-Kaushal D (@drulabs twitter/github)
drulabs@gmail.com