Holiday clean up or cute versioning in android š§¹
TL;DR;
Cool versioning style for android or any project using gradle. Define all versions and dependencies to separate files and use those instead of hardcoding values into project modules. Clean, all in one place and lifesaver whenever dealing with project with multiple modules. Example project šhttps://github.com/marius-m/versioning_love
Preface
So one day I was trying to clean-up our *.gradle
files. As we use multiple modules in our project + patched libraries, we have versions of various dependencies that we need to reuse through out all the project modules. I was not happy about how we were using the versioning and remembered that there was a very cute naming used in one library ā https://github.com/facebook/screenshot-tests-for-android. So Iāve taken the inspiration to clean-up our playground as well and make a post about it, as I thought of it ā it was TOO COOL š¤ not to be shared with the internet. So here we go š.
The code
Iāve split the naming into two parts.
- File
version_generic.gradle
would have most commonly used version numbers throughout the main project and its modules / libraries
ext {
versions = [
minSdk : 19,
testMinSdk : 26,
debugMinSdk: 26,
compileSdk : 28,
targetSdk : 28,
buildTools : "28.0.3",
support: "27.1.0",
androidGradlePlugin: "3.0.1",
kotlin: "1.3.0",
]
}
- File
version.gradle
would have all the library namings and dependencies used. And this is how an exampleversions.gradle
might look like
ext {
apply from: rootProject.file("versions_generic.gradle")
final versionAndroidSupport = versions.support
final versionKotlin = versions.kotlinplugs = [
gradleBuildTools: "com.android.tools.build:gradle:${versions.androidGradlePlugin}",
gradleVersioning: "com.github.ben-manes:gradle-versions-plugin:0.13.0",
kotlin: "org.jetbrains.kotlin:kotlin-gradle-plugin:$versionKotlin",
detekt: "gradle.plugin.io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.0.0.RC9.2",
]coreDeps = [
ui: project(":app-ui"),
components: project(":app-components"),
models: project(":app-models"),
twPrinter: project(":tw-printer"),
kotlin: "org.jetbrains.kotlin:kotlin-stdlib:$versionKotlin",
rxJava: "io.reactivex:rxjava:1.2.0",
rxAndroid: "io.reactivex:rxandroid:1.2.1",
]androidDeps = [
appCompatV7: "com.android.support:appcompat-v7:$versionAndroidSupport",
supportV4: "com.android.support:support-v4:$versionAndroidSupport",
design: "com.android.support:design:$versionAndroidSupport",
cardView: "com.android.support:cardview-v7:$versionAndroidSupport",
multiDex: "com.android.support:multidex:1.0.3",
]unitTestDeps = [
junit: "junit:junit:4.12",
mockito: "org.mockito:mockito-core:2.8.9",
kotlin: "org.jetbrains.kotlin:kotlin-test-junit:$versionKotlin",
kotlinMockito: "com.nhaarman:mockito-kotlin:$versionKotlinMockito",
assertj: "org.assertj:assertj-core:2.5.0",
mocksFactory: project(":app-mocks-factory"),
]
}
Here are a couple of things that might be interesting to mention.
- To include simple dependency:
rxJava: āio.reactivex:rxjava:1.2.0ā
- To include a project that is a part of the project, you could define it like this:
components: project(ā:app-componentsā)
- This also can be used when including plugins for the project:
gradleVersioning: ācom.github.ben-manes:gradle-versions-plugin:0.13.0ā
- The versions, defined in
versions.gradle
can be used dynamically like this:gradleBuildTools: ācom.android.tools.build:gradle:${versions.androidGradlePlugin}ā
- Whenever you have same version needed to be applied in multiple dependencies, you can define it into a variable like this:
final versionJUnit = ā4.12ā
- Also the cool thing about this, you could ācategorizeā dependencies for easier tracking what goes where!
After we finished defining versioning files, we need to include them into main project builds.gradle
file like this:
buildscript {
apply from: rootProject.file('versions.gradle')
repositories {
google()
mavenCentral()
jcenter()
}dependencies {
classpath plugs.gradleBuildTools
classpath plugs.gradleVersioning
classpath plugs.kotlin
}
}
The important part there is only apply from: rootProject.file(āversions.gradleā)
. This will associate the versions file with the build files. Whenever we do this, we can include the plugins for the project like this: classpath plugs.gradleBuildTools
. Including dependencies and versioning names to modules of the project is as simple as this:
android {
compileSdkVersion versions.compileSdk
buildToolsVersion versions.buildToolsdefaultConfig {
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
vectorDrawables.useSupportLibrary = true
}
}dependencies {
implementation coreDeps.coreUtils
implementation coreDeps.components
implementation coreDeps.models
implementation coreDeps.kotlin
implementation coreDeps.rxJavatestImplementation unitTestDeps.mocksFactory
testImplementation unitTestDeps.junit
testImplementation unitTestDeps.mockito
}
- Providing compile/build tools/sdk versions is as easy as just linking back to
versions_general.gradle
like this:compileSdkVersion versions.compileSdk
- And same thing goes for dependencies, š
implementation coreDeps.coreUtils
. Clean and simple.
Summary
Cleaning up project dependencies moved me to look through all the project and remove unused dependencies and remove duplicates whenever iāve found it. Thatās what I call a bit of refreshment for the holidays š² and for our lovable playground ā¤ļø.
And what would be a post without an example project ? š https://github.com/marius-m/versioning_love
Cheers š¤