Android development / Basic: Android and Compose foundations / Lesson 1
Android projects, Studio, and the build toolchain
Trace a small reading-list app from source files to an installed package, and explain which configuration controls compatibility.
On this page
Lesson goals
- Distinguish the IDE, SDK, Gradle wrapper, and Android Gradle plugin.
- Explain SDK settings without confusing compilation with runtime support.
Follow the build pipeline
Android Studio edits, indexes, previews, and debugs a project; Gradle performs its repeatable build. The Android Gradle plugin contributes Android tasks, while the SDK supplies platform APIs and packaging tools. Kotlin source becomes executable code, resources receive identifiers, and the manifest describes entry points. An APK is an installable package; an Android App Bundle is a publishing format from which a distribution service can produce device-specific APKs. Knowing these boundaries helps distinguish an editor warning from an actual compilation or installation failure.
Read the project before editing it
Start with a Studio-generated Compose project using its compatible template versions. settings.gradle.kts defines included modules and repository policy; the root build configures shared plugins; app/build.gradle.kts configures the application module. Kotlin files live under source directories and resources under res. A version catalog may supply plugin and dependency aliases. Keep the wrapper and its configuration in version control so another developer uses the same Gradle distribution. Do not copy an entire build file from an unrelated tutorial into an established project.
android {
namespace = "com.example.reading"
defaultConfig {
applicationId = "com.example.reading"
versionCode = 1
versionName = "1.0"
}
}
This block belongs in app/build.gradle.kts with the template plugins and SDK settings retained. namespace locates generated classes; applicationId identifies the installed app. Changing one does not automatically migrate stored user data.
Separate three SDK decisions
compileSdk determines which platform symbols the compiler can see. minSdk states the oldest supported device API, subject also to library requirements. targetSdk selects compatibility behavior and signals which platform changes the app has addressed; it does not prevent installation on newer Android versions. Choose actual values from the project requirements and the installed compatible toolchain, then consult current distribution rules before release. A successful compilation does not prove that a newer API exists on every supported device: guard calls or use an appropriate AndroidX abstraction.
Connect resources to an entry point
The generated launcher activity is an Android component rather than a normal main function. Its onCreate method attaches a Compose UI through setContent. Resource references let Android choose localized text and alternative assets without scattered conditional logic. Retain the template theme and manifest entry while learning. A preview renders a composable in an IDE environment, which is useful for layout inspection but does not exercise installation, permissions, process recreation, or real networking. Those behaviors require a suitable test environment later in the course.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent { MaterialTheme { Text("Reading list") } }
}
}
Use the generated package and imports for Bundle, ComponentActivity, setContent, MaterialTheme, and Text. The template supplies AndroidX and Compose dependencies. This teaching excerpt omits the surrounding project and is not independently runnable.
Diagnose failures in dependency order
First determine whether the failure occurs during synchronization, compilation, packaging, installation, or launch. Read the first relevant error and its file location instead of treating the final task failure as the cause. Check the wrapper, plugin, Kotlin, JDK, and Compose compiler compatibility together before upgrading a single piece. Separate debug configuration from release signing, and never commit signing secrets. Record the tested toolchain in the project documentation so a future update has a known starting point and can be reviewed as a deliberate change.
Common errors and fixes
Gradle sync cannot resolve a plugin
- Why it happens
- An alias or repository differs from the generated project configuration.
- How to fix it
- Compare settings and the version catalog with the template, then correct the specific coordinate.
- Prevent it next time
- Review dependency changes together and keep reproducible versions.
A feature compiles but crashes on an older device
- Why it happens
- compileSdk was mistaken for a runtime guarantee.
- How to fix it
- Guard the API by device level or use a compatible AndroidX implementation.
- Prevent it next time
- Test the lowest supported API as well as a current target environment.
An update installs as a separate application
- Why it happens
- The applicationId changed between builds.
- How to fix it
- Restore the intended application identity and verify the variant suffix.
- Prevent it next time
- Treat application identity and signing identity as release requirements.
Check your understanding
1. A project compiles against a newer SDK but supports older phones. Explain whether targetSdk alone makes an unguarded new API safe.
Show worked solution
No. The compiler knows the symbol through compileSdk, while the device implements its own API level. Check availability at runtime or use a supported abstraction, and test that branch on the oldest supported configuration. Raising targetSdk also requires reviewing behavior changes independently.
2. A colleague reports that a Compose preview works but the app will not launch. Give a focused investigation sequence.
Show worked solution
Build the intended variant, inspect packaging and installation errors, then inspect the launch crash and manifest activity declaration. Confirm the device satisfies minSdk. Preview success only demonstrates that part of the UI can be rendered by tooling; it does not validate the packaged application or device configuration.
Key takeaways
- The build is a pipeline with distinct failure stages.
- SDK settings describe different compatibility contracts.
- Preserve a known compatible toolchain before experimenting.