API is a globally used abbreviation for Application Programming Interface which allows intermediary software for establishing communication between two applications. Each time you use a social media application such as Instagram for sending an instant message or you place an order online, you are implicitly using an API.
Before knowing about the contemporary APIs in the Android Gradle Plugin, let’s understand what exactly an API is. API is used for connecting applications to the internet and sending data to the server, while you are using your mobile phone. In response to the data that you send to the server, it retrieves the necessary information, interprets it, performs the required action and reverts it to your mobile phone. API is the application which is responsible for interpreting the data and sending you the formatted information in a readable manner. This is the prime role of an API in applications.
The Android Studio build system is driven by Gradle and many features of the Android Studio are enhanced due to the Android Gradle plugin which is customised for creating Android apps only. Usually, the Android plugin is updated in lock-step with Android Studio. But it is capable of running Independent of the Android Studio and in some instances, it can be updated separately.
The Android Gradle Plugin comes with a wide range of tools for compiling the various distinct code snippets and linking them together into an app that runs error-free on your tangible Android device or emulator. There is a significant level of decoupling between the Android Gradle Plugin and the Android Studio. Android Studio is totally compatible with any stable version the Android Gradle Plugin, it is even backwards compatible with the traditional Android Gradle Plugin 1.1. So even if you have decade-old projects that can also run efficiently on the Android Studio. Gradle scripts and the Android Gradle Plugin configure and extend the build-in features according to the use case.
The configuration of the elementary projects in Android is mostly declarative. You can configure the Android Gradle Plugins that are written by using a Domain Specific Language (DSL) or a Gradle Build Language that is based on Groovy script. The build.gradle.kts files are written using the recently introduced Gradle Kotlin DSL. The Android Gradle Plugin DSL was written years before the introduction of Gradle Kotlin DSL. You only need to do refresh the Android Gradle Plugin DSL for working with the Gradle Kotlin DSL. Furthermore, the Android Gradle Plugin 4.1 is fully compatible with the new Kotlin DSL.
The DSL should not be considered as the only solution for extending the build. The Android Gradle Plugin is itself a binary plugin. You can use Groovy or Kotlin for writing scripts apply them in multiple build files for reuse within a project. But a better alternative stop for placing custom imperative logic is buildSrc, that is compatible with Groovy and Kotlin, and on top of that Java. Usually, binary plugins written in Groovy, Java, or Kotlin are used for customisation.
A lot of build developers intend to extend the Android Gradle Plugin by following various techniques, such as altering current artifacts, creating supplementary artifacts that will contribute to the final artifact or configuring previously specified variants delicately. Although the APIs for the above-mentioned use cases were already present in The Android Gradle Plugin, it needs to be updated so that it is less coupled to the abstract implementation specifications of the Android Gradle Plugin which lead to the scope for flexibility in future and enhanced compatible with Gradle’s lazy configuration.
New APIs in the Android Gradle Plugin:
DSL INTERFACES AND DOCUMENTATION:
On the basis of the pre-existing implementations, the Android Gradle Plugin 4.1 has introduced several new DSL interfaces. The new documentation published for the DSL and API of the Android Gradle Plugin has been extracted from these interfaces. With the introduction of API and DSL Interfaces in Kotlin, the Kotlin script support enhanced and some breaking changes were observed by the Kotlin script users.
The ecosystem around the Android Gradle Plugin had stretched, but the pre-existing DSL definitions failed to some extent. The documentation generator was a classical replica from Gradle and missed support for the contemporary Java 8 language features and Kotlin. Furthermore, there was no clear definition of stable and experimental APIs. Clearing all these bugs was a very challenging task due to the different system requirements and level of compatibility of the build authors interacting with the APIs present in the Android Gradle Project.
In order to preserve the existing DSL implementation classes for maintaining binary compatibility, interfaces were created in Kotlin in the gradle-api artifact. These define all the public functions present in the DSL and are implemented with the help of pre-existing implementation classes. Now the documentation for Android Gradle Plugin is generated from these Kotlin interfaces, so that uniform documentation is present whether Groovy or Kotlin script, buildSrc or binary plugins is used for adding functionalities.
We added some constraints in defining the interfaces in Kotlin, with respect to nullability and mutability, that they should be declared explicitly. Although in the long run, this was helpful, it comes with a shortcoming for the pre-existing projects in which the build authors have already employed Gradle’s Kotlin script support.
Another hurdle was to make the decision about expressing collections that are mutated in DSL.
Now collections are defined as, val collection: MutableCollectionType. This implies that now it is impossible to assign collections in Kotlin scripts using, collection = collectionTypeOf(…)
NEW VARIANT APIs:
Even though we already had a variant API in the Android Gradle Plugin, it had some restrictions due to its design choices. Instead of upgrading the pre-existing API and stacking debts on it, developers decided to introduce a completely new API to resolve all the prevailing issues and provide a better extension model which is almost decoupled from the internal operations of the Android Gradle Plugin.
For the convenience of the Android developers, the existing API will be retained for a while and authors and plugins will be gradually migrated to the new system. Google has also released a collection of sample use cases of the new variant and artefact APIs, which is still being expanded. The previous API was much slower than the new API in terms of configuration runs. In the previous API, the build flow decisions were made prior to the running time of API, while the new API allows the variants to be modified later also.
The build flow alternations in the new API can be both, explicit and implicit, in the earlier category the setting properties affect the build flow while in the latter one, in case there is an incompatible optimisation in terms of the variant API, it is done conditionally on the use case of the specific API.
The new API divergers into two callbacks, onVariants and onVariantProperties.The action for each variant created runs with the help of onVariants.For customising the properties affection the build flows, such as enabling or testing a variant, build authors and plugin authors use the new Variant API. Following this, the onVariantProperties callbacks are made that allow the build authors and plugin authors to create register tasks and custom logic that absorb or alter the intermediates of the build.
The onVariantProperties API is implemented by Gradle Properties and Providers.Properties allow us to use the API without worrying about the accurate value of the API. They also allow provide libraries for lazy computation of value and tracking dependency information. The onVariant API doesn’t use properties as these values are used at the configuration time and it is not at all benefited from the laziness. Though it takes the advantage of running prior to the configuration for offering a higher degree of flexibility than the previous API.
The new API in Android Gradle Plugin allows us to manage the registry of artifacts linked with each variant for all the input, output and intermediate files. These files are expressed in terms of providers with dependency information attached.
The possible operations on artifacts include:
It always receives the final version of an artifact, which is a read-only value. As it is not allowed to modify the artifact obtained by a get. This is the reason for keeping the return type of the get method a Provider and not a Property.
It only seems to be relevant for artifact types that are decorated with MultipleArtifact, as they can be represented as a List of either Directory or RegularFile. A task is used for declaring an output that will be appended to the list.
It is used fie eliminating all the current provider of an Artifact. discarding all previous producers with a new one. It is an ‘out’ operation in which a task declares itself as the only provider of the artifact. In cases where more than one task declares itself as the artifact provider, the last one is the winner.
By Vanshika Singolia