🏆 For Judges / Reproducibility
🔧 Build & Verify

Build it yourself. Verify everything.

Every claim on this site is verifiable from the source. This page documents the exact toolchain (down to point releases), the 16 KB ELF compliance, the APK signature, and the step-by-step build procedure.

📦 v1.0.14 · versionCode 31 🛠️ AGP 8.13.2 🟪 Kotlin 2.3.21 📐 Gradle 8.14 ⚙️ NDK r27.2.12479018

Exact toolchain pin

From gradle/libs.versions.toml and gradle/wrapper/gradle-wrapper.properties. Copy these versions exactly to reproduce the build.

🟪
Kotlin
2.3.21
Required for kotlin.time.Instant + LiteRT-LM 0.11.0 metadata compat
🛠️
Android Gradle Plugin
8.13.2
R8 v8.13.19 supports Kotlin 2.3 metadata
📐
Gradle
8.14
Wrapper distribution: gradle-8.14-bin.zip
⚙️
Android NDK
r27.2.12479018
Required for 16 KB page-size aligned linker output
📱
compileSdk / targetSdk
35 (Android 15)
minSdk = 31 (Android 12). 16KB enforcement requires SDK 35+
🧠
LiteRT-LM
0.11.0
litertlm-android:0.11.0 — Gemma 4 native @Tool runtime
🩺
Kotlin FHIR
1.0.0-beta03
dev.ohs.fhir:fhir-model:1.0.0-beta03 — Apache 2.0
🗄️
SQLite (requery)
3.49.0
16 KB aligned libsqlite3x.so (upgraded from 3.45.0)
🎨
Jetpack Compose BOM
2026.04.01
Compose 1.11 stable
🪡
KSP / Hilt
2.3.7 / 2.58
Aligned with Kotlin 2.3 metadata format
📡
Google Nearby
play-services-nearby
Strategy.P2P_CLUSTER · BLE + Wi-Fi Direct
📷
ML Kit
barcode + doc + text-jp
Barcode Scanner (no permissions) + Document Scanner + Text Recognition v2 with Japanese bundle

Reproduce the APK in 6 steps

Tested on macOS 15 (Apple Silicon) and Ubuntu 24.04. Should work on Windows 11 with WSL2.

1

Install Android Studio + NDK

Download Android Studio Koala or later. Use the SDK Manager to install:

  • Android SDK Platform 35 (Android 15)
  • Android SDK Build-Tools 35.0.0
  • NDK 27.2.12479018 (Side panel → SDK Tools → check "Show Package Details")
  • CMake 3.22.1
2

Clone the repository

git clone https://github.com/kurodohenroonsen/JemmaPass.git
cd jemmapass
git checkout v1.0.14  # the submitted hackathon tag
3

Configure SDK / NDK paths

Create local.properties in the project root:

sdk.dir=/Users/your-name/Library/Android/sdk
ndk.dir=/Users/your-name/Library/Android/sdk/ndk/27.2.12479018
4

Sync Gradle & download dependencies

./gradlew --refresh-dependencies dependencies

This downloads Gemma 4 LiteRT runtime, Kotlin FHIR, requery SQLite, ML Kit, and the rest. ~600 MB on first sync.

5

Build the release APK

./gradlew clean assembleRelease

# APK lands at:
ls -la app/build/outputs/apk/release/

