Posted on

Android Studio Gradle Plugin pt 2


android default view attributes

Designed by Freepik

In previous post we created a basic Gradle plugin. And I realized that it’s easier just to write them in Android Studio, right in the modules build.gradle. And then you can move it to standalone project to build and release. What we’re going to do now is make all views to have a default wrap_content attribute.

Wrap Content

So this one is quite common, I wouldn’t say that it’s more common than match_parent, but for default it makes more sense. What do I mean by default? I mean that you don’t need to declare it in XML. I still use XML editor, although ConstraintLayout is out, plus it’s a great way to learn about Gradle

If your view doesn’t have layout_width or layout_height attributes you’ll get red underlying, but it’s not compiler complaining, just lint. And you’ll still be able to build successfully. What you’ll get is a runtime exception.

Which is great, this means that we won’t have to fight with compiler.

Gradle Plugin in AS

Anyways, that’s a boilerplate code for creating and applying your own Gradle plugin in Android Studio.

Add this to app build.gradle file and after this you’ll see a gradleBasics folder in Gradle sidebar with checkAttributes task. Project.task is a method for adding new tasks

Layouts

Now let’s figure out what happens in build. I use Data Binding library, so I started with it and by no means following code is not a final fully functional plugin, but rather a work in progress.

So if you know Data binding, they have a layout tag that wraps the whole layout. And during builds it’s gone of course plus some Java generated classes. And the output of that layout I found is in app/build/intermediates/data-binding-out/flavorName/buildTypeName/layout

As I said I don’t handle non data binding layout yet and this one is gonna be for just activity_main.xml file. So what I have is I didn’t declare layout_height for a Toolbar. And it gives a runtime exception.

Gradle

If you’re not familiar with Gradle or syntax, surprisingly it’s super easy to start. Because  it’s JVM based and like with Kotlin, it’s just a different representation of common to us Java code. All the libraries you can use in Gradle, language by the way called Groovy.

Build Types/Flavors

Ok, let’s begin. First, I haven’t figured how to get current build type, flavor in Gradle, but this code returns all of the variants.  What are variants? Let’s talk about build types and flavors first. Build types are familiar for you: debug, release are standard ones. And flavors you declare with this

I recommed everybody to add those for every project. As a matter of fact I have a Android Studio template which includes those automatically for every new project. Check this post for details. What this minSdkVersion does is it improves your build types in min 3 times, it’s something with dex indexing. Don’t forget to choose it

android default view attributes

And when I return to lagacyDebug for testing pre L version, builds take forever, about 5-9 minutes compare to 1 minute modern one. Convinced yet?

And what you see, build variant is a combination of a flavor and build type.

Plugin

So not to hardcode variant output directories we can access them with this code

When you hold Ctrl and hover over those variables you can see source of only project. Which means that for android. there’s no autocomplete/suggest, you can’t see possible method options nor source code. What, do I need to go online for a reference like it’s 1992 you might think? No, you can check possible methods inside of android {} and then write your tasks.

Here’s the whole task code

First it build paths for all the possible activity_main.xml build directories and checks if file exist. Then using default Java libraries to parse and edit xml and save changes. As I said, it’s still too hardcoded. And now your Toolbar will have a missing height attribute and app won’t crash

Run at the Right Time

Of course you don’t wanna manually run this task. The perfect time to run it is after data binding generated those files. Just by checking for task that contain databinding in them I found those dataBindingProcessLayoutsModernDebug. It sounds like what we need and for now I just make our script run after that task only

As you see it’s hardcoded, I will fix that in future. What you get now is your view have a default wrap_content attribute. More of an example, fully functional plugin is gonna be later, just a matter of parsing the whose layout and check if view doesn’t have widht/height attributes

 

Ok, thanks for reading. Don’t forget to subscribe, follow me on Twitter, Facebook, G+ and share with friends if you think they will benefit from it!