How does Android turn your Kotlin code into an APK?

And what actually changes when you use Jetpack Compose instead of XML?


When you click Build → APK in Android Studio, your source code goes through several stages before becoming an installable APK.


⚡ How an Android App Becomes an APK — 9 Steps

1️⃣ Kotlin/Java Source Code Compilation

2️⃣ Jetpack Compose Code Transformation

3️⃣ .class Bytecode → .dex with D8/R8

4️⃣ Android Resources Compilation with AAPT2

5️⃣ AndroidManifest.xml Merging

6️⃣ APK Packaging

7️⃣ Code Shrinking & Optimization

8️⃣ APK Alignment with Zipalign

9️⃣ APK Signing 🔐


_______________________________________________________


NOW STEPS DETAILS 


1️⃣ Kotlin/Java → JVM Bytecode

Your Kotlin/Java source code is first compiled into JVM .class bytecode.


class User {

    fun getName(): String = "Android"

}

⬇️


Kotlin / Java

      ↓

.class bytecode

For Kotlin, the Kotlin compiler handles this compilation step.


2️⃣ .class → .dex

Android devices don't execute JVM .class files directly.


The D8 compiler converts the bytecode into DEX (Dalvik Executable) format.


.class

   ↓

D8

   ↓

.dex

DEX is the format used by the Android Runtime (ART).


If R8 is enabled for the release build, it can also perform shrinking, optimization, and obfuscation as part of the release build process.


3️⃣ What happens to Jetpack Compose code?

This is where Compose becomes interesting.


Consider:


@Composable

fun Greeting(name: String) {

    Text("Hello $name")

}

You don't write an XML layout.


The Compose compiler/plugin transforms composable code so that it can participate in Compose's runtime and recomposition model.


Eventually, that code is compiled down through the normal Kotlin/Android compilation pipeline:


Composable Kotlin

      ↓

Compose compiler transformation

      ↓

JVM bytecode

      ↓

D8

      ↓

DEX

So Compose is not generating an XML layout behind the scenes.


4️⃣ What happens with XML layouts?

With the traditional View system:


<TextView

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:text="Hello Android" />

XML resources are processed by AAPT2.


The XML isn't shipped simply as the original text file for Android to interpret.


AAPT2 compiles Android resources into the application's resource table and packaged resource representation.


XML / Resources

      ↓

AAPT2

      ↓

Compiled Android resources

The APK can therefore contain compiled resources, including binary XML representations for applicable XML resources.


5️⃣ Resource Processing

Things such as:


strings.xml

drawables

colors

themes

XML resources

images

are processed through the Android resource pipeline.


The resulting resources are packaged into the APK alongside your compiled code.


6️⃣ Manifest Merging

Your application may depend on many libraries.


Each library can have its own:


AndroidManifest.xml

Gradle's Android build system merges these manifests into the final application manifest.


This can include:

Activities

Services

Permissions

Providers

Metadata


Application configuration


7️⃣ Everything gets packaged

Now the build system brings the pieces together:


Kotlin / Java

      ↓

.class → .dex


Compose code

      ↓

Compose compiler → .class → .dex


Resources

      ↓

AAPT2 → compiled resources


Manifest

      ↓

Manifest merger

      ↓

   Packaging

      ↓

    APK

The APK is essentially a packaged application containing your compiled code, resources, manifest information, and other required files.


8️⃣ Optimization for Release Builds

For release builds, R8 can:


✅ Remove unused code

✅ Optimize bytecode

✅ Obfuscate names

✅ Reduce application size


Then zip alignment is applied as part of APK packaging/signing workflows to optimize how the packaged data is laid out.


9️⃣ APK Signing 🔐

Before distribution, the APK needs to be digitally signed.


Your signing key allows Android and distribution systems to verify the APK's authenticity and integrity.


For Play distribution, modern Android apps are commonly uploaded as AAB (Android App Bundle) rather than directly distributing one universal APK.


So what's really different between XML and Compose?

XML + Views

XML layout

   ↓

AAPT2

   ↓

Compiled resources

   ↓

APK

   ↓

View system loads/inflates layout

Jetpack Compose

Composable Kotlin

   ↓

Compose compiler

   ↓

Kotlin/JVM bytecode

   ↓

D8

   ↓

DEX

   ↓

Compose runtime

The important difference is that Compose defines UI through Kotlin code and the Compose runtime, whereas the traditional View system commonly defines layouts through XML resources that are inflated into View objects.


⚠️ One common misconception:


It's not accurate to say:


"Compose is faster because it doesn't parse XML."


Performance depends on much more than that.


Compose has its own runtime, composition, recomposition, layout, and drawing mechanisms. The real advantage is the declarative UI model and state-driven UI architecture, not simply eliminating XML parsing.


🧠 The simplest mental model

XML:

XML → compiled resources → View system

Compose:

Kotlin → compiled code → Compose runtime


Both ultimately become code/resources packaged into an APK and executed by Android.


That's the interesting part: whether you write XML or Kotlin, Android still has to turn your application into a form that ART can execute. 🚀


#AndroidDevelopment #Kotlin #JetpackCompose #AndroidStudio #APK #AndroidInternals #Gradle #R8 #AAPT2 #MobileDevelopment