codingstairs
NotesEDULifeContact
⌕Search⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

Get in touch

Send without signing in. Add your email if you'd like a reply.

  • Leave a message anonymously →
  • ✉ warragon112@gmail.com
  • KakaoTalk Open Chat ↗

© 2026 codingstairs

  • Notes
  • EDU
  • Search
  • Life
  • Contact
  • Legal
  • RSS
  • GitHub
Notes›mobile

Android App Build — APK · AAB · Signing

Published 2026-04-28· Updated 2026-05-18·0 views

Android App Build — APK · AAB · Signing

Building an Android app, regardless of the tool, eventually goes through similar steps. Compile sources, bundle resources, convert to DEX, and sign. The result is an APK or an AAB. This post walks through that flow, the meaning of the SDK versions (min · target · compile), signing-key operations, and the parts that Tauri, Flutter, and React Native share.

1. APK · AAB

APK (Android Package) — Android's traditional package format. A ZIP container with compiled code (DEX), resources, manifest, and signature.

AAB (Android App Bundle) — introduced by Google in 2018. The Play Store dynamically builds the smallest APK that fits a user device's screen density, language, and architecture. As a result, the download size users see is reduced.

Item APK AAB
Device install Possible directly Not directly installable (use bundletool to generate APK)
Play Store upload Allowed (older apps) Required (new apps from 2021-08)
Size optimization One APK Per-device split
Sideloading Natural Awkward

From August 2021, AAB became mandatory for new apps in the Play Console. As a result, Play distribution uses AAB and sideloading or third-party stores use APK.

2. Build flow

Source (Java · Kotlin) → javac · kotlinc → .class
Resources (res/ · assets/) → AAPT2 → compiled resources
.class → R8 (or D8) → .dex (with shrink · obfuscation)
DEX + resources + AndroidManifest → packager → sign → APK · AAB

Gradle — the de facto standard tool for Android builds. Define dependencies, plugins, and build variants in build.gradle or build.gradle.kts:

android {
  compileSdk = 35
  defaultConfig {
    applicationId = "com.example.app"
    minSdk = 24
    targetSdk = 35
    versionCode = 1
    versionName = "1.0.0"
  }
  buildTypes {
    release {
      minifyEnabled = true
      shrinkResources = true
      proguardFiles(...)
    }
  }
}

AAPT2 (Android Asset Packaging Tool 2) — compiles and links resources (res/). PNG optimization, ID assignment, binary XML conversion.

R8 — the successor to ProGuard. Removes unused classes and methods and shortens names to shrink DEX size. Enabled with minifyEnabled = true.

D8 — converts .class (JVM bytecode) to .dex (for the Android virtual machine). Often performed together with R8.

Bundletool — a tool that generates per-device APKs from an AAB. For local debugging, bundletool build-apks ... produces a runnable APK.

3. SDK version meanings

Property Meaning
minSdk Lowest OS version where the app runs
targetSdk OS version the app is tested and guaranteed for. Affects permission and behaviour defaults
compileSdk SDK used to build. Determines whether new APIs can be called

Google Play policy raises the minimum targetSdk for new and updated apps every year. As of late 2024, new apps require Android 14 (API 34) targetSdk.

Lowering minSdk widens user reach but increases code branching. Usually you drop OS versions whose market share falls below a threshold.

4. Signing

Keystore — a .jks file created with Java's keytool. It stores the private key bundled with a certificate:

# Mac · Linux
keytool -genkey -v -keystore release.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload

# Windows (PowerShell, after JDK install)
keytool.exe -genkey -v -keystore release.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload

Upload Key vs App Signing Key — since the Play App Signing model (introduced in 2017), two keys are split:

  • Upload Key — held by the developer. Signs uploads to Play. If lost, Google can reissue it.
  • App Signing Key — held by Google. Signs the final binary delivered to users.

Opting in to Play App Signing reduces the risk of losing keys, but direct access to the App Signing Key is restricted.

Signing scheme evolution:

  • v1 (JAR signing) — META-INF/*.SF. Per-entry integrity. Replaced by v2 after weakness reports.
  • v2 (APK Signing Block) — 7.0+. Whole-APK integrity.
  • v3 (key rotation) — 9.0+.
  • v4 (incremental) — 11.0+.

The Gradle Android Plugin applies the appropriate scheme automatically. Typically v2 + v3 are active together.

Signing config — keep keystore passwords in environment variables or a secrets manager. Don't commit them in plaintext:

android {
  signingConfigs {
    release {
      storeFile = file(System.getenv("KEYSTORE_PATH"))
      storePassword = System.getenv("KEYSTORE_PASSWORD")
      keyAlias = System.getenv("KEY_ALIAS")
      keyPassword = System.getenv("KEY_PASSWORD")
    }
  }
  buildTypes {
    release {
      signingConfig = signingConfigs.release
    }
  }
}

5. What cross-platform tools share

Tauri Mobile, Flutter, and React Native all end up with the same Android build flow:

  • Compile or bundle their own code (Rust, Dart, JS).
  • Auto-generate and manage the Android (Gradle) project.
  • Produce APK or AAB via gradlew assembleRelease or gradlew bundleRelease.
  • Define signing, minSdk, and targetSdk in build.gradle.

Each tool provides a default template, but the final artifact looks like a standard Android app. When the boundary feels fuzzy, open it directly in Android Studio to verify.

6. Build variants and CI

Build variants — the product of flavors and buildTypes gives multiple builds:

flavorDimensions += "tier"
productFlavors {
  free { dimension = "tier" }
  pro  { dimension = "tier" }
}

Tasks like assembleFreeDebug and assembleProRelease are generated automatically.

CI builds:

  • GitHub Actions — speed up with gradle/wrapper-validation-action + actions/cache.
  • Store the keystore as a base64-encoded secret → decode at build time.
- run: |
    echo "$KEYSTORE_BASE64" | base64 -d > release.jks
    ./gradlew bundleRelease

7. Common pitfalls

What losing the key means — without Play App Signing opt-in, losing the key prevents updates under the same app ID. You'd have to relaunch as a new app.

Missing targetSdk bumps — Play Console can refuse new updates. Review the policy yearly.

minSdk vs library conflicts — some libraries require a higher minSdk. Inspect the dependency tree.

Multi-arch APK — including x86_64, arm64-v8a, and armeabi-v7a all together makes APKs heavy. AAB splits them automatically. For direct APK distribution, use ABI splits.

Unintended R8 removal — classes referenced only via runtime reflection can be stripped. Preserve them with ProGuard rules (-keep).

New permission models — Android 13+ notification permission, 14+ partial media access, etc., bring new permission models over time. Compatibility code is needed.

Play Integrity API — bot · tampering protection API. After adoption, some user devices report being denied.

Gradle version mismatch — the Android Gradle Plugin · Gradle · Kotlin · JDK compatibility matrix shifts quickly. Check the official docs.

Closing thoughts

Android builds, regardless of cross-platform tool, end up running through the same Gradle + AAPT2 + R8 + signing flow. AAB has become the standard for new apps, and Play App Signing reduces the risk of key loss. Yearly targetSdk updates and new permission-model compatibility are recurring operational tasks.

Next

  • ios-build
  • (mobile end)

Android Developers Build · Android App Bundle · Play App Signing · APK Signature Scheme v2/v3/v4 · R8 / ProGuard rules · Play Console Policy · bundletool GitHub · Android version share for reference.

More in mobile

All in this category →
  • iOS App Build — Xcode · Signing · TestFlight
  • Flutter Basics
  • Cross-platform Mobile — Comparing the Candidates