DEMIENGINEDOCUMENTATION Everything is free

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": [] }
}
FieldMeaning
application_idReverse-DNS application identity (for example com.example.skyforge). Required before packaging; the package name of the APK is derived from it.
display_nameThe launcher label and activity title.
version_name / version_codeHuman version string and integer version code written into the Android manifest and the build report.
icon / splashasset:// IDs of the launcher icon and startup splash image. Sources may be PNG, JPEG, WebP, or SVG.
windowLogical resolution width and height in pixels, and mode: windowed, borderless, or fullscreen. On phones, fullscreen is the usual choice.
android.orientationRequested activity orientation: unspecified, portrait, landscape, portrait_sensor, or landscape_sensor.
android.permissionsAndroid 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 0 when valid, 1 on any validation error.
CodeMeaning
PROJECT_BUILD_FEATURE_MEDIA_UNSUPPORTEDThe project needs media support (FFmpeg) that this engine build lacks.
PROJECT_BUILD_FEATURE_NETWORK_UNSUPPORTEDThe project needs networking (ENet) that this engine build lacks.
PROJECT_BUILD_FEATURE_SVG_UNSUPPORTEDThe 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_MISSINGandroid.permission.INTERNET is required but not declared.
BUILD_PACKAGE_CONTENT_UNEXPECTEDPackage 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 0 on success, 1 when 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 0 when every test passed, 1 when any failed; the run always ends with a SUMMARY marker.

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/, plus demi.project.json, demi.packages.lock.json, and cook.manifest.json. Anything else fails with BUILD_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

  1. application_id is the reverse-DNS name you will keep forever.
  2. demi doctor --platform android and demi validate --platform android are clean.
  3. demi test android --serial <device> passes on real hardware.
  4. Release signing variables are present in the environment and absent from logs.
  5. demi build aab produced a fresh artifact and *.build-report.json.
  6. The report's versions match version_name and version_code in 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.