Agree or not agree, but on an average consensus pretty much every android dev goes through the loop of Update Dependencies.Code.Repeat. for each of his/her android project. Its frustrating, a waste of time and super annoying when you would want to have the same version across all projects.
One of such situations that I recently got into was trying to keep all my apps under Android-Examples repository on github updated. As you can see it the repository has multiple small and simple examples of completely functional android apps. Keeping all of them updated was becoming a hard task whenever a new version of android-gradle-plugin, support library or google play services would be released.
Initially I would go on to update each app in the repository and then commiting it back. As you can see it wasn’t the most efficient way to do it. So sometime back I decided that I am going to put an end to this process and make all version configurations common to all apps and thus escape the Update Dependencies.Code.Repeat. loop of hell.
So now that I had decided to not update each app individually, I decided to look at my options. The obvious one here was looking at Gradle that supported variables.
Now we all might have done this for
support-library , where we define a variable inside our module’s
build.gradle and then reference it as below
So what I have done here is basically
Defined a variable named
supportLibVerwith the value
Next referenced it by using it in the
Note that the surrounding quote is a double quote
"and not a single quote.
Now this approach is basically using a Local Variable , which means that this variable works in the scope of the
build.gradle file it is defined in.
We want to externalize the variable from outside the
build.gradle file of the module, so as to provide values to all modules of the project.
Gradle’s Extra properties comes to the rescue for this.
The way we use them is by moving our varibales to an
ext block inside the project’s root
build.gradle file and referencing it as below
Now reference it in all/required modules as below
Notice that referencing variable is changed now to
..hmm looks like we are going somewhere with this. So till now we have been able to externalize the variables so as to facilitate common values to the multiple modules inside a particluar project.
But my requirement was a step ahead than this. I wanted to provide common values to all projects inside my repository and not just to one particular project. So I needed to provide an external
gradle file (that I place at the root of the folder which contains all my projects) with all
ext variables defined in it , something like this [dependencies.gradle]
But how do I make them available to each sub-module inside each of my projects?
I had to dig the gradle docs and buried deep inside is a section that talks about it, called Subproject Configuration.
So after some practical experimentation i figured out how I can use it to facilitate the
ext variables to sub-modules of each project.
This is what I did next in each Project’s root
build.gradle, I added a
subprojects configuration section just below
allprojects configuration section and added a
apply from: statement to apply my external gradle file to each sub-module.
What this did was that it made my external variables, defined in
dependencies.gradle files available in the scope of each module in each of my projects now and I could now reference them simply as
Good. Now this makes life so much easy and now I can provide common values to all the dependencies.
But wait, if you would try to provide a variable and facilitate the version for
android-gradle-plugin, you would see that this wont work!
Well thats a bummer, as I needed to make that as a common variable too.
So after much experimentation, I figured out it was because when we define the
subprojects configuration , it doesnot apply to the root project’s
build.gradle. Hmm, this is news as we had almost solved the problem.
So the way I solved this is by applying the
dependencies.gradle to the
buildscript section directly inside the root
build.gradle for each Project. So now each project’s root
build.gradle script became as below
Here is a functional root
build.gradle script from one of the project of my repository itself and Here is a functional module
build.gradle script from the same project of my repository itself. You can see I extended the idea to start externalizing the variable for
compileSdkVersion too :D
Great! Now we only need to change the values inside the
dependencies.gradle file and hey presto! when ever I would be loading up any of the projects , they will reference the values from this file and would automagically be working of the most udpated version.
You can checkout the Android-Examples repository to see a fully functional model of this approach.
Phew, thats all for this time. Hoping it will solve any similar problems, as this approach can be definitely be extended.
Got featured in AndroidWeekly Issue 221, thank you for the love
Comment/Suggest me a better approach, if you know one.
Keep on crushing code!🤓 😁