About

The gradle build systems allows use to attach and include external binaries or other library modules to our build as dependencies. These dependencies can be located on our PC or from a remote repo like github, and any transit repositories that they require will be automatically included.

To include a dependency into our build, you must specify the dependency inside our build.gradle file.

What are dependencies
Dependencies or libraries are basically precompiled source codes. Have you noticed that when we write our custom classes inside the java folder, we dont need to do anything special at all, however, when we want to use other libraries, often we do not receive them in a .java file, instead it is often in a .jar file.

This is basically the java byte code. In this section we will learn how to add these compiled binaries into our project, and use them. {: .prompt-tip}

Now, when selecting a gradle language, you have the option of either kotlin or grovvy. This guide will show both usecases. Be sure to watch out for the language highlight in the code snippets and infer the synthax differences.




build.gradle(Module: )

Essentially these are the dependancies that we are referring to, they are declared within the build.gradle.kts (or build.gradle for gradle) files:

Kotlin
dependencies {  
    implementation("androidx.appcompat:appcompat:1.6.1")  
    implementation("com.google.android.material:material:1.8.0")  
    implementation("androidx.constraintlayout:constraintlayout:2.1.4")  
    testImplementation("junit:junit:4.13.2")  
    androidTestImplementation("androidx.test.ext:junit:1.1.5")  
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")  
}

Library module dependency

Here's how dependencies work. We declare the library inside the build.gradle.kts,

Kotlin
dependencies {
    // Local Library Module Dependency
    implementation project(":mylibrary")
}

Then we must also declare them inside the settings.gradle.kts, under "include"

Kotlin
pluginManagement {  
    repositories {  
        google()  
        mavenCentral()  
        gradlePluginPortal()  
    }  
}  
dependencyResolutionManagement {  
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)  
    repositories {  
        google()  
        mavenCentral()  
    }  
}  
  
rootProject.name = "Stone Camera"  
include(":app")
include(:"mylibrary")  // Here

Important
When you build your application, the build system compiles the library module and packages that resulting compile will be included in the app. {: .prompt-tip}


Local binary dependency

For local binaries (downloaded .jar files), Gradle declares dependencies on jar files inside your project's libs folder.

Gradle
dependencies {
    // Local Library Module Dependency
    implementation project(":mylibrary")
    
    // Local binary dependency
    implementation fileTree(dir: "libs", includes: ['*.jar'])
    
    // Alternatively, to specify specific files...
    implement files("libs/myFile.jar", "libs/myOtherfile.jar")
}

Remote binary dependency

This will allow gradle to attempt to fetch the files over the internet.

Gradle
dependencies {
    // Local Library Module Dependency
    implementation project(":mylibrary")
    
    // Local binary dependency
    implementation fileTree(dir: "libs", includes: ['*.jar'])
    
    // Alternatively, to specify specific files...
    implement files("libs/myFile.jar", "libs/myOtherfile.jar")
    
    // Remote binary dependencies
    implementation "com.example.android:app-magic:12.3"
}

The way it works is to ask gradle to look for the file named "app-magic", version 12.3 from the group/package "com.example.android". A group dependency like this requires that we decalre the approapriate remote repositories where Gradle should look for the library. If the library doesnt already exist locally, they will be pulled from the remote side when the build requires it.

Groovy or kotlin
A lot of times our gradle build files could be written in groovy or kotlin synthax. This maybe confusing. However its important to take node the general context works like this:
type "argument" this is where a function was redacted; implements "com.somewhere"
type functionName("arguments")
type functionName(kwarg: "argument") {: .prompt-tip}




Practical Demonstration

Using the glide library which is an image loading and caching library for android focused on smooth scrolling, as our example...

The source code is here. So how do we add a github repo project files into our app?

Well, if we scroll down we can see a few examples and documentations:

There are mainly 2 ways to get this library into our project:


Method 1: Use as local binary

The first thing we got to do is to download their .jar files and put in inside our project's libs folder and include it as a local binary:


