0% found this document useful (0 votes)
85 views47 pages

All You Need To Know About Gradle in Android

Gradle is a build automation tool essential for managing Android project builds, with key files being build.gradle at both module and project levels. The module-level build.gradle configures individual modules, while the project-level build.gradle applies settings across all modules. Important configurations include compileSdk, defaultConfig, build types, product flavors, and dependency management, which collectively facilitate effective project structure and resource management.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
85 views47 pages

All You Need To Know About Gradle in Android

Gradle is a build automation tool essential for managing Android project builds, with key files being build.gradle at both module and project levels. The module-level build.gradle configures individual modules, while the project-level build.gradle applies settings across all modules. Important configurations include compileSdk, defaultConfig, build types, product flavors, and dependency management, which collectively facilitate effective project structure and resource management.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 47

Gradle in Android

 Gradle is a build automation tool used to manage the build


process for Android projects.
 Gradle acts as the maestro that determines when each task
starts and exactly what it will do, as we will see later.

Structure of gradle files


 There are many files related to Gradle, and we will discuss
all of them, but the most important files are those related
to build.gradle, which are of two types.

Module Level Project Level


build.gradle.kts (Module :app) build.gradle.kts (Project: [project name])

Now, we will talk about each one of them and the difference
between them.
 What is the difference between
the build.gradle for the app and the build.gradle for
the project?
 any module you create has its own build.gradle, and the app is
considered a module, which is why it has its own build.gradle.
 On the other hand, the project can contain more than one module,
which is why there is a build.gradle for the app module and
a build.gradle for the entire project.
 Any code I write in the build.gradle for the app will apply only to
that app, which is a module.
 Meanwhile, any code I write in the build.gradle for the project will
apply to the entire project, including all the modules, one of which
is the app module.
 First: build.gradle (Module: app)
o The location of this file is in the module itself: app/build.gradle.
o Its purpose is to specify the configuration for the module, as we
will see.
o If you open the build.gradle file for the app module, you will see
several blocks that we will discuss now:
1- Plugin Block
 These plugins are specific to the app module only, meaning I cannot
use them outside the app module in the rest of the project.

2- android Block
 The android block contains several attributes and blocks that we will
discuss in detail.
 Namespace

com.example.myApplication

This is considered the top-level This usually refers to the


This is considered a second-level domain,
domain (TLD) for the company or name of the application in
and it usually is the name of the
organization, and it is usually "com" the case of the app module,
organization or the company. For
for commercial reasons, similar to while for the other modules,
example, if I am creating an app for a
many companies. it refers to the name of the
company named "Example Corp," I would
module itself.
choose the word "example" to reflect the
company's name.

 The app module is considered the main module for the entire project;
therefore, the namespace is the application ID.

 What is the benefit of the namespace?


The namespace ensures that the resources and classes in the module are
uniquely identifiable to avoid conflicts. For example, if I have two modules,
and each has a class for a specific feature with the same name, conflicts will
occur without the namespace. However, by using the namespace, I can
uniquely define which class belongs to which module.

 compileSdk
Here, I will specify the Android SDK version that
the app will compile against.

Specifying compileSdk as 35 means this project will be compiled with Android


SDK 35, allowing it to use the features of SDK 35.
 defaultconfig Block
The purpose of this block is to define the default configuration for the
application.

applicationId
o The applicationId is a unique identifier for the app in the project or on Google
Play. There may be multiple apps with the same name in the store, but there
cannot be more than one app with the same applicationId since it is unique.

minSdk
o Setting minSdk to 24 means the app will not run on any device with an API
level lower than 24.

targetSdk
o Setting the targetSdk to 35 indicates that the app is designed to run on devices
with an API level of 35 and it’s preferable for compileSdk to match
the targetSdk.

versionCode
o This is an integer representing the version number, which is important for
updating the app on the app store. It must be incremented each time the app
is uploaded to the store.

versionName
o This is a string that can be in any format, such as "14.", "5", or "41.9." Its
purpose is to display the app's version to the user on the app store.
testInstrumentationRunner
o This is related to testing; it specifies the test runner to be used for running
instrumented tests.

 buildFeatures Block
I use the buildFeatures block to enable certain features, such
as viewBinding, dataBinding, or BuildConfig.

 buildType Block
Every app has two default build types: release and debug,
which are created with the project.

 The release is the production version that goes to the client and
is uploaded to the Play Store for final use.
 The debug version is used by developers or testers, allowing