~3-5 minutes on M2 / Ryzen 7 hardware. The release APK is debug-signed for hackathon distribution (we don't ship a production key — anyone can re-sign for their own deployment).

6

Verify the SHA-256

shasum -a 256 app/build/outputs/apk/release/*.apk

# Compare with the SHA-256 published on hackathon.html#apk
# A matching hash proves you built the same artifact we submitted.

16 KB page-size compliance · verified

Android 15 enforces 16 KB native page alignment for all .so files shipped via Google Play (deadline November 1, 2025). Here is how to verify JemmaPass complies.

The llvm-objdump proof

Each native library inside the APK should show align 2**14 (= 16 384 bytes = 16 KB) on its LOAD segments. We tested all 11 .so files shipped with JemmaPass v1.0.14.

📄 Verification command (run yourself) Bash
# Extract native libs from the release APK
cd app/build/outputs/apk/release/
unzip -o *.apk -d apk-contents/

# Path to NDK llvm-objdump (adjust version if needed)
LLVM=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump

# Verify each .so file in arm64-v8a (the Pixel 9 ABI)
for so in apk-contents/lib/arm64-v8a/*.so; do
  echo "=== $(basename $so) ==="
  $LLVM -p $so | grep -E "p_align|LOAD" | head -5
done

Expected output

📄 Reference output · Pixel 9 build · all libs PASS Text
=== libsqlite3x.so ===
    LOAD off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**14
    LOAD off 0x00020000 vaddr 0x00400000 paddr 0x00400000 align 2**14
    LOAD off 0x00060000 vaddr 0x00800000 paddr 0x00800000 align 2**14
                                                              ^^^^
                                              16 KB (2**14 = 16384)

=== liblitertlm_jni.so ===
    LOAD off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**14
    LOAD off 0x00040000 vaddr 0x00400000 paddr 0x00400000 align 2**14

=== libimage_processing_util_jni.so ===
    LOAD off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**14

[... 8 more libs, all showing align 2**14 ...]

✅ ALL 11 .so files comply with 16 KB page-size alignment.
💡 Why this matters for the hackathon. Google Play has been rejecting APKs that fail this alignment since November 2025. A failing APK cannot be distributed at scale, regardless of how cool the demo is. JemmaPass shipped this compliance from day one of the hackathon by pinning requery:sqlite-android:3.49.0 (the first version with 16 KB-aligned libsqlite3x.so).

APK signature · tamper-evident

The APK is signed with a debug key (per hackathon distribution norms). To verify the APK you downloaded matches what we built:

📄 Step 1 · Verify SHA-256 Bash
shasum -a 256 jemmapass-v1.0.14-release.apk
# The expected SHA-256 is published on hackathon.html#apk after the final release build.
# Compare your output against that published hash.
# If they match → the bytes are identical to our submission.
📄 Step 2 · Verify APK Signature Scheme v2/v3 (Android tooling) Bash
# Path to apksigner from Android SDK build-tools
APKSIGNER=$ANDROID_HOME/build-tools/35.0.0/apksigner

# Verify
$APKSIGNER verify --verbose jemmapass-v1.0.14-release.apk

# Expected output:
# Verifies
# Verified using v1 scheme (JAR signing): false
# Verified using v2 scheme (APK Signature Scheme v2): true
# Verified using v3 scheme (APK Signature Scheme v3): true
# Verified using v4 scheme (APK Signature Scheme v4): false
# Number of signers: 1
📄 Step 3 · Inspect signer certificate Bash
$APKSIGNER verify --print-certs jemmapass-v1.0.14-release.apk

# Should show the certificate fingerprint matching what we publish
# on the hackathon page. Any mismatch = the APK was re-signed by someone else.
⚠️ About the debug signature. JemmaPass ships with a debug-signed APK for hackathon distribution. This is intentional: a debug key is throwaway, public, and self-generated by the SDK. For a production release, the APK should be re-signed with a Play Store-grade key — but that's a deployment concern, not a hackathon submission concern. The SHA-256 of the bytes is what proves the artifact is ours.

Install & test in 8 minutes

A judge with a Pixel 9 and a USB cable can validate the full claim of "100% offline operation" in under 10 minutes.

~1 min
✅ Step 1 · Install the APK

Enable "Install unknown apps" on your file manager → tap the APK file → confirm install. No Play Store, no Google account required.

~5 min
📥 Step 2 · First-boot model + KB download

On first launch, JemmaPass downloads Gemma 4 E4B (3.4 GB) and knowledge_full.db (3.36 GB) from jemmapass.net/models/ over Wi-Fi. This is the only time the app touches the network.

10 sec
✈️ Step 3 · ENABLE AIRPLANE MODE

Pull down the notification shade. Tap the airplane icon. Wait 5 seconds for radios to fully shut down. From this point on, the app cannot reach the internet — period.

~30 sec
👤 Step 4 · Onboard a profile

Voice your name + birth date. Add an allergy by voice ("I'm allergic to penicillin"). Scan a medication box with the camera. Watch Gemma 4 resolve everything to clinical codes locally.

~10 sec
📱 Step 5 · Generate & display QR

Tap "Share". The _j2: QR appears. Note its size (single QR, no multi-frame splitting for a typical profile).

~30 sec
🔁 Step 6 · Scan it back

Take a second Android device (or your iPhone with native Camera). Scan the QR. The profile loads instantly. On iPhone, the multilingual text fallback channel shows the allergy in English/Japanese.

~5 sec
🚨 Step 7 · Trigger the red alert

With the penicillin-allergic profile loaded, scan an Augmentin box (or any beta-lactam). RED ALERT fires in <200 ms with localized TTS. This is the killer moment of the demo, reproducible on your device.

~30 sec
📡 Step 8 · Test Nearby SOS (optional, 2 devices needed)

On device A, enable SOS Mode. On device B (within ~10 m), open Rescuer Mode. Device A's pruned profile appears on device B within ~6 seconds, having traveled over BLE + Wi-Fi Direct only.

Skeptical? Prove the offline claim

Two ways to forensically verify that JemmaPass makes ZERO network calls during clinical operations (after the initial model download).

Method 1 · adb network monitor

📄 Capture all network attempts from the app Bash
# Find the JemmaPass UID
APP_UID=$(adb shell dumpsys package be.heyman.android.jemmapassdemo | grep userId | head -1 | awk '{print $1}' | cut -d= -f2)

# Reset network counters
adb shell cmd netstats reset

# Run the full demo flow on the device

# Capture stats
adb shell cmd netstats get --uid $APP_UID

# Expected during the demo (with airplane mode):
# rxBytes: 0
# txBytes: 0

Method 2 · Faraday cage / aluminum-foil wrap

Wrap the Pixel 9 in two layers of aluminum foil (cellular + Wi-Fi + BLE all blocked). Open JemmaPass. Run the full demo. Everything works. Unwrap. Compare. There is no difference because there are no network calls being silently made.

💡 The hard guarantee. Search the source for OkHttp, Retrofit, HttpURLConnection, or any networking primitive. You'll find them only in two places: (1) the first-boot model downloader (which gates itself on Wi-Fi presence), and (2) the optional crash-report upload (off by default in v1.0.14). No clinical decision touches the network.

Numbers speak louder

Reproducibility proves the artifact is real. The benchmarks page shows it's actually fast.

📊 Benchmarks ❓ Anticipated FAQ ← Hub