Android projects and activities
How a Gradle project is laid out, what the manifest declares, and how an activity moves through its lifecycle.
The files that matter
An Android app is a Gradle project. The root build file configures the build for every module; the app module is the one that produces your APK or App Bundle.
| Path | What lives there |
|---|---|
settings.gradle.kts | Which modules are part of the build |
build.gradle.kts (root) | Plugin versions, shared repositories |
app/build.gradle.kts | compileSdk, minSdk, targetSdk, dependencies |
app/src/main/java/ | Kotlin sources, folders mirror the package name |
app/src/main/res/ | layouts, strings, drawables, themes |
app/src/main/AndroidManifest.xml | Components, permissions, app metadata |
app/src/test/ and app/src/androidTest/ | JVM unit tests and on-device instrumented tests |
Two SDK numbers decide what you can use and who can install the app: minSdk is the oldest Android version you support, compileSdk is the API level you compile against. They are independent, and raising minSdk shrinks your audience.
The manifest and the launcher activity
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:label="@string/app_name"
android:theme="@style/Theme.MyApp">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>- The
MAIN/LAUNCHERintent filter is what puts an icon on the home screen. Exactly one activity should normally carry it. android:exportedis mandatory whenever a component has an intent filter on Android 12 and above:truelets other apps start it.- Every component you add (activity, service, receiver, provider) must be declared here, or the system will not know it exists.
The activity lifecycle
An activity is created and destroyed by the system, not by your code. Configuration changes such as rotation destroy and recreate it, so anything you want to survive must be kept outside the instance.
| Callback | Called when | Typical use |
|---|---|---|
onCreate | Activity is created | Inflate the UI, bind state, restore saved state |
onStart / onStop | It becomes visible / is hidden | Start or stop observers, analytics |
onResume / onPause | It gains / loses focus | Resume or pause media, sensors, animations |
onDestroy | It is finishing or being recreated | Release bindings and long-lived references |
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val startCount = savedInstanceState?.getInt("count") ?: 0
setContent { AppScreen(initial = startCount) }
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putInt("count", 3)
}
}FAQ
What is the difference between minSdk and targetSdk?
Why did my state disappear when I rotated the device?
onSaveInstanceState for small, transient values.Related
Layouts and Jetpack Compose Permissions, storage and publishing
Last refreshed 2026-09-18.