Method 2: Have Gradle download it from repo

As previously mentioned, we can have gradle to download this files automatically via the "Remote dependency" method.

So lets copy this code from the readme page:

Gradle
repositories {
    google()
    mavenCentral()
}

dependencies {
    implementation 'com.github.bumptech.glide:glide:4.16.0'
}

Into our build.gradle(Project:) gradle, we will often see google and mavenCentral is already preincluded.

Gradle
// Top-level build file where you can add .......
buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle7.0.4"
        
        // NOTE: Do not place your application dependencies here;
        // they belong in the individual build.gradle files
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

Towards our build.gradle(Module:) gradle's dependencies section. We will see these code that has already preincluded in a project template. All wee need to do is to all ours in:

Gradle
dependencies {
    
    implementation "androidx.appcompat:appcompat:1.2.0"
    implementation "con.google.android.material:material:1.3.0"
    implementation "androidx.constraintlayout:constraintlayout:2.1.2"
    testImplementation "junit:junit4.+"
    androidTestImplementation "androidx.test.ext.junit:1.1.2"
    andoridTestImplementation "androidx.test.espresso:espresso-core:3.3.0"
    
    // Our dependencies code goes here
    implementation "com.github.bumptech.glide:glide:4.12.0"
    annotationProcessor "com.github.bumptech.glide:compiler:4.12.0"
}




Modern Gradle outlines & Common errors

In 2023 september, our gradle outlines will look vastly different, first of all, our build.gradle(Project: ) will look like this:

Gradle
// Top-level build file where you can add ......
plugins {  
    id 'com.android.application' version '8.0.2' apply false  
    id 'com.android.library' version '8.0.2' apply false  
}

And the settings.gradle(Project settings) will look like this:

Gradle
pluginManagement {  
    repositories {  
        google()  
        mavenCentral()  
        gradlePluginPortal()  
    }  
}  
dependencyResolutionManagement {  
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)  
    repositories {  
        google()  
        mavenCentral()  
    }  
}  
rootProject.name = "ExampleGlideProject"  
include ':app'

So when adding an external dependencies, we will instead declare the repositories inside the project settings instead, and leave the build.gradle(Project:) untouched.

The dependencies can be added into the build.gradle(Module:) as usual.


Dependencies not fully resolved

This happens from time to time when you have already added the dependencies, yet you still see a missing class error:

You need to make sure you added the repository into your build settings! Read the documentations carefully.

Add these repositories into your settings.gradle(Project settings) file

Gradle
pluginManagement {  
    repositories {  
        google()  
        mavenCentral()  
        gradlePluginPortal()  
        jcenter()  // Add here, usually optional
    }  
}  
dependencyResolutionManagement {  
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)  
    repositories {  
        google()  
        mavenCentral()  
        jcenter()  //Must Add here
    }  
}  
rootProject.name = "ExampleGlideProject"  
include ':app'

Duplicate Class errors

This also happens from time to time when we use external libraries. This conflicts usually comes from The external library using its own version of some class implementations. Details:

The fix:

Add these lines of code inside gradle.properties. Make sure you dont repeat lines already present:

Gradle
android.useAndroidX=true
android.enableJetifier=true

Why it works?:

Your project (or one of its sub-projects, or a dependency) is no longer using android.support libraries and instead is using androidx libraries, which causes conflicts if mixed with android.support libraries.

If you want to use androidx-namespaced libraries in an old project, you need to set the compile SDK to Android 9.0 (API level 28) or higher but below "API level 31", and set both of the mentioned Android Gradle plugin flags to true.

android.useAndroidX: When this flag is set to true, the Android plugin uses the appropriate AndroidX library instead of a Support Library. The flag is false by default if it is not specified.

android.enableJetifier: When this flag is set to true, the Android plugin automatically migrates existing third-party libraries to use AndroidX dependencies by rewriting their binaries. The flag is false by default if it is not specified.