APK/AAB, signing, permissions, and devices.
Android builds
An Android build turns a DemiEngine project into an installable phone or tablet package: a debug APK for development, or a release APK or App Bundle for a store. Android packaging exists so the same project you authored on the desktop runs on real mobile hardware with its own identity, permissions, orientation, and signing. This page covers the project settings, the build commands, signing, and on-device runs and tests. Examples use "Skyforge" at games/my_game.
Project settings for Android
Android builds read identity and platform options from demi.project.json. The same build block that feeds the Linux bundle carries the mobile fields:
"build": {
"application_id": "com.example.skyforge",
"display_name": "Skyforge",
"version_name": "0.1.0",
"version_code": 1,
"icon": "asset://branding/icon",
"splash": "asset://branding/splash",
"window": { "width": 1280, "height": 720, "mode": "fullscreen" },
"android": { "orientation": "landscape", "permissions": [] }
}
| Field | Meaning |
|---|---|
application_id | Reverse-DNS application identity (for example com.example.skyforge). Required before packaging; the package name of the APK is derived from it. |
display_name | The launcher label and activity title. |
version_name / version_code | Human version string and integer version code written into the Android manifest and the build report. |
icon / splash | asset:// IDs of the launcher icon and startup splash image. Sources may be PNG, JPEG, WebP, or SVG. |
window | Logical resolution width and height in pixels, and mode: windowed, borderless, or fullscreen. On phones, fullscreen is the usual choice. |
android.orientation | Requested activity orientation: unspecified, portrait, landscape, portrait_sensor, or landscape_sensor. |
android.permissions | Android permission strings the app needs, for example android.permission.INTERNET for networked games. |
If you author an Android permissions list, include android.permission.INTERNET when the project uses HTTP or sessions. Validation reports PROJECT_BUILD_PERMISSION_NETWORK_MISSING when such an authored list omits it. Projects without an authored build block retain the Gradle default permissions, including INTERNET. HTTP usage is described in HTTP & TLS.
Validate the Android target
Android can do less than a desktop in some optional areas. Validate for this platform before building so capability problems are named instead of discovered on a device:
demi validate games/my_game --platform android
validate [path]— validates the project and all reachable source.--platform android— adds Android capability and permission checks.- Returns
0when valid,1on any validation error.
| Code | Meaning |
|---|---|
PROJECT_BUILD_FEATURE_MEDIA_UNSUPPORTED | The project needs media support (FFmpeg) that this engine build lacks. |
PROJECT_BUILD_FEATURE_NETWORK_UNSUPPORTED | The project needs networking (ENet) that this engine build lacks. |
PROJECT_BUILD_FEATURE_SVG_UNSUPPORTED | The project uses SVG as runtime content (SVG textures or icons referenced from scenes, HUDs, or Lua) that this engine build cannot decode. Branding-only SVG icon/splash sources never trigger this: packaging rasterizes or installs them host-side. |
PROJECT_BUILD_PERMISSION_NETWORK_MISSING | android.permission.INTERNET is required but not declared. |
BUILD_PACKAGE_CONTENT_UNEXPECTED | Package content outside the audited roots was found and rejected. |
Check the host toolchain as well — Java, the Android SDK, and the NDK:
demi doctor \
--platform android --format json
--platform android— checks the Android toolchain and reports discovery paths.--format json— emits the report as JSON.
Building an APK
An APK is the installable Android package you sideload or distribute directly:
demi build apk
build apk— cooks for Android and packages a debug APK.--configuration release— produces a release configuration build instead of debug.--gradle— invokes Gradle, optionally taking the Gradle wrapper path to use.- Returns
0on success,1when validation, cooking, or packaging fails.
Building an App Bundle for store upload:
demi build aab
build aab— packages an Android App Bundle.
Artifacts and reports are written under the project:
project/build/android/— the built APK or AAB and its intermediates.*.build-report.json— the build report next to the artifact: versions, content hashes, and configuration.
Packaging is transactional: a failed or cancelled build leaves the previous artifact intact and never publishes a partial staging directory.
Signing release builds
Signing proves the APK comes from you and is required for store distribution and for upgrades to install over older versions. Signing values come only from the environment — never from the project, the repository, command output, or build reports:
export DEMI_ANDROID_KEYSTORE=/secure/path/release.keystore
export DEMI_ANDROID_KEYSTORE_PASSWORD=...
export DEMI_ANDROID_KEY_ALIAS=skyforge
export DEMI_ANDROID_KEY_PASSWORD=...
demi build apk --configuration release
DEMI_ANDROID_KEYSTORE— path to the keystore file holding the release key.DEMI_ANDROID_KEYSTORE_PASSWORD— keystore password.DEMI_ANDROID_KEY_ALIAS— which key inside the keystore to sign with.DEMI_ANDROID_KEY_PASSWORD— password for that key entry.
Release signing values must never enter source, logs, reports, or packaged content. Debug builds use the platform's debug signing automatically and need none of these variables.
Running on a device
Development on hardware reuses a current APK whenever your inputs are unchanged, so the loop stays short:
demi run android \
--serial <device> --watch
run android— builds, installs, and launches on the connected device.--serial <device>— which device to target (the adb serial of the attached phone or tablet).--watch— enables cooked-source hot reload to the device as you edit.
End-to-end tests on the same hardware:
demi test android --serial <device>
test android --serial d— runs the project's E2E scripts through the real runtime on the device via adb.- Returns
0when every test passed,1when any failed; the run always ends with aSUMMARYmarker.
Android qualification uses a connected physical device. Test authoring (stable node IDs, bounded waits) is covered in E2E tests.
Content audit and lifecycle notes
- Release packages are audited against the allowed roots —
assets/,certs/,packages/,scenes/,scripts/, plusdemi.project.json,demi.packages.lock.json, andcook.manifest.json. Anything else fails withBUILD_PACKAGE_CONTENT_UNEXPECTED. - The cooked Android content lives in the platform's cooked directory with its
cook.manifest.json, the same cook pipeline as Linux bundles. - Frame-rate hints, surface recreation, pause/resume, and native-window rebinding are handled by the runtime; game code keeps using the normal script lifecycle.
- Saves and caches go to the platform user-data and cache directories on the device, never into the installed APK or the project.
Before you upload to a store
application_idis the reverse-DNS name you will keep forever.demi doctor --platform androidanddemi validate --platform androidare clean.demi test android --serial <device>passes on real hardware.- Release signing variables are present in the environment and absent from logs.
demi build aabproduced a fresh artifact and*.build-report.json.- The report's versions match
version_nameandversion_codein the project.
Related pages: demi.project.json for the full build block, Build, cook & test for every build command, and Linux bundles for the desktop counterpart.