them to track issues or the code during development.
 I can easily add another build type by going to

File > Project Structure > Build Variants.

 I will notice attributes for the build type, such as the application
ID Suffix in debug. If I specify it as .debug, it will append the
word "debug" to the base package name.
 If I want the debug version to have a different app name than the
release version:

1. First, ensure I am in Project View.


2. Next, open the app module and the src folder.
3. Create a directory and choose Debug/res.
4. Create a resource file named strings.
5. I will find it overriding the strings file, allowing
me to change it.
 If I run the app, I will see that it installs on the device with the
new name in debug mode.
 Similarly, I can change any resource, meaning a specific resource
can exist in the release version and a different one in the debug
version.
 If I have specific code that I want to execute in debug mode
and not in release:
1. I will enable BuildConfig like this:

2. I will write the code like this:

 If I run the app, I will see that in debug mode, it performs


the toast, whereas in release mode, it does not execute
the toast.
productFlavors
 By default, there are no flavors in the app at the beginning, but there
are two build types: debug and release, which we discussed earlier.
 What is the difference between build types and product
flavors?
- The build type gives you a different type of build, whether it’s debug or release,
while product flavors generate APKs with different characteristics. What does
this mean?
- For example, if I have an app and I want to create a free version and a pro
version, each of them will produce two versions, which are
the debug and release, allowing me to test both versions from all aspects and
eventually release them.

 How do I add flavors?


- Suppose I have an app and I want to create a paid version and a free version:
- Go to File > Project Structure > Flavors.

- If I click Add Product Flavor, it tells me that I need to have a flavor dimension.
- Therefore, I will choose the first option, Add Flavor Dimension, which will open this
dialog where I will specify the flavor dimension name.

- It will appear like this:

- I will add the first product flavor as free and the second as pro like this:
 I will notice that there are attributes for each flavor that I can define,

 such as the version code and minSdk, and I can specify these for each flavor.

 Now, for example, I will set the ApplicationID Suffix like this:
o Free --> .free o Pro --> .pro

 If I go to the build.gradle file for the app, I will find that it has automatically
added this code:

 I can add any resource to any flavor, and I can also add it to a specific flavor while
leaving the other flavor without it, in the same way mentioned before:

Product view > src > generate directory > free/res

 Here, I will create any resource I want in the same way as before.

 I can control the execution of any code in any flavor in the same way as
before, like this:

 This code will execute in free and will not execute in pro.
 There’s another way to implement different code in each flavor:
Step One:
1. I will display the project in Project View.
2. After that, if I select the build variant, for example, freeDebug, I will create:
src > directory > freeDebug/kotlin

3. A folder named kotlin will be created where I will create a class or file and
define a method, for example, like this, which I will not be able to access
unless I am in freeDebug.

Step Two:
1. I will do the same as before but select a different build variant, for
example, proDebug, and then create : src > directory > proDebug/kotlin
2. A folder named kotlin will be created again, where I will create a class or file
with the same name as before; follow the same System of access, which will
only be available while in proDebug.

Step Three:
 If I run the app in free, it will execute the code I created in freeDebug, and if I
run it in pro, it will execute the code in proDebug.
BuildConfig file

BuildConfig is a class that is generated, and the values inside it


are static.

 To enable it, I go to the build.gradle file of the module


and add this code:
 How to add a parameter to BuildConfig?
 I will use the method:

buildConfigField(“Boolean”,”isHappy”,”false”)

Parameter datatype Parameter name value

 There are three ways I can add parameters to BuildConfig like this:

 Method One: defaultConfig

 The advantage of this method is that I can create


the parameter and access it anywhere.

 After syncing and building, the parameter will be added to the


class, and I can easily access it like this:

 If I run the app, I will see a toast with the value from the class,
which is false.
 Method Two: buildType
 If I add it only to the release, it means I can only use it in the
release, and the same applies to debug.

 I can access it the same way as before without any issues.

 Method Three: flavors


 If I add it to the flavor, for example, the free flavor, it means I can
only use it in this flavor, whether it’s debug or release.
 compileOptions Block

 Using this block allows me to specify Java compatibility


with the source code and bytecode:

 sourceCompatibility = javaVersion.VERSION_1_8
 This line specifies compatibility with the source code.
What does this mean?
 It means that the source code will use the features available in Java 8.
This allows me to use features such as lambda expressions, stream
API, and other Java 8 features without facing compatibility issues.

 targetCompatibility = javaVersion.VERSION_1_8
 This line specifies compatibility with the bytecode.
