Module 03: Project Structure & Gradle Build System
Objective: Gain a deep understanding of Android project file organization and the Gradle build system, and be able to independently read and modify project configuration.
Comparison with Frontend Project Structure
Let's start with a side-by-side overview to build intuition:
Frontend Project (React/Vue) Android Project
├── package.json ├── build.gradle (project-level)
├── tsconfig.json ├── settings.gradle
├── .env / .env.local ├── gradle.properties
├── node_modules/ ├── .gradle/ (build cache)
├── public/ ├── app/ (main module)
│ ├── index.html │ ├── build.gradle (module-level)
│ └── favicon.ico │ ├── src/
├── src/ │ │ ├── main/
│ ├── main.ts │ │ │ ├── AndroidManifest.xml
│ ├── App.tsx │ │ │ ├── java/ (source code)
│ ├── components/ │ │ │ ├── res/ (resource files)
│ ├── pages/ │ │ │ └── assets/
│ ├── styles/ │ │ ├── test/ (unit tests)
│ ├── utils/ │ │ └── androidTest/ (instrumented tests)
│ └── assets/ │ └── proguard-rules.pro
├── dist/ / build/ └── build/ (build output)
├── vite.config.ts
└── webpack.config.js1. Directory Structure in Detail
1.1 Project Root Directory
MyApp/
├── .gradle/ # Gradle cache (similar to node_modules/.cache)
├── .idea/ # Android Studio config (similar to .vscode/)
├── app/ # Main module (similar to src/ in frontend projects)
├── build/ # Build output (similar to dist/)
├── gradle/ # Gradle Wrapper files
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties # ⭐ Locks the Gradle version
├── build.gradle # Project-level build config
├── settings.gradle # Module declarations
├── gradle.properties # Gradle global properties
├── local.properties # Local environment config (SDK path, not committed to Git)
├── gradlew # Gradle Wrapper script (Unix)
├── gradlew.bat # Gradle Wrapper script (Windows)
└── proguard-rules.pro # Code obfuscation rules1.2 The app Module Directory (Key Focus)
app/
├── build.gradle # ⭐ Module-level build config (most frequently edited)
├── proguard-rules.pro # Obfuscation rules
└── src/
├── main/ # Main source code
│ ├── AndroidManifest.xml # ⭐ App manifest file
│ ├── java/ # Java source code
│ │ └── com/example/myapp/
│ │ ├── MainActivity.java
│ │ ├── model/ # Data models
│ │ ├── network/ # Network requests
│ │ ├── adapter/ # List adapters
│ │ ├── fragment/ # Fragment screens
│ │ ├── activity/ # Activity screens
│ │ └── util/ # Utility classes
│ ├── res/ # ⭐ Resource files
│ │ ├── layout/ # XML layout files (similar to HTML templates)
│ │ ├── values/ # Strings, colors, dimensions, styles
│ │ ├── drawable/ # Images, shapes, selectors
│ │ ├── mipmap/ # App icons
│ │ ├── menu/ # Menu definitions
│ │ ├── anim/ # Animation definitions
│ │ ├── xml/ # XML config files
│ │ ├── raw/ # Raw resource files
│ │ └── navigation/ # Navigation graphs (Jetpack Navigation)
│ └── assets/ # Raw assets (not compiled, bundled as-is)
├── test/ # Unit tests (run on JVM)
│ └── java/
└── androidTest/ # Instrumented tests (require an Android device)
└── java/1.3 Multi-Module Projects
Large legacy projects often have multiple modules (similar to a frontend monorepo):
MyApp/
├── settings.gradle # Declares all modules
├── app/ # Main app module
├── library-core/ # Core library module
├── library-network/ # Network library module
├── library-ui/ # UI component library module
└── feature-login/ # Login feature module// settings.gradle
include ':app'
include ':library-core'
include ':library-network'
include ':library-ui'
include ':feature-login'2. AndroidManifest.xml
This is the "ID card" and "routing table" of an Android app, similar to index.html + route configuration in a frontend project.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<!-- Permission declarations (similar to browser permission requests) -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<!-- Global app configuration -->
<application
android:name=".MyApplication" <!-- Custom Application class -->
android:icon="@mipmap/ic_launcher" <!-- App icon -->
android:label="@string/app_name" <!-- App name -->
android:theme="@style/Theme.MyApp" <!-- Global theme -->
android:allowBackup="true"
android:supportsRtl="true">
<!-- Activity declaration (similar to route registration) -->
<activity
android:name=".MainActivity"
android:exported="true"> <!-- Allow external launch -->
<intent-filter>
<!-- Mark as launcher entry point (similar to the homepage) -->
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Other Activities -->
<activity android:name=".LoginActivity" />
<activity android:name=".SettingsActivity" />
<!-- Service declaration -->
<service android:name=".service.SyncService" />
<!-- BroadcastReceiver declaration -->
<receiver android:name=".receiver.NetworkReceiver" />
<!-- ContentProvider declaration -->
<provider
android:name=".provider.DataProvider"
android:authorities="com.example.myapp.provider" />
<!-- meta-data: Pass extra configuration to components -->
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="your_api_key" />
</application>
</manifest>The Four Core Components
The AndroidManifest registers the four core components, which form the backbone of an Android app:
| Component | Purpose | Frontend Equivalent |
|---|---|---|
| Activity | A single screen/page | A route page (/home, /login) |
| Service | Long-running background task | Web Worker / Service Worker |
| BroadcastReceiver | Listens for system or app events | window.addEventListener |
| ContentProvider | Cross-app data sharing | REST API / IndexedDB |
When taking over a legacy project: Start with AndroidManifest.xml -- it tells you what screens the app has, what permissions it uses, and what background services exist.
2.2 Manifest Merger
When a project contains multiple modules or library dependencies, each may have its own AndroidManifest.xml. At build time Gradle merges them into a final manifest:
app/src/main/AndroidManifest.xml
library-core/src/main/AndroidManifest.xml
Library A's AndroidManifest.xml
↓
Manifest Merger
↓
app/build/intermediates/merged_manifest/...Common merge conflicts:
| Conflict | Cause | Fix |
|---|---|---|
android:allowBackup conflict | Different values in multiple modules | Override in app's manifest with tools:replace="android:allowBackup" |
| Duplicate permissions | Same permission declared by multiple libraries | Usually auto-deduplicated; use tools:node="remove" if needed |
android:exported conflict | Inconsistent export attribute | Explicitly override in app's manifest |
<application
android:allowBackup="false"
tools:replace="android:allowBackup">
<!-- Explicitly override the library's allowBackup setting -->
</application>Debugging tip: The merged manifest is at
app/build/intermediates/merged_manifest/...— check there first when issues arise.
3. Gradle Build System
3.1 What Is Gradle?
Gradle is Android's build tool, equivalent to npm + webpack/vite combined in the frontend world:
| Gradle Feature | Frontend Equivalent |
|---|---|
| Dependency management | npm install / package.json |
| Compiling Java code | tsc (TypeScript compilation) |
| Packaging APK | npm run build |
| Running tests | npm test |
| Code signing | (deployment pipeline) |
3.2 Gradle Wrapper
# gradle/wrapper/gradle-wrapper.properties
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/distsSimilar to
.nvmrcor theenginesfield in frontend: ensures the team uses the same Gradle version.
Important: Don't casually change the Gradle Wrapper version! Legacy projects may depend on a specific Gradle version.
3.3 settings.gradle
// settings.gradle (Groovy DSL, common in legacy projects)
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "MyApp"
include ':app'// settings.gradle.kts (Kotlin DSL, common in newer projects)
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "MyApp"
include(":app")3.4 Project-Level build.gradle
// build.gradle (project root directory)
// Configure plugins shared by all modules here
plugins {
id 'com.android.application' version '8.2.0' apply false
id 'com.android.library' version '8.2.0' apply false
}3.5 Module-Level build.gradle (Most Important!)
This is the file you'll modify most often, equivalent to a module's package.json + tsconfig.json:
// app/build.gradle
plugins {
id 'com.android.application'
}
android {
namespace 'com.example.myapp'
compileSdk 34 // Compile target API level
defaultConfig {
applicationId "com.example.myapp" // App unique identifier (package name)
minSdk 24 // Minimum supported version
targetSdk 34 // Target runtime version
versionCode 1 // Version code (integer, used by app stores)
versionName "1.0.0" // Version name (string, shown to users)
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
// Build types (similar to .env.development / .env.production in frontend)
buildTypes {
release {
minifyEnabled true // Enable code obfuscation/shrinking
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
'proguard-rules.pro'
signingConfig signingConfigs.debug // Signing configuration
}
debug {
minifyEnabled false
debuggable true
applicationIdSuffix ".debug" // Debug package name suffix
}
}
// Flavor dimensions (e.g., free vs. paid, domestic vs. international)
flavorDimensions "version"
productFlavors {
free {
dimension "version"
applicationIdSuffix ".free"
}
paid {
dimension "version"
applicationIdSuffix ".paid"
}
}
// Java compile options
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
// View binding (replaces findViewById)
buildFeatures {
viewBinding true
}
// Resource shrinking
buildTypes {
release {
shrinkResources true
}
}
// Source sets: different build types / flavors can have independent code and resources
sourceSets {
main {
java.srcDirs = ['src/main/java']
res.srcDirs = ['src/main/res']
}
debug {
// src/debug/java and src/debug/res are recognized automatically
}
}
}
// Dependencies (similar to dependencies in package.json)
dependencies {
// AndroidX core libraries
implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
// Jetpack components
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.7.0'
implementation 'androidx.lifecycle:lifecycle-livedata:2.7.0'
implementation 'androidx.navigation:navigation-fragment:2.7.6'
implementation 'androidx.navigation:navigation-ui:2.7.6'
implementation 'androidx.room:room-runtime:2.6.1'
// Networking
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.12.0'
// Image loading
implementation 'com.github.bumptech.glide:glide:4.16.0'
// JSON parsing
implementation 'com.google.code.gson:gson:2.10.1'
// Common dependencies in legacy projects
implementation 'com.jakewharton:butterknife:10.2.3' // View binding (legacy)
// Test dependencies
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.mockito:mockito-core:5.8.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}Build Variants and Source Sets
Combining buildTypes and productFlavors, Gradle generates all possible build variants:
buildTypes: debug, release
productFlavors: free, paid
Generated variants:
- freeDebug
- freeRelease
- paidDebug
- paidReleaseEach variant can have its own source directory:
app/src/
├── main/ # shared by all variants
├── debug/ # debug variant only
├── release/ # release variant only
├── free/ # free flavor only
├── paid/ # paid flavor only
├── freeDebug/ # free + debug combination only
└── paidRelease/ # paid + release combination only// src/debug/java/com/example/myapp/Config.java
public class Config {
public static final String API_BASE_URL = "https://api-staging.example.com";
}
// src/release/java/com/example/myapp/Config.java
public class Config {
public static final String API_BASE_URL = "https://api.example.com";
}Frontend analogy: Similar to
.env.developmentand.env.production, but more powerful — you can replace entire classes or resource files.
3.6 Dependency Configuration Types
| Gradle Config | Meaning | npm Equivalent |
|---|---|---|
implementation | Available at compile time and runtime, not exposed to consumers | dependencies |
api | Same as implementation, but exposed to consumers | No direct equivalent |
compileOnly | Only available at compile time | devDependencies (approximately) |
runtimeOnly | Only available at runtime | No direct equivalent |
testImplementation | Only available for tests | devDependencies (test-related) |
androidTestImplementation | Only available for instrumented tests | devDependencies (E2E tests) |
3.7 Dependency Repositories
repositories {
google() // Google Maven repository (AndroidX, Material)
mavenCentral() // Maven Central (most open-source libraries)
jcenter() // ⚠️ Deprecated, but legacy projects may still use it
maven { url 'https://jitpack.io' } // JitPack (direct GitHub project references)
}3.8 Common Gradle Commands
# Clean build (similar to rm -rf dist/ node_modules/.cache)
./gradlew clean
# Build Debug APK
./gradlew assembleDebug
# Build Release APK
./gradlew assembleRelease
# Install to device
./gradlew installDebug
# Run unit tests
./gradlew test
# Run instrumented tests
./gradlew connectedAndroidTest
# List all available tasks
./gradlew tasks
# View dependency tree (similar to npm ls)
./gradlew app:dependencies
# Profile build time
./gradlew assembleDebug --profile4. Resource System (res/)
Android's resource system is highly structured, similar to a combination of public/ + src/styles/ + src/assets/ in a frontend project.
4.1 res/ Directory Structure
res/
├── layout/ # XML layout files (UI definitions for screens/components)
│ ├── activity_main.xml
│ ├── fragment_home.xml
│ └── item_user.xml # List item layout
├── values/ # Value resources (strings, colors, dimensions, styles)
│ ├── strings.xml # String constants
│ ├── colors.xml # Color definitions
│ ├── dimens.xml # Dimension definitions
│ ├── themes.xml # Theme definitions
│ └── styles.xml # Style definitions
├── drawable/ # Drawable resources
│ ├── ic_home.xml # Vector icon
│ ├── bg_button.xml # Button background shape
│ └── selector_tab.xml # State selector
├── mipmap-xxxhdpi/ # App icons (different resolutions)
├── menu/ # Menu definitions
├── anim/ # Animation definitions
├── xml/ # XML config files
├── raw/ # Raw resources (audio, video, etc.)
└── navigation/ # Navigation graphs4.2 Resource References
Resources are referenced in Java code and XML via the R class:
// The R class is auto-generated and contains IDs for all resources
// Format: R.resourceType.resourceName
// Referencing in Java code
setContentView(R.layout.activity_main); // Reference a layout file
String appName = getString(R.string.app_name); // Reference a string
int color = getColor(R.color.primary); // Reference a color
imageView.setImageResource(R.drawable.ic_home); // Reference an image<!-- Referencing in XML -->
<TextView
android:text="@string/hello_world"
android:textColor="@color/primary"
android:textSize="@dimen/text_size_large"
android:background="@drawable/bg_button" />R.java Generation
At build time, AAPT2 (Android Asset Packaging Tool) scans the res/ directory and generates integer IDs for each resource, aggregating them into the auto-generated R.java:
// Auto-generated, do not modify manually
public final class R {
public static final class layout {
public static final int activity_main = 0x7f030004;
}
public static final class id {
public static final int tv_title = 0x7f080059;
}
public static final class string {
public static final int app_name = 0x7f0b001f;
}
// ...
}Frontend analogy: Similar to Webpack/Vite generating module IDs or
import.meta.globfor asset files.
Common R file errors:
| Error | Cause | Fix |
|---|---|---|
cannot find symbol class R | Resource compilation failed or cache issue | Build → Clean Project / Rebuild |
R.id.xxx not found | Wrong ID or not compiled | Check XML and re-sync |
AAPT: resource not found | Referenced resource doesn't exist | Check resource file names and IDs |
4.3 values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">My App</string>
<string name="hello_world">Hello, World!</string>
<!-- String with parameters -->
<string name="welcome_message">Welcome, %1$s! You have %2$d messages.</string>
<!-- String array -->
<string-array name="week_days">
<item>Monday</item>
<item>Tuesday</item>
<item>Wednesday</item>
</string-array>
</resources>// Usage
String appName = getString(R.string.app_name);
String welcome = getString(R.string.welcome_message, "John", 5);
// -> "Welcome, John! You have 5 messages."
String[] days = getResources().getStringArray(R.array.week_days);4.4 values/colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="primary">#FF6200EE</color>
<color name="primary_dark">#FF3700B3</color>
<color name="accent">#FF03DAC5</color>
<color name="text_primary">#DE000000</color>
<color name="text_secondary">#99000000</color>
<color name="background">#FFFFFFFF</color>
<!-- Color with alpha (AARRGGBB) -->
<color name="overlay">#80000000</color>
</resources>4.5 values/dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- dp: density-independent pixels, for layout dimensions (similar to CSS rem) -->
<dimen name="padding_small">8dp</dimen>
<dimen name="padding_medium">16dp</dimen>
<dimen name="padding_large">24dp</dimen>
<dimen name="button_height">48dp</dimen>
<!-- sp: scale-independent pixels, for font sizes (scales with system font settings) -->
<dimen name="text_size_small">12sp</dimen>
<dimen name="text_size_medium">16sp</dimen>
<dimen name="text_size_large">20sp</dimen>
</resources>Unit Reference:
| Android Unit | Description | CSS Equivalent |
|---|---|---|
dp (density-independent pixel) | Pixel that doesn't change with screen density | rem (approximately) |
sp (scale-independent pixel) | Like dp, but also follows system font size settings | rem (for fonts) |
px | Physical pixels | px (not recommended) |
Rule of thumb: Use
dpfor layout dimensions,spfor font sizes, and never usepx.
4.6 values/themes.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- App theme (similar to CSS :root variables + global styles) -->
<style name="Theme.MyApp" parent="Theme.MaterialComponents.DayNight">
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/primary_dark</item>
<item name="colorAccent">@color/accent</item>
<!-- Status bar color -->
<item name="android:statusBarColor">?attr/colorPrimaryDark</item>
</style>
</resources>5. BuildConfig & Version Management
5.1 BuildConfig
Gradle auto-generates a BuildConfig class containing build configuration info:
// BuildConfig is auto-generated
public final class BuildConfig {
public static final boolean DEBUG = true;
public static final String APPLICATION_ID = "com.example.myapp.debug";
public static final String BUILD_TYPE = "debug";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "1.0.0";
}
// Usage in code
if (BuildConfig.DEBUG) {
Log.d("App", "This is a debug build");
}
String baseUrl = BuildConfig.DEBUG
? "https://api-staging.example.com"
: "https://api.example.com";5.2 Custom BuildConfig Fields
// app/build.gradle
android {
defaultConfig {
buildConfigField "String", "API_BASE_URL", '"https://api.example.com"'
buildConfigField "int", "MAX_RETRY_COUNT", "3"
buildConfigField "boolean", "ENABLE_ANALYTICS", "false"
}
buildTypes {
debug {
buildConfigField "String", "API_BASE_URL", '"https://api-staging.example.com"'
buildConfigField "boolean", "ENABLE_ANALYTICS", "false"
}
release {
buildConfigField "String", "API_BASE_URL", '"https://api.example.com"'
buildConfigField "boolean", "ENABLE_ANALYTICS", "true"
}
}
}6. Signing Configuration
Publishing to the app store requires signing:
// app/build.gradle
android {
signingConfigs {
release {
storeFile file("keystore/release.jks")
storePassword "your_store_password"
keyAlias "your_key_alias"
keyPassword "your_key_password"
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}Security tip: Never commit signing files or passwords to Git. Use
local.propertiesor environment variables to manage sensitive information.
7. ProGuard / R8 Code Obfuscation
# proguard-rules.pro
# Keep all classes that implement Serializable
-keepclassmembers class * implements java.io.Serializable { *; }
# Keep Gson model classes
-keep class com.example.myapp.model.** { *; }
# Keep Retrofit interfaces
-keep,allowobfuscation interface * {
@retrofit2.http.* <methods>;
}
# Keep enums
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}Frontend equivalent: Terser / UglifyJS minification and obfuscation.
8. Gradle Checklist for Taking Over a Legacy Project
When opening a legacy project, check in this order:
gradle-wrapper.properties: Confirm the Gradle version -- don't upgrade casually- Project-level
build.gradle: Confirm the Android Gradle Plugin (AGP) version - Module-level
build.gradle:compileSdk: Compile target versionminSdk: Minimum supported versiontargetSdk: Target runtime versiondependencies: Third-party libraries in use
settings.gradle: Confirm the module structuregradle.properties: Confirm global configuration
AGP and Gradle Version Compatibility Table
| AGP Version | Minimum Gradle Version | Minimum JDK |
|---|---|---|
| 8.2.x | 8.2 | 17 |
| 8.1.x | 8.0 | 17 |
| 8.0.x | 8.0 | 17 |
| 7.4.x | 7.5 | 11 |
| 7.3.x | 7.4 | 11 |
| 7.2.x | 7.3.3 | 11 |
| 7.1.x | 7.2 | 11 |
| 7.0.x | 7.0 | 11 |
| 4.2.x | 6.7.1 | 8 |
| 4.1.x | 6.5 | 8 |
Common Sync Failures and Fixes
| Error Message | Cause | Fix |
|---|---|---|
Could not find com.android.tools.build:gradle:X.X.X | AGP version incompatible with Gradle version | Check the compatibility table above |
Unsupported class file major version XX | JDK version too low | Upgrade JDK |
Could not resolve all files for configuration | Dependency download failed | Check network/mirror configuration |
SDK location not found | SDK path not configured | Check local.properties |
Duplicate class found | Dependency conflict, two libraries contain the same class | Use ./gradlew app:dependencies to investigate and exclude |
Manifest merger failed | Multi-module manifest attribute conflict | Check app/build/intermediates/merged_manifest |
AAPT2 error: check logs for details | Resource file naming or format error | Check res/ file names and XML syntax |
Method count exceeded 64K | Method count exceeds 65,536 | Enable multiDexEnabled true |
# View full dependency tree to investigate conflicts
./gradlew app:dependencies --configuration releaseRuntimeClasspath
# Show only conflicting dependencies
./gradlew app:dependencies --configuration releaseRuntimeClasspath | grep "\->" | sort | uniqFrontend Developer Cheat Sheet
| Frontend Concept | Android Equivalent | Notes |
|---|---|---|
package.json | build.gradle | Dependencies and project config |
npm install | Gradle Sync | Download dependencies |
dependencies | implementation 'group:artifact:version' | Different dependency declaration format |
.env | buildConfigField + BuildConfig | Environment configuration |
index.html | AndroidManifest.xml + activity_main.xml | Entry point definition |
| Route config | <activity> in AndroidManifest.xml | Screen registration |
dist/ | build/outputs/apk/ | Build output |
.nvmrc | gradle-wrapper.properties | Tool version locking |
| CSS variables | values/colors.xml + values/dimens.xml | Global style variables |
@media queries | Resource qualifiers (values-xxhdpi/, etc.) | Adapt to different screens |
public/ | assets/ | Uncompiled raw resources |
| Tree-shaking | R8 / ProGuard | Remove unused code |
Next Steps
Now that you understand the project structure, move on to Module 04: Activity & Fragment to learn about Android's screens and lifecycle.