Setting Up Project Configuration
1. Configuring build.gradle Files
| File | Location | Content |
|---|---|---|
| build.gradle (Module: app) | app/build.gradle |
|
| build.gradle (Project) | build.gradle |
|
Example: Adding a dependency
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
}
2. Setting Kotlin Version and Compiler Options
| Option | Values | Description |
|---|---|---|
| kotlin_version | 1.9.23 |
Version of Kotlin to use in the project |
| kotlin.compiler.languageVersion | 1.9 |
Language version for the Kotlin compiler |
| kotlin.compiler.apiVersion | 1.9 |
API version for the Kotlin compiler |
| kotlin.compiler.jvmTarget | 17 |
Target JVM version for compiled bytecode |
Example: Gradle Configuration
android {
compileSdk 34
defaultConfig {
targetSdk 34
minSdk 21
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
languageVersion = "1.9"
apiVersion = "1.9"
}
}
Note: Ensure that the
kotlin_version in your build.gradle matches the version specified in your project's gradle.properties.Warning: Using a
jvmTarget lower than the required version may lead to runtime errors or missing features.3. Configuring Android SDK Versions
| Property | Value | Description |
|---|---|---|
| compileSdk | 34 |
SDK version used to compile the app |
| targetSdk | 34 |
SDK version the app is targeting |
| minSdk | 21 |
Minimum SDK version the app supports |
Example: build.gradle.kts (app level)
android {
compileSdk = 34
defaultConfig {
applicationId = "com.example.myapp"
minSdk = 21
targetSdk = 34
versionCode = 1
versionName = "1.0"
}
}
Note: Ensure
compileSdk and targetSdk are set to the same version for compatibility.4. Setting Up Build Types
| Build Type | Description | Default Properties | Use Case |
|---|---|---|---|
| debug | Used during development. Includes debugging symbols and enables live reload. | debuggable true, minifyEnabled false |
Development and testing with full debugging support. |
| release | Optimized for production. Includes code shrinking and obfuscation. | debuggable false, minifyEnabled true |
Production deployment with optimized performance. |
| staging | Used for internal testing before release. Similar to release but with debug support. |
debuggable true, minifyEnabled true |
Internal testing with optimized code but debug support. |
Example: Configuring Build Types in build.gradle.kts
android {<br> buildTypes {<br> debug {<br> isDebuggable = true<br> isMinifyEnabled = false<br> }<br> release {<br> isDebuggable = false<br> isMinifyEnabled = true<br> proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")<br> }<br> staging {<br> isDebuggable = true<br> isMinifyEnabled = true<br> proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")<br> }<br> }<br> }
Note: Build types can be customized further with
buildConfigField or resValue to inject values at compile time.5. Configuring Product Flavors
Product flavors in Android allow you to build different versions of your app with varying features, resources, or code. They are defined in the build.gradle file and enable you to maintain a single codebase while creating multiple variants of your app.
| Flavor Name | Description | Use Case |
|---|---|---|
| free | Basic version with limited features | Free app distribution with ads or basic functionality |
| pro | Full-featured version without ads | Premium app with enhanced features and no advertisements |
Example: Defining Product Flavors
android {
compileSdk 34
defaultConfig {
applicationId "com.example.myapp"
minSdk 21
targetSdk 34
versionCode 1
versionName "1.0"
}
flavorDimensions "version"
productFlavors {
free {
dimension "version"
applicationIdSuffix ".free"
versionNameSuffix "-free"
}
pro {
dimension "version"
applicationIdSuffix ".pro"
versionNameSuffix "-pro"
}
}
}
Example: Adding Flavor-Specific Resources
Flavor-specific resources are placed in src/free/res/ or src/pro/res/. For example, you can have different icons or strings per flavor.
src/free/res/values/strings.xml
<resources>
<string name="app_name">MyApp Free</string>
</resources>
src/pro/res/values/strings.xml
<resources>
<string name="app_name">MyApp Pro</string>
</resources>
Note: Flavor dimensions must be defined before any product flavor. Each flavor must belong to a dimension, and multiple dimensions can be used for more complex configurations.
Key Points
- Product flavors allow building multiple app variants from a single codebase.
- Flavors can have different resources, application IDs, and version names.
- Use
flavorDimensionsto group related flavors. - Flavor-specific code and resources should be placed in
src/<flavorName>/directories.
6. Managing Dependencies
| Dependency | Version | Repository | Description |
|---|---|---|---|
| androidx.core:core-ktx | 1.12.0 |
AndroidX | Core Kotlin extensions for Android |
| androidx.lifecycle:lifecycle-runtime-ktx | 2.7.0 |
AndroidX | Kotlin extensions for Lifecycle |
| com.google.dagger:hilt-android | 2.50 |
Dagger | Dependency injection framework |
| com.squareup.retrofit2:retrofit | 2.9.0 |
Retrofit | Type-safe HTTP client for Android |
| com.github.bumptech.glide:glide | 4.16.0 |
Glide | Image loading and caching library |
Example: Adding Dependencies to build.gradle.kts
dependencies {
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
implementation("com.google.dagger:hilt-android:2.50")
kapt("com.google.dagger:hilt-android-compiler:2.50")
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.github.bumptech.glide:glide:4.16.0")
}
Note: Ensure that
kapt is applied for Hilt compiler in Kotlin projects.
Dependency Management Best Practices
- Use
implementationfor direct dependencies - Use
kaptfor annotation processors like Hilt - Keep versions consistent across modules
- Use
apifor dependencies that need to be exposed to consumers
7. Setting Up ProGuard Rules
Example: Basic ProGuard Configuration
-keep public class com.example.MainActivity {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclassmembers class com.example.model.** {
<fields>;
<methods>;
}
-keepnames class com.example.BuildConfig
| Rule | Description | Usage |
|---|---|---|
| -keep | Prevents class or member from being obfuscated | Use to preserve public APIs |
| -keepclassmembers | Keeps members of a class but allows the class to be obfuscated | Use for internal model classes |
| -keepnames | Prevents renaming of classes but allows obfuscation | Use for BuildConfig or reflection targets |
Note: ProGuard rules are applied during the build process in release builds. Debug builds typically do not use ProGuard.
Warning: Incorrect ProGuard rules can break runtime behavior or cause crashes in release builds.
ProGuard Rule Categories
- API Preservation: Keep public APIs to prevent breaking changes
- Internal Class Protection: Protect internal model classes and their members
- Build Configuration: Preserve BuildConfig and reflection targets
8. Configuring Build Features
| Feature | Description | Configuration | Notes |
|---|---|---|---|
| Build Variants | Define different versions of the app for various environments | buildTypes and productFlavors |
Used for debug, release, staging builds |
| Build Scripts | Customize build logic using Gradle scripts | build.gradle.kts |
Supports Kotlin DSL for configuration |
| ProGuard/R8 | Code shrinking, optimization, and obfuscation | minifyEnabled |
Enabled by default in release builds |
| Instant Run | Fast deployment during development | enable in android |
Deprecated in favor of Apply Changes |
| Build Cache | Speed up builds by caching intermediate results | buildCache |
Available in Gradle 4.1+ |
Example: Build Types Configuration
android {
buildTypes {
debug {
debuggable true
applicationIdSuffix ".debug"
}
release {
isMinifyEnabled = true
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
}
}
}
Example: Product Flavors
android {
flavorDimensions "version"
productFlavors {
free {
dimension "version"
applicationIdSuffix ".free"
}
paid {
dimension "version"
applicationIdSuffix ".paid"
}
}
}
9. Setting Application ID and Version
| Property | Value | Description |
|---|---|---|
| applicationId | com.example.myapp |
Unique identifier for the app in the Android ecosystem |
| versionCode | 1 |
Positive integer used by Google Play to determine app updates |
| versionName | "1.0" |
Human-readable version string displayed to users |
Example: app/build.gradle.kts
android {
namespace = "com.example.myapp"
compileSdk = 34
defaultConfig {
applicationId = "com.example.myapp"
minSdk = 21
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
}
Note: The
versionCode must be incremented with each release, while versionName can be updated to reflect user-facing version information.10. Configuring Signing Configs
| Property | Description | Values |
|---|---|---|
| storeFile | Path to the keystore file | file('path/to/keystore.jks') |
| storePassword | Password to access the keystore | 'your-store-password' |
| keyAlias | Alias of the key in the keystore | 'your-key-alias' |
| keyPassword | Password for the specific key | 'your-key-password' |
Example: Signing Config in build.gradle.kts
android {
signingConfigs {
create("release") {
storeFile = file("path/to/keystore.jks")
storePassword = "your-store-password"
keyAlias = "your-key-alias"
keyPassword = "your-key-password"
}
}
}
Note: Store passwords and key aliases should be kept secure and not hardcoded in version-controlled files.
11. Using Version Catalogs
Version catalogs in Android projects help manage dependency versions centrally, improving maintainability and consistency across the project.
| Property | Value | Description |
|---|---|---|
| libs.versions | 1.0.0 |
Version catalog version used in the project |
| libs.kotlin.stdlib | 1.9.20 |
Kotlin standard library version |
| libs.androidx.core | 1.10.1 |
AndroidX Core library version |
Example: Defining a version catalog in libs.versions.toml
[versions]
kotlin = "1.9.20"
androidx-core = "1.10.1"
[libraries]
kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" }
androidx-core = { group = "androidx.core", name = "core", version.ref = "androidx-core" }
[bundles]
kotlin = [ "kotlin-stdlib" ]
androidx = [ "androidx-core" ]
Example: Using version catalog in build.gradle.kts
plugins {
id("com.android.application") version "8.2.0"
id("org.jetbrains.kotlin.android") version "1.9.20"
}
dependencies {
implementation(libs.kotlin.stdlib)
implementation(libs.androidx.core)
}
Note: Version catalogs are supported starting from Gradle 8.0 and Android Gradle Plugin 8.0.
12. Configuring Compose Compiler
| Option | Values | Notes |
|---|---|---|
| compose.compiler | androidx.compose.compiler:compiler |
Gradle plugin for Jetpack Compose compiler |
| kotlinOptions | androidx.compose.compiler:compiler |
Used in build.gradle.kts to configure Compose compiler options |
Example: Configuring Compose Compiler in build.gradle.kts
android {
compileSdk = 34
defaultConfig {
applicationId = "com.example.myapp"
minSdk = 21
targetSdk = 34
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.1"
}
}
Note: Ensure that the
kotlinCompilerExtensionVersion matches the version of Compose you are using.
Warning: Using an outdated version of the Compose compiler can lead to build failures or runtime issues.