Android build reference

Android build architecture, configuration, and deployment with Qbs

Technical reference for the Android build infrastructure. Kiln, the default build path, builds OctoMY™ for Android with kiln build --os android and makes the packages with kiln package apk and kiln package aab (see the kiln reference). This page describes the Qbs Android pipeline, the second path until qbs retires, with Qt6.


Build Architecture

Qbs builds Android applications using its own packaging pipeline, without Gradle. The Android.sdk module handles:

  1. Resource compilation via AAPT2
  2. DEX compilation via d8
  3. APK/AAB assembly directly

This differs from CMake-based Qt6 projects, which use Gradle as an intermediary.


Android Version Targeting

Property Value Meaning
minSdkVersion 28 Minimum Android 9 (Pie) — Qt6 requirement
targetSdkVersion 35 Android 15 — Google Play 2025 requirement
compileSdkVersion 35 Compile against API 35

These values ensure compatibility with devices running Android 9 through Android 16, while meeting Google Play Store publishing requirements.


Project Structure

Each of the three applications has an android/ directory:

src/{agent,hub,remote}/android/
├── AndroidManifest.xml          # App manifest (package, permissions, activity)
└── res/
    ├── drawable-hdpi/icon.png   # App icon (high density)
    ├── drawable-mdpi/icon.png   # App icon (medium density)
    ├── drawable-ldpi/icon.png   # App icon (low density)
    └── values/libs.xml          # App name string resource

The signing keystore is stored separately at integration/cicd/targets/android-arm64/certificates/android_release.keystore.


AndroidManifest.xml

Each app's manifest declares the Qt6 Activity and application bindings:

<application android:name="org.qtproject.qt.android.bindings.QtApplication" ...>
    <activity android:name="org.qtproject.qt.android.bindings.QtActivity"
              android:exported="true" ...>
        <meta-data android:name="android.app.lib_name" android:value="{appname}"/>
    </activity>
    <provider android:name="androidx.core.content.FileProvider" .../>
</application>

Key elements:

Element Purpose
QtApplication Qt6 application class (handles library loading)
QtActivity Default Qt6 activity (no custom subclass needed)
android:exported="true" Required since Android 12 (API 31) for launcher activities
android.app.lib_name Name of the native shared library to load
FileProvider Required by Qt6 for file sharing intents

Per-app differences:

App Package Library Name
Agent org.octomy.agent agent
Hub org.octomy.hub hub
Remote org.octomy.remote remote

Qbs Configuration

AndroidOptions.qbs

Located at integration/qbs/imports/AndroidOptions.qbs, this Properties block configures the Android SDK when targeting Android:

The properties belong to the Android.sdk module:

Property Value Description
platform "android-35" Compile SDK version
packageType the project's androidPackageType "apk" or "aab"
aaptName "aapt2" Resource compiler
dexCompilerName "d8" DEX compiler

The value of Android.sdk.packageType is project.androidPackageType.

App.qbs Android Integration

App.qbs conditionally includes Android support:

  • Dependencies: Android.sdk and Android.ndk (when targeting Android)
  • Manifest: Points Android.sdk.manifestFile to the per-app AndroidManifest.xml
  • Linker: Skips --start-group/--end-group flags (Android's lld resolves all archive symbols by default)

project.qbs

Property Default Description
androidPackageType "apk" Override with "aab" for Google Play

BuildOptions.qbs Android Guards

The following desktop-only features are disabled on Android:

  • -fstack-clash-protection (not supported by NDK)
  • -fuse-ld=mold / -fuse-ld=lld (NDK provides its own linker)
  • cpp.cxxStandardLibrary (NDK always uses libc++)

QtDepends.qbs Module Exclusions

These Qt modules are excluded on Android builds:

Module Reason
printsupport No printing support on Android
shadertools-private Desktop-only
serialport No serial port access on Android
webenginecore / webenginewidgets Not available on Android

Signing

The release keystore is at integration/cicd/targets/android-arm64/certificates/android_release.keystore. For release builds, configure signing via Qbs Android.sdk properties or environment variables.


ABI Support

OctoMY™ has two Android targets, both 64-bit:

ABI Status Typical device
arm64-v8a Supported: built, tested on devices, shipped Modern phones (Android 9+)
x86_64 A target, postponed until we have x86_64 Android hardware. It builds, and the hub runs on the API 35 emulator. Device tests and releases wait for hardware x86_64 tablets and Chromebooks, the emulator

How to build each ABI, and the folder of its Qt installation:

  • arm64-v8a — kiln package apk --arch arm64. Qt install path: Qt/6.10.1/android_arm64_v8a.
  • x86_64 — kiln package apk --arch x64. The build farm builds it as android/35/x86_64. Qt install path: Qt/6.10.1/android_x86_64.

Postponed is not dropped: x86_64 stays in the build matrix and in kiln. armv7 / armeabi-v7a / any 32-bit ARM target is the opposite case. It is a deliberate, permanent non-target and will not be re-added. The justification (no 32-bit Android hardware in the target market, the Google Play 64-bit policy since 2019, libnative's JIT being 64-bit by design) is in the root AGENTS.md under "Android architecture support". Read that before requesting a change to the Android ABIs.

Build, install and start

kiln is the Android path on a development machine. It builds both 64-bit ABIs and installs and starts the application through adb:

kiln package apk src/hub --arch arm64 --install --launch
kiln package apk src/hub --arch x64 --install --launch     # the API 35 emulator

--install runs adb install -r on the device that adb sees, or on the device that android.device in .kiln.local names. --launch starts the launcher activity of the manifest with am start -W -n <package>/<activity>. Then it watches the process for 30 seconds (--launch-watch <seconds>, 0 to not watch). If the process dies, kiln names the process and its ID and prints the logcat lines about that ID. kiln refuses armv7, armeabi-v7a and every other 32-bit ABI with a message that points to AGENTS.md.

The suites run on a device with kiln test --os android --arch arm64. See the Build for Android howto.

qbs profile

The qbs profile android-arm64 stays for the build farm. The farm patches its own qbs Android module at container start. The tree no longer carries the patched module files or the script that installed them (integration/qbs/vendor/, deleted in script-ports Phase 12). A stock qbs fails the Android build, so use kiln on a development machine.

  • Profile: android-arm64
  • ABI: arm64-v8a
  • qbs.architecture: arm64
  • Qt install path: Qt/6.10.1/android_arm64_v8a
  • Typical device: modern phones (Android 9+)

AAB (Google Play) bundle

For Play Store distribution, build the App Bundle:

kiln package aab src/hub --arch arm64

arm64-v8a alone covers the vast majority of active Play Store devices.


SDK/NDK Requirements

Component Minimum Version
Android SDK Platform API 35
Android NDK r26+ (r27.2+ recommended; r28+ gains 16 KB page support)
JDK 17+ (21+ for Qt 6.11)
Qt 6.10.0+
Qbs 2.0+
Android OpenSSL ssl_3 (extracted into the SDK root)

See also

Topics
reference android build-system qbs deployment mobile
See also