Build for Android
Compile and deploy the applications to Android devices
Build the Android applications (Agent, Hub, Remote) with kiln, install them on a device and start them. This guide covers both Android targets:
- arm64-v8a, which OctoMY™ ships for today: modern 64-bit Android phones, Android 9+, which is every device shipped since around 2020, including budget and rugged industrial tiers.
- x86_64, the second Android target. It builds, and the hub runs on the API 35 emulator. Device tests and releases wait until we have x86_64 Android hardware. It is postponed, not dropped.
32-bit ARM (armv7 / armeabi-v7a) is a deliberate, permanent non-target.
See the Android architecture support note
below.
kiln is the only Android path on a development machine. It makes the package
in its own process with the SDK's tools. There is no Gradle, and kiln does not
use qbs's Android module. The qbs android-arm64 profile stays for the build
farm, which patches its own qbs.
Prerequisites
Install the following before you build:
| Component | Version | Notes |
|---|---|---|
| Qt for Android | see integration/toolchain-requirements.json (qt.minimum) |
android_arm64_v8a, and android_x86_64 for the emulator. Not needed with the vendored Qt, see Without a Qt Android kit |
| Android SDK | API 35+ | Platform tools (adb), build tools and platforms/android-35 |
| Android NDK | r26 / r27+ | r26.1.10909125 works; r28+ gains 16 KB page support |
| JDK | 17+ | javac and java on the path |
| Android OpenSSL | ssl_3 | The NDK does not ship OpenSSL. The root .kiln names its folder per ABI |
| kiln | this tree | See Build through the kiln queue |
One-time setup
Tell kiln where the SDK, the NDK and the Qt Android kit are. These are machine
settings, so they go in .kiln.local in the checkout root:
[os=android]
android.sdk = /home/me/Android/Sdk
android.ndk = /home/me/Android/Sdk/ndk/26.1.10909125
[os=android arch=arm64]
qt.qmake = /home/me/Qt/6.10.1/android_arm64_v8a/bin/qmake6
[os=android arch=x64]
qt.qmake = /home/me/Qt/6.10.1/android_x86_64/bin/qmake6
If adb devices lists more than one device, add android.device = <serial>.
The kiln reference lists every android.* key.
Without a Qt Android kit
kiln can also build Qt for Android itself, from the pinned source, so you need no Qt for Android from Qt's installer. This is the vendored Qt of Build without a Qt installation, built for the device. You still need the SDK, the NDK, the JDK and Android OpenSSL from the table above.
-
Say so in
.kiln.local, and leave out theqt.qmakelines of the Android sections:qt.vendored.build = on qt.provider = vendored [os=android] android.sdk = /home/me/Android/Sdk android.ndk = /home/me/Android/Sdk/ndk/27.2.12479018 [os=android arch=arm64] output.dir = /home/me/build/octomy-android-arm64 [os=android arch=x64] output.dir = /home/me/build/octomy-android-x86_64Each ABI has its own
output.dir, because each one builds all of Qt. -
Fetch Qt's source once with
kiln vendor, if the checkout does not have it yet. -
Build and package as above:
kiln package apk src/hub --arch arm64 --install --launchThe first build runs Qt's configure for Android, builds the Qt modules that the application uses, and Qt's Java libraries with the JDK's
javac. It also builds androiddeployqt and rcc for your machine. The build folder is then laid out as Qt's Android kit, and the package is made from it as it is from an installed kit.
javac must be on the path, because Qt's Java libraries are compiled in the
build. The vendored Qt builds no QML, and the applications use none, so the
package is made without qmlimportscanner.
Android architecture support
There are two Android targets, and both are 64-bit:
| ABI | Status |
|---|---|
arm64 (arm64-v8a) |
Supported. Built, tested on devices and shipped. --arch arm64. |
| x86_64 | A target that is postponed, not dropped. It builds today, and the hub runs on the x86_64 emulator, but device tests and releases wait until we have x86_64 Android hardware. --arch x64. |
| armv7, armeabi-v7a, any 32-bit ABI | Never. A deliberate, permanent decision. kiln refuses it with a message that points to AGENTS.md. |
Do not remove x86_64 from the build matrix or from kiln. The reasons,
including why 32-bit is out for good (no 32-bit Android hardware in the target
market, the Google Play 64-bit policy, and libnative's JIT being 64-bit by
design), are in the project root AGENTS.md under "Android architecture
support". Read that before you open an issue or a merge request that touches
the Android ABIs.
Build, install and start
One command builds the application, makes its package, installs the package on the device and starts it:
kiln package apk src/hub --arch arm64 --install --launch
src/hubis the application. Usesrc/agent,src/remoteorsrc/constructfor the others.--arch x64builds for x86_64, for the API 35 emulator.- Without
--install, kiln only makes the package. The path of the package is the line kiln writes to standard output. The package goes in<build root>/package/asoctomy-<application>_<version>_<abi>.apk. --installrunsadb install -ron the device. kiln asksadbfor the device before the build, so a missing device does not cost a build.--launchstarts the launcher activity of the application's manifest witham start -W -n <package>/<activity>. Then kiln watches the process for 30 seconds.--launch-watch <seconds>changes the time, and--launch-watch 0does not watch.- The build is a release build.
--variant debugmakes a debug build.
If the process dies while kiln watches it, kiln exits 1. It names the process
that died and its process ID, and it prints the lines of logcat that come
from that ID or name it. A native exit() leaves no signal and no tombstone,
only a line from Zygote: Process <pid> exited cleanly (<status>). kiln
prints that line too.
Run the tests on a device
The suites run on a device inside the tests-runner package:
kiln test --os android --arch arm64 test/testAddressBook
kiln builds the package with the suites, installs it, starts each suite and
reads its result from logcat. If the runner's process ends without a result,
the verdict names the process, its ID and the line of the log that says how it
ended. See Run tests.
Release packages and signing
kiln signs with the SDK's debug key, ~/.android/debug.keystore, unless
android.keystore in .kiln.local names another. The release keystore is
integration/cicd/targets/android-arm64/certificates/android_release.keystore.
Give its password and key with android.keystore_password and
android.key_alias.
For Google Play, make the App Bundle:
kiln package aab src/hub --arch arm64
An App Bundle is for Google Play. A device installs an apk, so --install is
refused for aab.
Troubleshooting
INSTALL_FAILED_NO_MATCHING_ABIS
The package is for an ABI the device does not support. Check the ABIs of the device:
adb shell getprop ro.product.cpu.abilist
Build again with the --arch that the list names: arm64 for arm64-v8a,
x64 for x86_64.
no Android device answers
adb get-state did not say device. Start the emulator or connect a device
with USB debugging on. If adb devices lists several devices, name one with
android.device in .kiln.local.
--arch armv7 is a 32-bit ABI
32-bit Android is never a target. Use --arch arm64 or --arch x64. Read
AGENTS.md, "Android architecture support", for the reasons.
The application dies at start
kiln prints the death report. To read more of the log yourself:
adb logcat -d -v brief | grep -E 'octomy|Zygote|ActivityManager|libc|DEBUG'
Common causes: a wrong android.app.lib_name in the manifest, a missing Qt
plugin (for example no OpenGL ES), or a real runtime assertion.
See also
- Android Build Reference: technical configuration details
- kiln reference: every command and key
- Build through the kiln queue: how to set kiln up