Android Studio — Complete Guide for Beginners
In this tutorial, you'll learn about Android Studio. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
Android Studio is the official IDE for Android apps with a Gradle build system, visual layout editor, emulator, and profiling tools in one package.
In this tutorial, you will learn how to install Android Studio, create your first Android project with Kotlin and Jetpack Compose, configure the emulator, use the debugger and Logcat, manage dependencies with Gradle, run performance tests with the Profiler, and prepare your app for Google Play Store submission. These are the same workflows DodaTech uses to build mobile versions of Doda Browser and Durga Antivirus Pro for Android — mastering Android Studio gives you complete control over the full app lifecycle. We'll draw parallels with Python and JavaScript ecosystems throughout.
What You'll Learn
By the end of this guide, you will know how to create an Android project from scratch, design UIs with Jetpack Compose, run and debug apps on the emulator and physical devices, inspect network traffic and memory usage with the Profiler, and generate a signed APK or App Bundle for distribution.
Why Android Studio Matters
Android powers over 70% of mobile devices worldwide. Android Studio is the only officially supported IDE for the platform, and it provides deep integration with the Android SDK, build tools, and Google services. Its Gradle build system handles dependency management, multi-module projects, and variant-specific configurations (debug, release, staging). The Layout Inspector and Profiler help you diagnose UI jank and memory leaks before they reach users. For security tools like Durga Antivirus Pro, the Profiler is critical for ensuring background scanning services do not drain battery or consume excessive memory.
Learning Path
flowchart LR
A[Installation & SDK Setup] --> B[First Project with Jetpack Compose]
B --> C[Emulator & Device Testing]
C --> D[Debugging & Logcat]
D --> E{You Are Here}
E --> F[Profiler & Performance]
E --> G[Play Store Deployment]
style E fill:#f90,color:#fff
Installation and SDK Setup
Download Android Studio from developer.android.com/studio. The installer includes the Android SDK, emulator, and build tools. During installation, choose Standard setup — it installs the latest SDK for the most common API levels.
SDK Manager
Open Tools → SDK Manager. Here you manage API levels, build tools, and system images:
| Component | Purpose | Recommended Version |
|---|---|---|
| Android SDK Platform | API level for compilation | Latest stable (API 35) |
| Intel x86 Atom System Image | Emulator image | API 35 with Google Play |
| Android SDK Build-Tools | APK signing and packaging | Latest |
| Android Emulator | Virtual device testing | Latest |
| Android SDK Platform-Tools | ADB and fastboot | Latest |
Ensure Android_HOME is set in your environment variables:
# Add to ~/.zshrc or ~/.bashrc
export ANDROID_HOME=$HOME/Android/Sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
Creating Your First Android Project
Click File → New → New Project. Choose Empty Views Activity (Jetpack Compose):
| Setting | Recommended Value | Purpose |
|---|---|---|
| Name | MyFirstApp |
App display name |
| Package name | com.example.myfirstapp |
Unique identifier for Play Store |
| Save location | ~/AndroidStudioProjects |
Project root |
| Language | Kotlin | Modern, concise, Google-preferred |
| Minimum SDK | API 24 (Android 7.0) | Covers 95%+ of active devices |
Android Studio generates the project with MainActivity.kt, activity_main.xml (or Composable functions for Compose), and build.gradle.kts files.
Project Structure
| File/Directory | Purpose |
|---|---|
app/src/main/java/ |
Kotlin source code |
app/src/main/res/ |
Resources: layouts, drawables, strings |
app/build.gradle.kts |
Module-level build configuration |
build.gradle.kts |
Project-level build configuration |
settings.gradle.kts |
Module inclusion and Repository config |
gradle.properties |
JVM args and project-wide Gradle settings |
Building User Interfaces with Jetpack Compose
Jetpack Compose is Android's modern declarative UI toolkit. You describe your UI in Kotlin functions annotated with @Composable.
// MainActivity.kt — Hello World with Compose
package com.example.myfirstapp
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
Greeting("Android Studio")
}
}
}
}
@Composable
fun Greeting(name: String) {
var count by remember { mutableStateOf(0) }
Column(
modifier = Modifier.fillMaxSize().padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "Hello, $name!",
style = MaterialTheme.typography.headlineLarge
)
Spacer(modifier = Modifier.height(16.dp))
Text("Button pressed $count times")
Spacer(modifier = Modifier.height(8.dp))
Button(onClick = { count++ }) {
Text("Tap me")
}
}
}
Expected output on emulator:
- Centered "Hello, Android Studio!" in large text
- "Button pressed 0 times"
- Tapping the button increments the counter
- Material 3 theming with default colors and rounded corners
Preview in Android Studio
Add the @Preview annotation above Greeting to see a live preview panel:
@Preview(showBackground = true, showSystemUi = true)
@Composable
fun GreetingPreview() {
MaterialTheme {
Greeting("Android Studio")
}
}
The preview panel updates as you type — no emulator needed for basic layout work.
Running on the Emulator
Open Tools → Device Manager and click Create Device. Select a hardware profile (Pixel 8 is a good default) and a system image (API 35). Click Finish.
Emulator Shortcuts
| Shortcut | Action |
|---|---|
Ctrl+F11 |
Rotate device |
Ctrl+Shift+A |
Extended controls (location, battery, phone) |
Ctrl+F6 |
Take screenshot |
| Triple-finger swipe | Quick settings / notifications |
Run your app with Shift+F10. Android Studio installs the APK on the emulator and launches the activity. The Run tool window shows log output:
$ adb install -t -r app/build/outputs/apk/debug/app-debug.apk
Success
$ adb shell am start -n "com.example.myfirstapp/.MainActivity"
Starting: Intent { cmp=com.example.myfirstapp/.MainActivity }
Debugging with Logcat
The Logcat tool window (Alt+6) displays all device log messages. Filter by package name or log level:
| Log Level | Method | Use Case |
|---|---|---|
V |
Log.v() |
Verbose — detailed debugging |
D |
Log.d() |
Debug — development diagnostics |
I |
Log.i() |
Info — general operational messages |
W |
Log.w() |
Warning — potential issues |
E |
Log.e() |
Error — failures requiring attention |
WTF |
Log.wtf() |
What a Terrible Failure — should-never-happen bugs |
// LoggingDemo.kt — demonstrate Logcat levels
import android.util.Log
import androidx.compose.runtime.Composable
private const val TAG = "MainActivity"
@Composable
fun LoggingExample() {
Log.v(TAG, "Verbose: entering composable")
Log.d(TAG, "Debug: initializing state")
Log.i(TAG, "Info: user opened the app")
// Simulate a recoverable error
try {
val result = riskyOperation()
Log.d(TAG, "Operation result: $result")
} catch (e: Exception) {
Log.e(TAG, "Error in riskyOperation", e)
}
}
fun riskyOperation(): String {
Log.w(TAG, "Warning: riskyOperation may fail on null input")
return "success"
}
Logcat output (filtered by 'MainActivity'):
D/MainActivity: Debug: initializing state
I/MainActivity: Info: user opened the app
W/MainActivity: Warning: riskyOperation may fail on null input
D/MainActivity: Operation result: success
Breakpoints and Variable Inspection
Set breakpoints by clicking the gutter in the Kotlin editor. Run the app in debug mode (Shift+F9). When execution pauses, hover over variables to inspect their values, or use the Variables pane to navigate the call stack.
Gradle Build System
Gradle is Android's build system. Every Android project has two build.gradle.kts files.
Project-Level build.gradle.kts
// build.gradle.kts (Project: MyFirstApp)
plugins {
id("com.android.application") version "8.5.0" apply false
id("org.jetbrains.kotlin.android") version "2.0.0" apply false
}
Module-Level build.gradle.kts
// app/build.gradle.kts
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
}
android {
namespace = "com.example.myfirstapp"
compileSdk = 35
defaultConfig {
applicationId = "com.example.myfirstapp"
minSdk = 24
targetSdk = 35
versionCode = 1
versionName = "1.0.0"
}
buildTypes {
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}
dependencies {
implementation("androidx.core:core-ktx:1.13.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.0")
implementation("androidx.activity:activity-compose:1.9.0")
implementation(platform("androidx.compose:compose-bom:2024.05.00"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.material3:material3")
debugImplementation("androidx.compose.ui:ui-tooling")
}
Common Gradle Tasks
Run these from the Gradle tool window (right sidebar) or terminal. Git commands are also available via the built-in terminal:
./gradlew assembleDebug # Build debug APK
./gradlew assembleRelease # Build release APK (signed)
./gradlew lint # Run lint checks
./gradlew test # Run unit tests
./gradlew connectedAndroidTest # Run instrumented tests on device
Common Errors
1. "Failed to find Build Tools revision"
The project specifies a build tools version not installed in your SDK.
Fix: Open SDK Manager → SDK Tools, check "Show Package Details", and install the missing build tools version. Or update build.gradle.kts to use an installed version.
2. Emulator "KVM is not installed" on Linux
The emulator requires KVM for hardware acceleration.
Fix:
sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils
sudo adduser $USER kvm
Log out and back in, then restart the emulator.
3. "INSTALL_FAILED_UPDATE_INCOMPATIBLE" When Installing on Device
An existing app with the same package name but a different signature is installed.
Fix: Uninstall the existing app:
adb uninstall com.example.myfirstapp
Then reinstall.
4. Gradle Sync Failing with "Could not resolve" Dependency
A required library cannot be downloaded.
Fix: Check your internet connection. Add mavenCentral() or google() to the repositories block in settings.gradle.kts if missing. Use File → Invalidate Caches and Restart to clear the Gradle cache.
// settings.gradle.kts
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
5. App Crashing with "Cannot access 'fragment' on stopped activity"
The activity was destroyed (orientation change, memory reclaim) but a background Coroutine called a reference.
Fix: Use lifecycleScope.launch with Lifecycle.repeatOnLifecycle pattern, and never hold a Context reference longer than the lifecycle owner. The fix in Durga Antivirus Pro's background scanner uses a bounded service with a lifecycle-aware coroutine scope.
// Safe lifecycle-aware coroutine
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
// Safe to access UI here
viewModel.uiState.collect { state ->
updateUI(state)
}
}
}
6. R8/ProGuard Removes Required Classes in Release Build
Release builds crash with ClassNotFoundException because ProGuard stripped reflection-accessed classes.
Fix: Add keep rules in proguard-rules.pro:
-keep class com.example.myfirstapp.** { *; }
-keepattributes *Annotation*
-keepclassmembers class * {
@com.google.gson.annotations.SerializedName <fields>;
}
7. Layout Inspector Shows "Not connected"
The Layout Inspector cannot connect to the running app.
Fix: Ensure the app is compiled with debuggable = true. Use the debug build variant. If using a physical device, enable USB debugging in Developer Options and authorize the computer.
FAQ
Practice Questions
1. What is the difference between compileSdk, minSdk, and targetSdk in Gradle?
compileSdk is the API level used to compile your app. minSdk is the lowest API level your app supports. targetSdk signifies you have tested your app on this API level — Android uses this for backward compatibility behavior changes.
2. How do you add a button click event in Jetpack Compose?
Use Button(onClick = { /* handler */ }) { Text("Click") }. The onClick lambda runs when the user taps the button.
3. What Logcat level should you use for debugging during development?
Use Log.d() (Debug) for development diagnostics. Use Log.v() for high-frequency verbose logging that should be disabled in production. Use Log.e() for errors only.
4. How do you install an APK on a physical device using the command line?
Connect the device via USB, enable USB debugging, then run adb install app-debug.apk. Use adb devices first to verify the device is listed.
5. Challenge: Build a note-taking app with Compose
Create a new Android project. Build a Note data class with id: Int, title: String, content: String, and timestamp: Long. Display notes in a LazyColumn. Add a FAB (Floating Action Button) that opens a dialog to add a new note. Use remember and mutableStateListOf for state management without ViewModel. Run on the emulator and verify notes persist across orientation changes.
Mini Project: Network Request with Retrofit and JSON Parsing
Add a network layer to your app using Retrofit.
app/build.gradle.kts — add dependencies:
dependencies {
implementation("com.squareup.retrofit2:retrofit:2.11.0")
implementation("com.squareup.retrofit2:converter-gson:2.11.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
}
ApiService.kt — define the API interface:
package com.example.myfirstapp
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
data class Todo(val id: Int, val title: String, val completed: Boolean)
interface ApiService {
@GET("todos")
suspend fun getTodos(): List<Todo>
}
object RetrofitClient {
private const val BASE_URL = "https://jsonplaceholder.typicode.com/"
val instance: ApiService by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
}
}
NetworkViewModel.kt — manage UI state:
package com.example.myfirstapp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
class NetworkViewModel : ViewModel() {
private val _todos = MutableStateFlow<List<Todo>>(emptyList())
val todos: StateFlow<List<Todo>> = _todos
init { fetchTodos() }
private fun fetchTodos() {
viewModelScope.launch {
try {
_todos.value = RetrofitClient.instance.getTodos()
} catch (e: Exception) {
// Handle error — this pattern is used in Doda Browser's
// network resilience layer for retry and fallback
}
}
}
}
Set breakpoints in fetchTodos() and step through the network call. Use Logcat with filter Retrofit to see HTTP request/response logs from OkHttp's logging interceptor.
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro