Files
gen1recomp/mobile/ANDROID.md
T
bryanthaboi bcfc94d448 Merge pull request #366 from pmarcus93/android-respect-rotation-lock
Respect the device rotation lock on Android
2026-07-31 08:08:19 -04:00

3.8 KiB

Android (love-android 11.5a)

mobile/android/ is a vendored copy of love2d/love-android at tag 11.5a (matches conf.lua t.version = "11.5"), tracked directly in this repo, no git submodules involved. Nested love sources live at mobile/android/love/src/jni/love (also vendored). Build outputs (app/build/, love/build/, .gradle/, local.properties) stay gitignored.

Refreshing the vendored tree

To pick up a newer love-android release, replace the tree and re-vendor:

rm -rf mobile/android
git clone --depth 1 --branch <new-tag> --recurse-submodules --shallow-submodules \
  https://github.com/love2d/love-android.git mobile/android
rm -rf mobile/android/.git mobile/android/love/src/jni/love/.git \
       mobile/android/.gitmodules

scripts/build_android.sh re-applies project branding on every run (gradle.properties app id / name / portrait, plus permission trims), so a refresh is safe, just rebuild.

Build

# Build the APK
scripts/build_android.sh

# Build the APK, setting app.version_name/app.version_code to match a release
scripts/build_android.sh --version 0.2.5

# Zip game.love + branding only (no Android SDK required)
scripts/build_android.sh --package-only

Or via scripts/build.sh android [--version X.Y.Z].

The embedded game.love deliberately excludes data/generated/, assets/generated/, and any ROM. It contains the first-boot Lua importer and tools/rom_manifest.json.

ROM / mod / save import on Android uses love.system.pickFile([kind])GameActivity.showFilePicker (Storage Access Framework), which copies the chosen file under the app save directory as picked_rom.gb, picked_mod.zip, or picked_save.sav. RomImporter imports pending files from that folder on Choose / refocus; see docs/launcher.md. The APK payload itself remains data-free (no embedded ROM or generated cache).

SDK / NDK

love-android 11.5a expects:

  • JDK 17
  • Android SDK with API 34
  • NDK 25.2.9519653 (Apple Silicon host supported)

Set ANDROID_SDK_ROOT (or ANDROID_HOME), or let the script write local.properties when it finds ~/Library/Android/sdk.

Gradle flavor used: embedNoRecord (game fused into the APK, no microphone). Build task: assembleEmbedNoRecordDebug.

The APK lands under app/build/outputs/apk/embedNoRecord/debug/. scripts/build_android.sh also copies it to dist/android/debug/.

Payload path

app/src/embed/assets/game.love - zip of main.lua, conf.lua, src/, data/, assets/, and the Red, Blue, and Yellow ROM manifests. The Android packer verifies the Yellow manifest before it packages; if a partial source export omitted it, it restores the file from this checkout's Git data and then falls back to the project's GitHub copy. Generated game data, scripts, tests, and mobile build sources are excluded.

Branding (applied by the build script)

Setting Value
app.application_id com.theboisclub.pokemonred
app.name Pokemon Red
app.orientation fullUser. This is only the manifest default: SDL requests FULL_SENSOR at window creation (resizable window, no SDL_HINT_ORIENTATIONS), and GameActivity.setOrientationBis remaps that to FULL_USER so the device's rotation lock is honoured.
app.version_name / app.version_code set from --version X.Y.Z (code = major10000 + minor100 + patch); left as-is if --version is omitted
Permissions INTERNET / RECORD_AUDIO / WRITE_EXTERNAL_STORAGE stripped; VIBRATE + BLUETOOTH kept

Releases

.github/workflows/release.yml builds the APK with --version set to the release version and publishes it alongside the macOS/Windows/Linux builds as PokemonRed-<version>-android.apk.

Signing

Signed with the default Android keystore (no setup required).