What does this mean?
 It means that the bytecode that is compiled must be compatible
with Java 8. So if there's anything above Java 8, I won't find it in
the bytecode. This way, I can ensure that the generated class file
can run on a Java 8 runtime environment, even if I'm using a newer
version of the SDK for compilation.
 When I choose the JVM, it must be suitable for the minSdk, since,
for example, if I choose a low JVM version with a high minSdk, it
won't work.
 Before moving on to the next block, let’s talk about
the difference between

Java Version vs. Java Bytecode Version


 First: Java Version
 The Java version's role is to specify the Java features that we will
use. The same applies to Kotlin (e.g., Kotlin version).

 Second: Java Bytecode Version


 This specifies the Java bytecode that results from compiling the
source code. Each new version includes additions such as
capabilities and optimizations.

 The bytecode version does not relate to language features. This


means, for example, that I can use Java bytecode version 18, but I
cannot use the features in Java 18; these are two separate things.

 I must choose the Java version and Java bytecode version correctly,
because sometimes, for example, I might be using a library that
targets a specific JVM. If the library is compiled, it may produce
bytecode that is not compatible with the JVM I specified.
kotlinOptions Block

jvmTarget = “1.8”
 This specifies that the Kotlin code must compile to Java bytecode that is
compatible with Java 8, similar to targetCompatibility.
 This ensures that any Kotlin code can utilize the features available in
Java 8 and can also run on a Java 8 JVM.
3- dependencies Block
 In the dependencies block, we add the libraries we will need in the code.
 There are several keywords we use:

implementation
 This is used frequently, and through it, we can add any library or even
another module, and we can use it anywhere in the module, whether in the
package or in tests.

api
 This functions similarly to implementation, and we
discussed the difference between them previously.
Module 1
 Let’s assume I have three modules, and each module
has a class structured as follows: Class 1
 After that, I will implement it the way we discussed
before, which is --> implementation(project(---)) implementation
 The question now is: Does module1 recognize class3?
 The answer is no, and this is Module 2
what implementation means; it implements the
library only for the module itself, not for the other Class 2
modules that depend on it.
 Can I do the opposite? That is, implementation
make module1 recognize class3. Yes, of course, all I
need to do is change the Module 3
word implementation to api in module2 Class 3
like this: --> api(project(":module3"))
 This way, I can access class3 in module1.
debugImplementation
 This means that these libraries will be used only in debug mode.

releaseImplementation
 This means that these libraries will be used only in release mode.

testImplementation
 This is specific to the implementation related to local unit tests.

androidTestImplementation
 This is specific to the implementation related to tests that require
the emulator to be running during the tests, which refers to
Android tests.

 Secondly: build.gradle (project: project name)


 This file specifies the configuration that I want to apply to the entire
project.
 The same code that we discussed in the build.gradle file for the app can
be written here and used in the build.gradle(project), but as we said, it
will apply to the entire project.
 The location of the build.gradle file is found in the root project.

 The plugins here are supposed to apply to the entire project, but since
I’ve specified that it’s false, that means it will not apply to either the
project or the modules.
 Thirdly: settings.gradle.kts
 The settings.gradle is part of the Gradle build system used to configure
and manage multi-module projects.

 The settings.gradle file contains several elements for managing the


project, which we will discuss now:

1. pluginManagement

 The method pluginManagement() contains a method


called repositories(). The purpose of this method is that when I add any
plugin, it searches for it in these repositories.

2. dependencyResolutionManagement

 The repositories() here is specific to dependencies, meaning any


dependencies present in any module will be searched for in these
repositories.
 For example, if I have a library structured like this:

 When I run it, I will encounter an error that states:

 It tells me that it cannot reach the dependency. If I go to the website


from which I obtained the dependency, I will find an explanation of
how to use the library, and it tells me that I should add this code:

 I will add it to my project like this:

 If I run it, I will see that the library has been added, and I can use it easily.
3. name of the root project

 This specifies the project name that I defined for the project.
 include function

 This function is very important because I specify the modules that exist in
my project.

 Fourthly: gradle.properties
 This is a configuration file used in Gradle builds to define properties
and settings, as we will see shortly.
 The gradle.properties file allows me to customize many aspects of the
build process without having to change the build script.

What can I write in the gradle.properties file?


1- Define properties
 I can define properties that I can access anywhere in the Gradle
build scripts, such as in the build.gradle file.

 After that, I will be able to access them in any build script


