AI summary
Minecraft: Java Edition launcher for Android, forked from ZalithLauncher2. Automatically tunes JVM settings based on device specs, resolves mod dependencies automatically, and supports Microsoft, Ely.by, and offline accounts. Requires a separate runtime component with JRE and LWJGL natives to actually launch the game.
Generated by AI. May contain inaccuracies.
About this app
NovaLauncher A Minecraft: Java Edition launcher for Android, forked from ZalithLauncher2.
NovaLauncher keeps the parts of Zalith that work well — the instance model, the version resolution pipeline and the native runtime approach — and rebuilds the surface around three ideas: a quiet interface, JVM tuning the user never has to think about, and mod management that resolves its own dependencies.
Package com.novalauncher Minimum Android 7.0, API 24 Target / compile API 35 Language Kotlin 2.0, Jetpack Compose Licence GPL-3.0-or-later, inherited from Zalith What is different from Zalith Area Zalith 2 NovaLauncher Minimum API 26 24, reaches Android 7 and 7.1 devices Build stack AGP 9.x preview, Gradle 9.5 AGP 8.7.3, Gradle 8.11.1, reproducible on CI today Modules 8 Gradle modules including vendored LWJGL trees Single :app module, runtime layer behind one interface JVM arguments User-editable text field Computed from the device, never shown as a knob Garbage collector Fixed per profile Chosen from heap size, core count and Java version Mod dependencies Manual Resolved automatically, breadth-first, cycle-safe Content providers CurseForge and Modrinth Same, plus Modrinth works with no API key Java runtimes Bundled Auto-detect, curated downloads, custom paths in Settings Accounts Microsoft, offline, authlib Microsoft, Ely.by and local, all first-class on day one The architectural debt this fork pays down: Zalith spreads launch logic across several modules with native code interleaved into the Kotlin call path. Nova isolates every native touchpoint behind game/NativeBridge.kt, so the entire launcher — accounts, downloads, resolution, tuning — builds, runs and unit-tests on a plain JVM with no Android device and no prebuilt .so files.
Automatic JVM tuning The defining feature. There is no "allocate memory" slider on the main path. core/device/DeviceProfile.kt reads total RAM, core count, per-core maximum frequency from sysfs, ABI, SDK level and the low-RAM flag, then scores the device into LOW / MID / HIGH / FLAGSHIP.
core/jvm/JvmTuner.kt turns that profile into a plan:
Heap — a tier-dependent fraction of physical RAM (42% low, 55% flagship), after reserving 1 GB for the system and 512 MB for the renderer, then a bonus scaled by installed mod count (up to +1536 MB past 250 mods), clamped to a 64 MB boundary. 32-bit ABIs are capped at 1 GB because the address space cannot take more.
Collector —
Condition Collector ≤2 cores, or heap ≤768 MB, or LOW tier Serial Java 17+, heap ≥3 GB, ≥4 performance cores G1, 30–50 ms pause target Java 11+, heap ≥2 GB, ≥6 cores G1 otherwise Parallel G1 additionally gets region size derived from heap, InitiatingHeapOccupancyPercent=32 to start concurrent marking before the mixed-GC cliff, and string deduplication. Every plan carries a rationale list, written into the launch log so a tuning decision can always be explained after the fact.
The whole tuner is pure — no Android imports — which is why it is covered by unit tests that assert heap never exceeds physical memory, -Xms never exceeds -Xmx, and 32-bit devices never get a 2 GB heap.
Accounts All three types ship working, sharing one Account model and one refresh path.
Microsoft — OAuth 2.0 device-code flow, so no embedded WebView and no client secret. Polls the token endpoint honouring authorization_pending and slow_down, then walks Xbox Live → XSTS → Minecraft Services → profile. XSTS failures are translated into readable text: 401 becomes "Xbox Live profile missing or account is a child account", 403 becomes a region message, rather than a raw status code.
Ely.by — Yggdrasil authenticate/refresh/validate/invalidate against authserver.ely.by, including two-factor via the password:code form. When an Ely.by account launches, authlib-injector is attached as a -javaagent if present so the session and skin resolve correctly.
Local — offline UUIDs generated with the same version-3 MD5 scheme vanilla uses (OfflinePlayer:<name>), verified in tests against UUID.nameUUIDFromBytes, so worlds keep their player data.
Tokens live in SharedPreferences outside cloud backup; AccountRepository refreshes any online account inside a mutex five minutes before expiry.
Mods, packs and dependency resolution ContentRepository presents Modrinth and CurseForge behind one interface. Modrinth needs no credentials and works immediately. CurseForge activates once a key is pasted into Settings; nothing in the repository ships a dead key.
Installing a mod runs a breadth-first walk over its dependency graph, bounded at 128 nodes and guarded against cycles by a visited set. Required dependencies are pulled, optional ones skipped unless asked for, incompatible and embedded ones ignored. For each dependency the best build is chosen by release type first and publish date second, filtered to the instance's Minecraft version and loader. Anything unresolvable is reported rather than silently dropped.
Modpacks are detected by content: modrinth.index.json or manifest.json. Both formats create the instance, install the loader, download every file with checksum verification, apply overrides, then hand back a blueprint with the Minecraft version and loader to install. Archive extraction is path-traversal safe — entries resolving outside the target directory are rejected.
Build Requirements: JDK 17, Android SDK with API 35 and build-tools, ~3 GB free RAM.
git clone https://github.com/<owner>/NovaLauncher.git cd NovaLauncher echo "sdk.dir=/path/to/Android/sdk" > local.properties
./gradlew :app:assembleDebug # debug APK ./gradlew :app:testDebugUnitTest # unit tests ./gradlew :app:assembleRelease # signed release, R8 enabled Outputs land in app/build/outputs/apk/.
Signing. The release type reads NOVA_KEYSTORE, NOVA_KEYSTORE_PASSWORD, NOVA_KEY_ALIAS and NOVA_KEY_PASSWORD from the environment, falling back to nova-release.jks in the project root. If no keystore exists the release build degrades to the debug key instead of failing, which keeps forks buildable.
Low-memory machines. R8 and dexing are the memory-hungry steps. On a builder with under ~3 GB, disable minification:
./gradlew :app:assembleRelease -Pnova.minify=false The published v0.1.0 APK was produced this way; it is signed and installable but not shrunk. Turn minification back on for a size-optimised release.
Runtime component This repository contains the complete launcher: accounts, downloads, version and loader resolution, mod management, JVM tuning and the full launch-command builder. It does not vendor the binaries that execute the JVM on Android — the ARM JRE, the GL translation layer and the LWJGL natives. Those are large, separately licensed artifacts from upstream projects.
GameActivity therefore runs the pipeline end to end and stops at the final exec, showing the resolved runtime, heap, collector, main class and argument count, and writing the complete command and environment to files/logs/launch-*.log. Everything up to that point is real and inspectable.
game/NativeBridge.kt is the single seam to fill: supply libnovaglue.so exporting the declared JNI functions, plus the GL driver set and LWJGL bundle. See docs/RUNTIME.md. No other file needs to change.
Layout app/src/main/java/com/novalauncher/ ├── core/ │ ├── device/ DeviceProfile, CPU and memory probing │ ├── jvm/ JvmTuner, the tuning engine │ └── util/ Outcome/NovaError, OkHttp client, paths, hashing ├── data/ │ ├── account/ Microsoft, Ely.by, local, repository │ ├── download/ parallel downloader, safe archive extraction │ ├── instance/ instance model and persistence │ ├── java/ runtime detection, catalog, install │ ├── minecraft/ manifest, inheritance merge, rule evaluation │ ├── modloader/ Fabric, Quilt, Forge, NeoForge │ ├── mods/ Modrinth, CurseForge, resolver, modpacks │ └── settings/ preferences ├── game/ argument builder, launcher, native seam └── ui/ Compose theme, navigation, screens Outcome<T> with a typed NovaError is used instead of exceptions across every I/O boundary, so each failure carries a message already written for a person.
Tests ./gradlew :app:testDebugUnitTest 25 tests over tuning invariants, the offline-UUID algorithm, Mojang's Java version matrix, rule evaluation including disallow precedence, Maven coordinate parsing and account expiry.
Contributing See CONTRIBUTING.md.
Licence GPL-3.0-or-later. NovaLauncher is a derivative of ZalithLauncher2, which is GPL-3.0; this fork keeps that licence. Not affiliated with Mojang or Microsoft.
About this version
- Version
- 0.1.0 (1)
- Size
- 12.74 MB
- Requires Android
- 7.0
- Target SDK
- 24
- Architecture
- arm64-v8a, armeabi-v7a, x86_64
- Downloads
- 41
- Updated
- Sep 16, 2026
- Package
- com.novalauncher
Similar apps
Ratings & reviews
- 50
- 40
- 30
- 20
- 10