The anatomy of a project
The New Project wizard gave you a running app and about seventeen files you did not write. Most beginners leave them alone and hope, which works until the day a build breaks or a teammate cannot open the project. This lesson walks the Mandi Bhav starter one file at a time: what each one is for, who edits it, and which ones must never go into git.
The whole project on one screen
Switch the Project tool window from the Android view to the Project view (the drop-down at the top of the panel). The Android view regroups files to look tidy; the Project view shows what is really on disk, and it is the one that matches what git sees.
mandi-bhav/
├── settings.gradle.kts which modules exist, where to download from
├── build.gradle.kts root build file: declares plugins, applies none
├── gradle.properties switches for Gradle and the Android plugin
├── gradle/
│ ├── libs.versions.toml the version catalog: every version in one place
│ └── wrapper/
│ ├── gradle-wrapper.jar tiny program that downloads the right Gradle
│ └── gradle-wrapper.properties which Gradle version to download
├── gradlew wrapper script for macOS and Linux
├── gradlew.bat wrapper script for Windows
├── .gitignore
└── app/
├── build.gradle.kts the app module's build: SDK levels, dependencies
├── proguard-rules.pro shrinker rules for release builds
└── src/main/
├── AndroidManifest.xml what the app declares to Android
├── java/com/riztechacademy/mandibhav/
│ └── MainActivity.kt your Kotlin code
└── res/
├── drawable/ic_launcher_foreground.xml
├── mipmap-anydpi/ic_launcher.xml
└── values/
├── colors.xml
└── strings.xml
That is everything committed to the starter repository: seventeen files, about 24 KB of source. Everything else in the folder was made by a tool, and you will meet those at the end.
The project and the module
The first thing to see is that there are two levels. The project is the outer folder. The module is app/, the thing that actually becomes an APK. A real app often grows more modules (a core library, a feature-prices module), and each one gets its own build.gradle.kts and its own src/. Mandi Bhav has one module for now, and that is normal for an app of this size.
settings.gradle.kts
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "Mandi Bhav"
include(":app")
Gradle reads this file first. It answers three questions:
- Where do plugins come from?
pluginManagementlists the repositories Gradle searches for build plugins, such as the Android Gradle Plugin.google()is Google's Maven repository, where everythingandroidxand the Android plugin live.mavenCentral()is the public repository for most other Java and Kotlin libraries. - Where do libraries come from?
dependencyResolutionManagementdoes the same for the libraries your app uses.FAIL_ON_PROJECT_REPOSmeans a module is not allowed to add its own repository; every source of code is declared here, once, where a reviewer will see it. - Which modules exist?
include(":app")is the line that makesapp/part of the build. Add a module folder and forget this line, and Gradle ignores the folder completely.
The root build.gradle.kts
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.compose) apply false
}
Two plugins are declared and neither is applied. apply false means "load this plugin at this version, but do not switch it on here". The root project is not an app, so it has nothing to build; this file exists so that every module uses the same plugin version. The app module then applies them for real.
app/build.gradle.kts
This is the file you will edit most. It says which plugins build this module, its package namespace, the applicationId the Play Store knows it by, the three SDK levels, and the list of libraries. The next lesson takes it apart line by line, so for now notice only its shape: a plugins block, an android { } block for everything Android-specific, and a dependencies { } block.
gradle/libs.versions.toml
The version catalog. Instead of writing "androidx.core:core-ktx:1.19.1" inside the build file, the version is written once here and the build file refers to it by name, libs.androidx.core.ktx. Also covered properly in the next lesson.
The wrapper: gradlew, gradlew.bat and gradle/wrapper/
These four files are how the project runs Gradle without you installing it. gradle-wrapper.properties contains the important line:
distributionUrl=https\://services.gradle.org/distributions/gradle-9.9.0-bin.zip
When you run ./gradlew, the script checks whether Gradle 9.9.0 is already downloaded to your home folder, downloads it if not, and runs it. Everyone on the team, and the CI server, gets exactly the same Gradle. The wrapper files are committed, including the .jar; it looks like a build artefact and it is not.
gradle.properties
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
android.useAndroidX=true
Settings for the build itself, not for the app. The first gives the Gradle process 2 GB of memory; on an 8 GB laptop running an emulator you may need to know that number exists. The second tells the Android plugin the project uses the androidx libraries rather than the old support libraries.
app/src/main/
src/main is a source set: the code and resources used by every version of the app. Later you will meet src/debug/ and src/test/, which sit beside it and add to it for one build type, or for tests.
AndroidManifest.xmltells Android what the app contains and what it needs. It has its own lesson.java/com/riztechacademy/mandibhav/MainActivity.ktis your code. The folder is calledjavafor historical reasons; Kotlin files live there happily, and the folders below it mirror thepackageline at the top of each file. Moving a file without changing its package line still compiles, but it confuses everyone who reads the project.res/is resources: everything that is not code.values/strings.xmlholds the app name,values/colors.xmlholds the icon's green,drawable/holds a vector image (the white triangle in the icon), andmipmap-anydpi/ic_launcher.xmlcombines the two into an adaptive launcher icon. Resources get their own lesson at the end of this module.
app/proguard-rules.pro
Release builds can run through R8, which shrinks and renames your code to make the APK smaller. Some libraries need rules telling R8 what not to rename. The file is empty for now, and the starter's release build has isMinifyEnabled = false, so R8 is not running yet. It matters at the release module.
What the tools generate, and must never be committed
Build once and the folder fills up. The starter's .gitignore already excludes all of it:
| Path | What made it | Why it stays out of git |
|---|---|---|
build/, app/build/ |
Gradle, on every build | Rebuilt from source every time. After one debug build app/build/ was 45 MB, against 24 KB of source. |
.gradle/ |
Gradle | Caches and file locks for this machine. |
.kotlin/ |
The Kotlin compiler | Session data for this machine. |
local.properties |
Android Studio | Holds sdk.dir, the path to your Android SDK. |
.idea/, *.iml |
Android Studio | Your window layout and IDE settings. |
captures/, .cxx/, .externalNativeBuild |
Profiler and native builds | Large, machine-specific output. |
The trap: committing local.properties
local.properties is the one that hurts, because it looks like configuration. Open it:
sdk.dir=/Users/priya/Library/Android/sdk
Suppose Priya commits it. Arjun pulls on his Windows laptop, Android Studio may or may not rewrite it, and his command-line build fails before compiling a line:
* What went wrong:
Could not determine the dependencies of task ':app:compileDebugJavaWithJavac'.
> SDK location not found. Define a valid SDK location with an ANDROID_HOME
environment variable or by setting the sdk.dir path in your project's local
properties file at '.../local.properties'.
There is a second, worse reason. local.properties is the conventional place for things that must not be shared, and later in this course you will be tempted to put an API key in it. Anything machine-specific or secret belongs in an ignored file; everything needed to build belongs in a committed one. If you ever see local.properties in git status, stop and fix the .gitignore before committing.
The same goes for build/. Committing it does not break anything at first. It makes every clone slow, makes every pull request a wall of binary noise, and causes merge conflicts in files nobody wrote.
Check your work
What is the difference between the project and the module? The project is the whole folder and build; the module (app/) is one buildable unit that becomes an APK. A project can have many modules.
What does include(":app") do? It adds the app/ folder to the build. Without it, Gradle ignores the folder.
Why does the root build file say apply false? It fixes the plugin versions for every module without applying them to the root project, which builds nothing.
Which file decides the Gradle version? gradle/wrapper/gradle-wrapper.properties, through distributionUrl.
Is gradle-wrapper.jar committed? Yes. It is part of the wrapper, not a build output.
Why is Kotlin code in a folder called java? Historical naming; the source set folder works for both languages.
Why must local.properties stay out of git? It holds a path that is only valid on your machine, and it is where secrets tend to end up.
Practice
- Switch between the Android and Project views. Find one file that the Android view shows in a different place from where it really is.
- Run
git statusin your project after a build. Confirm that none of the generated paths in the table appear. - Open
gradle-wrapper.propertiesand find the Gradle version. Then find the Android Gradle Plugin version inlibs.versions.toml. They are different numbers for different tools. - Run
du -sh app/build app/src(macOS or Linux) and compare the two sizes. That ratio is whybuild/is ignored. - Break it on purpose: comment out
include(":app")insettings.gradle.ktsand run./gradlew assembleDebug. Gradle reportsTask 'assembleDebug' not found in root project 'Mandi Bhav': with the module gone, nothing in the build knows how to make an APK. Restore the line. - Harder: copy
local.propertiesaside, changesdk.dirto a path that does not exist, and run./gradlew assembleDebug. You should see the "SDK location not found" error above. Restore the file. Now explain to a teammate, in two sentences, why that file is in.gitignore.
Official documentation
- Android Developers — Projects overview — The official tour of modules, source sets and the project structure, including module types this course does not use yet.
- Android Developers — Gradle build overview — How settings, root and module build files fit together.
- Git — gitignore — The pattern rules behind lines like
/app/buildand.gradle.
Next: Gradle itself, the version catalog, and the build variants that let one project produce a debug and a release app.
Stuck on this lesson?
Being stuck is part of it — but being stuck alone for three days is not. Selected students who finish a course can join our internship, with real-world projects and code review from a working engineer.
About the internship