file like this:
2- Configuration settings
 I specify the build configuration settings.

 Here, for example, I specify the JVM arguments that Gradle uses for
running. These arguments allocate memory, performance options, and
encoding:
 -Xmx8192 --> This option specifies the maximum heap size that the
JVM will use, which is an additional 8 GB.
 -XX:+HeapDumpOnOutOfMemoryError --> This is a flag that creates a heap
dump in case an OutOfMemoryError occurs.
 -Dfile.encoding=UTF-8 --> This sets the default file encoding for the JVM to
UTF-8.

 This enables the Gradle daemon process, which speeds up the build
process.

 This allows Gradle to execute multiple tasks in parallel. If you set this to
true, it will execute more than one task at the same time. This certainly
increases performance and improves the build speed by using multiple
CPU cores.

 When this feature is true, it allows Gradle to configure only the modules
required for the tasks currently being executed, instead of configuring all
the modules.

 This enables AAP2 (Android Asset Packaging Tool 2), which helps
package all the files in the project to generate the APK.
 This enables the Gradle build cache, allowing it to use the output
from previous build processes, which increases build speed.

 This enables AndroidX dependencies libraries, which are considered


better than the old Android libraries.

 This enables the Jetifier tool, which helps ensure compatibility


between older Android libraries and AndroidX libraries.

 Fifth: local.properties
 This is a file among those that exist in my project, and it is a
simple text file generated by Android Studio.
 One important thing here is that by default, this file is included
in .gitignore, meaning it is among the files that will be ignored
when I upload the project to any version control system.

What is the benefit of the local.properties file?


1-Environment-specific configuration
 I can specify configuration settings such as SDK paths.

2-Sensitive information
 If I have sensitive information, such as an api_key, I can
store it in local.properties, as we will see shortly.
3-Convenience
 I can clarify or explain the steps for anything I want for
new developers.
Now let's store the api_key in local.properties:
Step One:
 I will go to local.properties and write the api_key there like this:

Step Two:
 I will go to build.gradle(app) in the default config and add this code:

Step Three:
 I will rebuild the project.

Step Four:
 Now I can use the api_key in the app easily.
Gradle wrapper file
What is the Gradle Wrapper?
 The Gradle wrapper (gradlew) is a small application included in the
source code that downloads and launches Gradle, making build
execution easier.

 If you open the Gradle folder, you will find a folder for the
wrapper. This folder contains two files:
 First : gradle-wrapper.jar
 This is a Java Archive (JAR) file that contains the logic
required to download the Gradle distribution.

What is Gradle Distribution?


 It is a collection of versions of the Gradle build tool that will
be downloaded and executed to run Gradle commands.
 Each distribution contains the files needed during runtime,
such as libraries, scripts, and other resources.

 Second: gradle-wrapper.properties
 This is a file that contains a set of properties which we will
discuss now.
 The property specifies the path to the base directory where the
Gradle distribution will be stored:

GRADLE_USER_HOME
 This points to the same path, which in Windows is typically:

% userprofile % \.gradle --> C:\users\username\.gradle

This is a relative path for the distributionBase, which specifies


where the Gradle distribution will be downloaded:
C:\users\username\.gradle\wrap per\dists

 This is the most important property; initially, it checks whether


this version of Gradle exists. If it exists, it won’t download it. If it
doesn’t exist, it will download it from the URL specified in the
property.

 This is similar to distributionBase as it defines the base directory


where the zip files are stored.

 This is similar to distributionPath, as it is relative to


the zipStoreBase and also specifies where the Gradle zip files will
be downloaded:

c:\users\username\.gradle\wrap per\dists
 Now, let's understand what happens when I run the
app, in order:
1- Gradle Starts the Build Process
 Initially, ./gradlew (the Gradle wrapper) is invoked.
 Gradle reads the configuration from the build.gradle file and
determines the tasks to be executed based on the build type
(whether it is debug or release).
2- Dependency Resolution
 Gradle checks and resolves the dependencies specified in
the build.gradle file, downloading any necessary libraries or
modules from the repositories defined in settings.gradle.
3- Compilation Tasks
 Gradle initiates the compile tasks for the project; then, the
compiler compiles the source code and converts it to bytecode.

The remaining steps were discussed in detail earlier


until the user can use the app.
 How to Migrate Gradle Groovy to
Gradle kotlin DSL
 There are two versions of Gradle: Groovy and Kotlin.
 Now I want to convert Gradle from Groovy to Kotlin:
Step One: I will change the names of the Gradle files:
- build.gradle(app) --> build.gradle.kts
- build.gradle(project) --> build.gradle.kts
- settings.gradle --> settings.gradle.kts
Step Two: Now I will start the migration.
 First: In Groovy, I can use single quotes and double quotes,
while in Kotlin, I use only double quotes.
 For example, I will change the plugin format from this:

 To this format:

 The same applies to all strings in the Gradle files.


 Seocnd: Convert the attributes written in Groovy to functions by
adding parentheses like this:

 Third: Convert the fields in Groovy to variables:


 From this format (Groovy):
 To this format (Kotlin):

 Forth: For the Build Types, I can't use the name of the buildType
directly; instead, we will use the getByName() method.
 From this format (Groovy):

 To this format (Kotlin):


Gradle Catalogs
 What is the benefit of Gradle Catalogs?
 When I have multiple modules in my project, there are many
repeated elements in the Gradle file. If I need to perform an
update, such as updating the versions of the libraries, I would have
to change each of the modules. That’s why we use Gradle
Catalogs.
 Any library has three parts, like this:

androidx.core :core-ktx :1.8.0


group name version
 Also, plugins consist of two parts:

id("com.example.mycustomplugin") version "0.1.0"


id version

 Now, if I create a new project, the catalogs will be


available, but if I have an old project and want to refactor
it to use the catalog, how can I do that?
 Step One:
Make the project visible in the project view.
Go to Gradle and create a new file named libs.versions.toml.
 Step Two:
The file will be divided into three sections.
 Step Three:
Assuming I have a library structured as follows:

In the catalogs file, we’ll write in the relevant section like this:

 Now I can use the library directly via the TOML like this.

 Step Four:
If I have a plugin structured like this:

I will do the same as I did with the library and add the plugin under
its corresponding section.
This way, I can use the plugin directly via the TOML.

 This means that if I need to make updates, instead of updating in


every module, I will only do it in one place.

 Step Fifth:

If I want to apply the same logic with the variables found in Gradle, I
will do it like this:

After that, I will use them easily in the build.gradle file like this:
Gradle script
 Most of the files we've discussed are Gradle scripts, like for example:
- build.gradle
- settings.gradle
- gradle.properties

 What are Gradle Scripts?


 A Gradle script is a file used in the build configurations of the
project. It usually uses a Domain-Specific Language (DSL), either
Groovy or Kotlin.
 What is a Domain-Specific Language (DSL)?
 It is a specific programming language designed for particular
problems in Android development. It allows programmers to
express tasks, concepts, or functionalities in a concise and
understandable way instead of using a general-purpose
programming language like Java or Kotlin.

 What is the difference between DSL, like Kotlin DSL, and


regular Kotlin?
1-Purpose
- Kotlin DSL is designed for Gradle to build projects, manage
dependencies, and execute tasks.
- Regular Kotlin is a general-purpose programming language
used in various contexts, such as Android app development,
desktop applications, or backend services.
2- Structure & Syntax
- Kotlin DSL uses specific keywords for builds, like plugin
{}, android {}, dependencies {}, and its syntax is more concise
and expressive about build tasks.
- Regular Kotlin follows the standard syntax to define classes,
functions, etc.
3- Context and Execution Environment
- Kotlin DSL is executed within the Gradle build lifecycle,
allowing it to reference Gradle-specific APIs, configurations,
and tasks, enabling direct interaction with the build system.
- Regular Kotlin runs in any Kotlin-compatible environment, like
JVM or Android, and is not limited to build processes; it can
handle a wide range of applications and logic.

 How to Create a Custom Gradle Script:


 Step One: Create a new file.
Make your project visible in the Project View, and create a new
file, say flavors.gradle.
 Step Two: Define your custom task.
Add the code you want to execute, for example, the code related
to flavors like this:
 Step Three: Include the custom script in your build file.
If I have more than one module in the project, instead of writing
this code in each module, I can simply apply the Gradle script I
created in every module like this:

 This is the root of the project, since I created the Gradle script in
the root; I could also place it in the Gradle file itself, but in this
case, I would apply it like this:
Gradle Tasks
 What are Gradle Tasks?
 A Gradle task is a small unit of work written in the Gradle build
script. Each task presents a specific action for execution, like
generating an APK from the project, installing the app on the
emulator, or checking the app's code for issues and suggestions
on how to resolve them. There are many other tasks as well, and I
can make a task depend on another task, as we will see shortly.

 I do not necessarily have to open the project in Android Studio to


