How to Configure Android Build System?

Feyza Ürkut
Huawei Developers
Published in
6 min readJun 27, 2024
Photo by Eilis Garvey on Unsplash

Introduction

In this article, I will discuss the indispensable elements of modern software development processes: software configuration management and build tools. You will find examples of these technologies, which are currently preferred in the Android build system, in this article.

Happy reading!

1- DSL (Domain Specific Language)

2- Version Catalogs

3- Usage of Version Catalogs for HMS Integration

4- KAPT to KSP

Software Configuration Management

Software configuration management encompasses the methods and tools used to manage version control, change management, and configuration information of a software project’s source code, documentation, and other related assets. This ensures that teams can work in an organized and coordinated manner, even on complex projects.

Build Tools

Build tools come into play during the process of converting source code into an executable form and automate this process. Well-configured build tools ensure that the software is correctly compiled, tested, and deployed, thereby increasing developers’ productivity and reducing the likelihood of errors.

1- Configuration with DSL (Domain Specific Language):

  • Groovy DSL: Configuration files written in the Groovy language, used in tools like Gradle.
  • Kotlin DSL: Configuration files written in the Kotlin language, used in tools like Gradle.

2- Dependency Management:

  • Version Catalogs: A configuration method that allows project dependencies to be defined in a centralized location.

3- Build-time Processing and Tools:

  • KAPT (Kotlin Annotation Processing Tool): A tool in Kotlin that performs the same function as Java Annotation Processing.
  • KSP (Kotlin Symbol Processing): A build-time processing tool specifically designed for Kotlin, offering faster and more efficient processing.

1- DSL (Domain Specific Language)

DSL (Domain Specific Language) is a specialized type of language optimized for a specific domain or problem.

1- Groovy DSL

Groovy DSLs are domain-specific languages created using the Groovy programming language. Groovy is a dynamic language that runs on the Java Virtual Machine (JVM) and has features that make it highly suitable for writing DSLs.

// build.gradle file(Gradle configuration using Groovy DSL)
plugins {
id 'java'
}

repositories {
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

2- Kotlin DSL

Kotlin DSLs are domain-specific languages created using the Kotlin programming language. Kotlin is a modern, statically-typed JVM language that offers powerful features for writing DSLs. Build tools like Gradle now support Kotlin DSL for configuration files.

// build.gradle.kts file (Gradle configuration using Kotlin DSL)
plugins {
kotlin("jvm") version "1.5.21"
}

repositories {
mavenCentral()
}

dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib")
testImplementation("org.jetbrains.kotlin:kotlin-test")
}

After introducing these two technologies, you can see that in the latest version of Android Studio Koala, it recommends using Kotlin DSL.

Selection of Build Configuration Language

📌 Script file naming

Script file extension names are based on the language the build file is written in:

  • Gradle build files written in Groovy use the .gradle file name extension.
  • Gradle build files written in Kotlin use the .gradle.kts file name extension.

📌 Add parentheses to method calls

Groovy lets you to omit parentheses in method calls, while Kotlin requires them. To migrate your configuration, add parentheses to these sorts of method calls.

This code shows how to configure a setting in Groovy:

compileSdkVersion 30

This is the same code written in Kotlin:

compileSdkVersion(30)

📌 Add = to assignment calls

The Groovy DSL lets you to omit the assignment operator = when assigning properties, whereas Kotlin requires it. This code shows how to assign properties in Groovy:

java {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}

This code shows how to assign properties in Kotlin:

java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

2- Version Catalogs

Version Catalogs introduced with Gradle 7.0 enable centralized definition of project dependencies. This facilitates easier management and sharing of dependency versions.

// gradle/libs.versions.toml file
[versions]
kotlin = "1.5.21"
springBoot = "2.5.3"

[libraries]
kotlinStdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
springBootStarterWeb = { module = "org.springframework.boot:spring-boot-starter-web", version.ref = "springBoot" }
// build.gradle.kts file
plugins {
kotlin("jvm") version libs.versions.kotlin
}
repositories {
mavenCentral()
}
dependencies {
implementation(libs.kotlinStdlib)
implementation(libs.springBootStarterWeb)
}

