MobDev.ReleaseAndroid (mob_dev v0.7.17)

Copy Markdown View Source

Builds the signed release AAB for a Mob Android app.

Called by mix mob.release --android. The pipeline:

  1. Regenerate the mob.exs url_schemes intent filter in AndroidManifest.xml (MobDev.UrlSchemes), so the release doesn't depend on a dev build having stamped the current setting.
  2. Regenerate the plugin-derived files (runtime manifest, driver tables, migrations, images) and run the same native build as mix mob.deploy --native (MobDev.NativeBuild.build_android_native/2) for every Gradle abiFilters ABI: jniLibs/<abi>/lib<app>.so is rebuilt with the current plugins linked in, never reused from the last deploy (MOB-404). No device needed.
  3. Copy the arm64 OTP tree to a temp staging dir and add:
    • App + dep BEAMs (flattened into {app_name}/)
    • App priv/ → {app_name}/priv/
    • exqlite BEAMs → lib/exqlite-{vsn}/ebin/ (OTP lib structure needed for :code.lib_dir(:exqlite) to resolve correctly at runtime)
  4. Run MobDev.OtpAssetBundle.build/2 — strips unused OTP libs (never one the app's runtime dependency closure needs, see MobDev.OtpRequiredApps) and optional BEAM chunks, then zips the tree to src/release/assets/otp.zip.
  5. Run ./gradlew bundleRelease — signs the AAB using the keystore configured in android/keystore.properties.

MobBridge.extractOtpIfNeeded() (Kotlin) extracts otp.zip into <filesDir>/otp/ on first launch. Without this zip the app crashes immediately — the BEAM has no runtime or application BEAMs to load.

The zip is written to the release-variant asset source set, not the shared main one — Gradle only merges src/release/assets/ into release builds, so a leftover zip from a prior release build can never leak into (and silently poison) a subsequent debug build. See decisions/2026-07-24-release-otp-zip-variant-scoped-assets.md.

Summary

Functions

Runs the full Android release pipeline and returns {:ok, aab_path} or {:error, reason}.

Functions

build_aab(opts \\ [])

@spec build_aab(keyword()) :: {:ok, Path.t()} | {:error, String.t()}

Runs the full Android release pipeline and returns {:ok, aab_path} or {:error, reason}.