execute these tasks; I can run them on the terminal using Bash or
any command prompt.

There are two types of Gradle tasks:

Custom task Built-in tasks


First: Built-in Tasks
 These are ready-made tasks in Android that I can use
directly.
 If I want to see all the available tasks, I will use this
command.

I will find that all available tasks are displayed, and I will
notice that they are divided into several types, with each
type having its specific tasks as follows:
1- Build tasks

These tasks are responsible for compiling and packaging.

For example, the assemble task has the function of building the
APK, and if I’m using flavors, it will generate all available APKs,
whether free, pro, or any other existing flavors.
2- Build Setup tasks
 This usually refers to the tasks that prepare the build
environment or configurations before the project's build
process itself. This may include dependencies,
configurations, and others.

I can create a new project using the command init.


3- Verification tasks

These tasks are responsible for testing, whether unit tests


or instrumented tests.

In this task, lint is responsible for outputting all existing issues in the
project, but in the form of HTML files. If I run this command and
then open the build file under reports, I will find an HTML file that
contains all the issues in the project along with their explanations.

4- Install tasks
These tasks are responsible for deploying and installing the APK.


5- Android tasks

These tasks are specific to Android in general, such as the first


task that displays all the dependencies in the project, the second
task responsible for signing configurations, and the third that
displays all the source sets in the project.

6- Help tasks

These tasks show information about the project.


Second: Custom Tasks
 Now, we can create a specific task that is ours, as we will see
shortly. However, because this topic is important, we will start
with small things first and then discuss the tasks that we might
need while working, which can save us a lot of effort.
 These tasks can be written in the build.gradle files of the
project, and we can make a specific Gradle script for them,
then apply it in the build.gradle to execute it.

 Here's a small task whose only function is to print "hello world." Now,
we want to understand everything in this code.
 The register function is used to define that a new task will be created
and takes two parameters: the first is the task name, which I specified
to be task1, and the second is the task itself, meaning the action that
will be executed, which is println("hello world").
 When I run it, I will find the output displayed as follows:
 How to Run the Custom Task?
 The custom task can be run via the terminal just as I
would run built-in tasks.

 I can also run it through Android Studio.

Configuration phase Vs Execution phase


First: Configuration Phase
 This occurs when Gradle builds the project. During the
build, registration of all tasks happens, and at that
registration time, the code inside the task executes.
Second: Execution Phase
 This happens when I run a specific task. The code
executed in this phase is the one that is within
the doFirst { } and doLast { }.
To understand this, let’s take a small example:

If I run it, I will find the output appears as follows:


 First: this is task one
This is the main task and is executed when the task is
registered, meaning this indicates it's run as part of the task
configuration phase, not during execution time.
 Second: this is task one inside first
This is because we used doFirst { }. The code written
inside doFirst { } is executed after the main task and before
any other task. This is executed during the execution time,
not during configuration.
 Third: this is task one inside last
This will execute last because we used doLast { }. It executes
after the main task and any other task.
 dependsOn method:
 This method is important in tasks and used widely.
Through it, I specify that a particular task should run
before another task.

 In this code, I specified that for task2 to execute, it must


first execute task1 and then execute task2.

 If I run task2, I will see the output as follows:


task1 should execute first,
This is task two
then task2, but the output
This is task one
displayed the opposite:
 What happened initially was that task2 was registered but not
executed, so it executed the line :
println(“this is task two”)
 Then it registered task1 but did not execute it, so it executed
this line as well :
println("this is task one")
 When it executed the dependsOn { } method, it
executed task1 first, and then task2, thus it indeed
executed task1 first and then task2.
 The "up-to-date" message means that : Gradle
considers task1 and task2 and that neither of their outputs
has changed.
 If there was a change in task1, and I ran task2,
since task2 depends on task1, this means that the change
would reflect on task2 because it will execute task1 first.
 The second task that depends on the first task does not have
to be a custom task; it can simply be a built-in task.

 Now, I want to create a task to make it so that when I


generate the APKs, it places them in a specific folder in the
app called, for example, my_apks.

 Here I specified that there is a certain task of the Copy type


named moveApk. This type has the following methods:

from() —> This is where I specify the path from which to


move the files.

into() —> I specify the path to which the files will be


moved.
- If I run the assemble task, it will first execute
the assemble task, and then it will execute the moveApk task,
and this is the benefit of the finalizedBy { } method, as I can
specify that a certain task will execute last after another task,
and I will find the APK moved to a new folder.

You might also like