(upbeat music)
- Hello, welcome to What’s New in Android Gradle Plugin.
I am Jerome Dochez, a software engineer
on the Android Gradle plugin team.
The first thing I want to talk about
is a new feature called configuration caching.
Caching the result of the configuration phase
means that it is almost completely disappeared
after an initial warmup, but how does it work?
Well, instead of recalculating the task graph
every time users invoke the same build command,
Gradle has the ability to serialize and deserialize
the task tree for reuse.
See how it improved the AGP build time.
Also having a deserialized task tree allows Gradle
to be more aggressive in running tasks in parallel,
which lead to further execution performance improvements.
Please try it as soon as possible,
but first, check that all the plugins you use are compatible with Configuration acche.
Now onto Chris Warrington.
- Thanks Jerome. Hi, I’m Chris,
and I also work on the Android Gradle plugin team.
Alongside the performance improvements from configuration caching,
we’ve been working on many other improvements to the Android Gradle plugin.
There’s two I’m gonna call out that I’d invite you to try.
Firstly, in Android Gradle plugin 7.0,
you can try our non-transitive R-class support.
This makes it explicit which resources you’re using and from where,
and improves build performance especially for larger projects.
There's a refactoring tool in Android Studio preview
to automatically fix up your project sources to support non-transitive R-classes.
Especially if you work on a large project, I’d encourage you to try it out.
We’ve also made some improvements to the Lint integration in Android Gradle Plugin 7.0
Firstly, the Lint task can be up to date. So if you don’t change anything in a library,
it won’t re-run through that library.
And we're working towards making it cachable,
so that even builds from clean benefit. This should help performance of running Lint
in a continuous integration setup that takes advantage of that significantly.
We’re excited for you to start seeing the benefit of these improvements
to the Android Gradle Plugin.
However, we know that upgrading your project to the latest version can be a barrier.
So alongside these performance improvements,
we’re also making the Android Gradle Plugin easier to use and easier to upgrade.
To achieve this, we’ve been working on our DSL.
That’s the language you use to configure your build.
First of all, reference documentation is now available on developer.android.com,
and covers all the DSL and APIs of the Android Gradle Plugin.
We're also cleaning things up
to hopefully make the DSL more consistent and easier to understand
while keeping existing projects and plugins compatible as much as possible.
And don’t worry, when I say cleaning things up,
underneath we won't remove the old way immediately
to give you time to migrate.
Our team is improving the Upgrade Assistant
to help you keep your project up to date
so you see the improvements we’ve been making to the tools.
The Upgrade Assistant now understands when things were added, renamed, or removed.
So it knows what needs to be done.
It empowers you to make choices about how and when you upgrade your project
and guides you through the process.
And the Upgrade Assistant shows you a preview of the changes before you commit to them.
All of this is working towards the goal that upgrading the Android Gradle Plugin
should be pretty seamless.
We've still got more to do,
but I hope that what we’ve delivered in Arctic Fox
makes keeping your projects up to date easier.
Now over to Jerome to talk about that the Variant API.
- Thank you, Chris.
Let’s talk about the other part of the big new push
for well-defined APIs in the Android Gradle plugin,
the Variant API.
But first, what is a variant?
As you know, you can define build types and product flavors in the AGP DSL,
and those are called variant dimensions.
We combine these variant dimensions
to create several variant objects and end result APK
or bundle will be built for each variant. These variants apply to all project types,
like application, libraries and dynamic features.
These variant objects are used to provide values to tasks.
So the first thing to understand is that tasks do not directly use the DSL objects.
but instead, the variant objects.
We therefore wanted to provide an ability to manipulate the variant objects
in order to directly influence the tasks input.
And that's the Variant API.
Gradle API is the module with all of our supported public APIs,
and you should only depend on that module
when writing plugins that interact with the Android Gradle Plugin.
The rest of the AGP code, and in particular, tasks, are private,
and these private APIs
should not be used directly by your plugins.
The Variant APIs can be divided into two broad categories,
access to tasks’ input values,
access to intermediate files produced and used by the Android Gradle Plugin.
Like I mentioned earlier,
the values that are used as input parameters to the tasks,
these values are not represented
as intrinsic values anymore, but as properties.
So for instance,
DSL applicationId, which is a string in the DSL,
becomes applicationId as a property of the string in the Variant API.
If you’re not familiar with the Gradle’s Provider/Property concepts,
I recommend you watch our presentation last year,
as this would otherwise become very opaque to you.
Using property objects everywhere has several advantages,
but the main one is that you can provide a value
for applicationId through a task,
and that task will automatically be invoked by Gradle
when applicationId.get() is invoked.
This is very important concept for those of you
who used code snippets to calculate values in order to set tasks input.
You should not do this any longer.
Instead, write a task with well-defined inputs
and outputs declarations,
so Gradle knows when it is up to date or not, and use the task output to set the value
on the property object.
Here, you can see an example. The tasks at the top defines an output
and writes the content of the file during the execution.
Using the Variant API, you can wire the output of the task
to the variant.applicationId.
It’s important to notice the variant.applicationId
will be determined, and known only at execution time,
once that task has executed.
Now, let’s continue this overview of the Variant API by talking about its lifecycle.
First, all the Variant API Blocks or Lambdas
are created in the androidComponents extension, not the Android one.
We wanted to separate Android and androidComponents,
to make it clear that all static configuration
belongs to the Android block,
while all dynamic behavior should be placed in the androidComponents block.
Here you can see a succession of steps in the life cycle of the APIs.
First, the DSL objects are finalized and locked.
The Lambdas registered with the before Variant APIs are executed.
This gives you the ability to disable variants of no interest.
But for those variants which are still active,
we then create a variant object,
and the Lambdas registered with the onVariant API,
are executed on these variant objects.
After the variant objects are locked,
so if you try to change any values, it will fail,
but you can obviously continue reading the values,
especially at execution time
if you’ve got tasks consuming these objects.
But finally the tasks from the AGPs are created
with these finalized values
and the execution phase can begin.
The Android Gradle plugin produces a lot of intermediate files,
like the merge manifest file, the dex file, et cetera, et cetera.
So we wanted to give some access to these intermediate files.
Some build customization might need to have access to these intermediate files,
so to modify them further before the modified value
is used by downstream tasks.
The Artifacts field on the Variant API will allow access
to predefined operations.
Like getting the final version of an intermediate file
just to check that it is correct,
replacing it with a completely different file,
or transforming it, which means consuming it,
changing it a little bit and reinjecting it inside to be processed.
One important factor to notice
is that the Android Gradle Plugin, itself, uses these APIs internally
to wire its own tasks, input, and output.
Any third-party plugins that want to interact
with the AGP tasks will be on the same footage.
Now back to Chris to talk about ASM.
-Thanks, Jerome.
We've also been focusing on delivering APIs
for specific advanced use cases too.
One thing we know from maintaining the Android Gradle Plugin
is that implementing Incrementality in a correct and performant way is tricky.
The Legacy Transform API offered a lot of flexibility
but at the cost of pushing that complexity onto the plugin author.
It also prevents the Android Gradle Plugin from taking advantage of new Gradle features
to make things faster. So in Android Gradle Plugin 4.2,
we have a new API specifically for bytecode transformation,
which is much more performant, and we hope it’s much simpler to use.
We have API recipes on GitHub.
So if you'd like to dig into the details and build a plugin that uses the API,
do have a look.
A simple example of using the API goes from hundreds of lines to tens,
and we saw a healthy reduction overall build times for a medium-sized sample project.
We’re working with plugin authors who use the Legacy Transform API
to migrate them over to the new Artifacts and ASM APIs.
The ASM API is already in use by the whole plugin,
and others should follow soon.
So, whether you’re an experienced Gradle Plugin author,
or just starting to look at what’s possible,
you can dig deeper into the new APIs we’ve been talking about
by taking a look at our new APIs in the Android Gradle Plugin article on Medium,
which is linked in the video description. We'd also love your feedback.
Please try out these new APIs,
especially if you maintain a plugin on top of AGP.
And if neither the ASM API nor the new Variant API support your use case,
please let us know by filing an issue on the issue tracker.
Thanks to all my coworkers for their contributions
to the Android Gradle Plugin and Android Studio,
and thanks to all the developers, all of you,
who’ve engaged by trying preview versions and filing issues.
We really do value your feedback.
Thanks for joining us.
And we hope you have a great time building great Android apps.
- Thank you.
(upbeat music)