3- Usage of Version Catalogs for HMS Integration

In this example, we will implement HMS Map Kit and Location Kit by following the steps below.

💫You can find the relevant code pieces below.

  1. build.gradle.kts (project level): Go to buildscript > dependencies and add the AppGallery Connect plugin configuration.
  2. settings.gradle.kts: Configure the Maven repository for HMS Core SDK.
  3. build.gradle.kts (app level): Add build dependencies to dependencies block.
  4. build.gradle.kts (app level): Add the plugin configuration to the plugins block.
  • Let’s specify the dependency and plugins in the libs.versions.toml file:
[versions]
...
agconnect = "1.9.1.300"
agconnect-agcp = "1.7.1.300"
gradle = "8.0.0"
hmsMap = "6.11.0.304"
hmsLocation = "6.12.0.300"

[libraries]
...
agconnect-core = { group = "com.huawei.agconnect", name = "agconnect-core", version.ref = "agconnect" }
agconnect-agcp = { group = "com.huawei.agconnect", name = "agcp", version.ref = "agconnect-agcp" }
tools-gradle = { group = "com.android.tools.build", name = "gradle", version.ref = "gradle" }
hms-map-kit = { group = "com.huawei.hms", name = "maps", version.ref = "hmsMap" }
hms-location-kit = { group = "com.huawei.hms", name = "location", version.ref = "hmsLocation" }

[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
agconnect = { id = "com.huawei.agconnect", version.ref = "agconnect-agcp" }
  • Let’s call the necessary dependencies and plugin in the build.gradle.kts (app level) file (we called it with its id because there was a problem finding the plugin):
plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.jetbrainsKotlinAndroid)
id(libs.plugins.agconnect.get().pluginId)
}

android {
...
}

dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
implementation(libs.agconnect.core)
implementation(libs.hms.location.kit)
implementation(libs.hms.map.kit)
}
  • We provide the relevant AppGallery Connect plugin classpath in the build.gradle.kts (project level) file:
buildscript{
dependencies {
// Add dependencies.
classpath(libs.tools.gradle)
classpath(libs.agconnect.agcp)
}
}
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.androidApplication) apply false
alias(libs.plugins.jetbrainsKotlinAndroid) apply false
}
  • In the settings.gradle.kts file we provide the Maven repository address for the HMS Core SDK:
pluginManagement {
repositories {
google {
content {
includeGroupByRegex("com\\.android.*")
includeGroupByRegex("com\\.google.*")
includeGroupByRegex("androidx.*")
}
}
mavenCentral()
gradlePluginPortal()
maven("https://developer.huawei.com/repo/" )
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven("https://developer.huawei.com/repo/" )
}
}
rootProject.name = "*"
include(":app")

4- KAPT to KSP

KAPT (Kotlin Annotation Processing Tool) performs the same function in Kotlin as Java Annotation Processing (APT). On the other hand, KSP (Kotlin Symbol Processing) offers better performance and more efficient utilization of Kotlin’s features.

⭐Specifically designed for Kotlin, KSP is faster and more efficient compared to KAPT.

// build.gradle.kts file (Using KAPT)
plugins {
kotlin("jvm") version "1.5.21"
kotlin("kapt") version "1.5.21"
}
dependencies {
implementation("com.google.dagger:dagger:2.37")
kapt("com.google.dagger:dagger-compiler:2.37")
}
// build.gradle.kts file (Using KSP)
plugins {
kotlin("jvm") version "1.5.21"
}
dependencies {
implementation("com.google.dagger:dagger:2.37")
ksp("com.google.dagger:dagger-compiler:2.37")
}

Conclusion

Software configuration management and build tools play a critical role in quality, efficiency, and sustainability within modern software development processes. Their proper and effective use ensures successful project completion and facilitates easier maintenance processes.

By employing these methods correctly and effectively, we can automate and optimize gradle processes in our projects.

Until next time in new writings!

References

--

--