Entwickler

Android-App selbst bauen

Die APK des TRS Launchers aus dem Quellcode bauen: Android-SDK und NDK, Rust-Targets, Debug- und Release-Build, eigener Signierschlüssel und eigene App-ID.

Die Android-App ist dasselbe Tauri-2-Projekt wie der Launcher auf dem PC, nur für Android gebaut. Diese Seite ist für alle, die mitentwickeln, und für Spieler, die ihre eigene APK bauen und installieren möchten. Wenn du nur spielen willst, nimm die signierte APK von unserer Website – siehe Android: APK installieren.

Was du bekommst: die komplette App – Anmeldung, Instanzen, Modpacks, Sozial, Garderobe und Minecraft: Java Edition über die eingebaute Spiel-Engine mit Touch-Steuerung. Was du nicht bekommst: automatische Updates. Die App fragt zwar unseren offiziellen Update-Kanal ab, aber Android installiert ein Update nur mit gleichem Paketnamen und gleichem Signierschlüssel – dein Build hat einen anderen Schlüssel, also aktualisierst du ihn, indem du neu baust.

Die Befehle hier sind die, die das CI nutzt (.github/workflows/ci.yml und release.yml, Jobs Android), plus die Hinweise für lokale Builds aus docs/mobile.md im Repository. Das CI baut unter Linux, lokale Builds sind für Windows beschrieben. Unter macOS ist der Android-Build nicht getestet.

Was wo liegt

PfadWas es ist
src-tauri/gen/android/Das Gradle-Projekt der App (eingecheckt, minSdk 26 = Android 8.0)
src-tauri/gen/android/app/build.gradle.ktsApp-ID, SDK-Stufen, Release-Signatur
src-tauri/tauri.android.conf.jsonAndroid-Abweichungen der Tauri-Konfiguration (kein Desktop-Updater, keine mitgelieferten TRS-Client-Jars)
src-tauri/plugins/tauri-plugin-trs-game/android/Die Spiel-Engine (Teile von Amethyst/PojavLauncher, ndk-build) und das Touch-Overlay
src-tauri/plugins/tauri-plugin-trs-game/android/prebuilt.lockFertige Engine-Teile, die Gradle lädt und per SHA-256 prüft

Voraussetzungen

WerkzeugVersion (wie im CI)
Node.js und pnpmNode 22, pnpm in der Version aus package.json (corepack enable)
Ruststable über rustup, Targets aarch64-linux-android (Handys) und x86_64-linux-android (Emulator)
JDK21 (CI: Temurin; das JBR aus Android Studio geht auch)
Android-SDKmit cmdline-tools und platform-tools
Android-NDK28.2.13676358 für die App (NDK_HOME) und 27.3.13750724 (r27d) für die Spiel-Engine
Gradlenichts zu installieren – der Wrapper in src-tauri/gen/android nimmt Gradle 8.14.3

Die App wird gegen Android-SDK 36 gebaut (compileSdk/targetSdk). Im CI werden nur platform-tools und die beiden NDKs von Hand installiert, den Rest holt das Android-Gradle-Plugin. Nimm die SDK-Lizenzen einmal mit sdkmanager --licenses an.

Du brauchst beide NDKs. Das Spiel-Plugin legt in seiner eigenen build.gradle.ktsndkVersion = "27.3.13750724" fest; der Rust-Teil wird mit dem NDK aus NDK_HOME (28.2) gelinkt.

Debug-APK bauen

Code holen

git clone https://github.com/theredstonee/TRS-Launcher.git
cd TRS-Launcher
pnpm install

SDK-Teile und Rust-Targets installieren

sdkmanager --install "platform-tools" "ndk;28.2.13676358" "ndk;27.3.13750724"
rustup target add aarch64-linux-android x86_64-linux-android

Die beiden NDK-Versionen kannst du auch in Android Studio installieren (SDK Manager → SDK Tools → NDK (Side by side), Haken bei Show Package Details).

Umgebung setzen

Unter Windows (PowerShell) oder Linux:

$env:ANDROID_HOME = "$env:LOCALAPPDATA\Android\Sdk"
$env:NDK_HOME     = "$env:ANDROID_HOME\ndk\28.2.13676358"
$env:JAVA_HOME    = "C:\Program Files\Android\Android Studio\jbr"

Unter Windows schaltest du vorher den Entwicklermodus ein – siehe Probleme.

Bauen

pnpm tauri android build --apk --debug --target aarch64

Das baut die Oberfläche (pnpm generate), die Rust-Bibliothek für arm64 und dann mit Gradle die APK. Der erste Gradle-Lauf lädt die fertigen Engine-Teile aus prebuilt.lock (per SHA-256 geprüft, zwischengespeichert in ~/.gradle/caches/trs-engine-prebuilt) – er braucht also Internet und dauert eine Weile.

APK finden

Die APKs landen unter src-tauri/gen/android/app/build/outputs/apk/, in einem Ordner je ABI und Build-Art. Das CI verlässt sich nicht auf den genauen Ordnernamen – du musst es auch nicht:

find src-tauri/gen/android/app/build/outputs/apk -name '*.apk'

Aufs Handy bringen

Schalte in den Entwickleroptionen deines Handys USB-Debugging ein, schließ es an und starte:

adb install -r pfad/zur.apk

Oder kopier die APK aufs Handy und öffne sie dort, wie unter Android: APK installieren beschrieben. Eine Debug-APK ist mit dem Debug-Schlüssel deines Android-SDK signiert und lässt sich sofort installieren.

Ein Debug-Build und unsere offizielle App haben den gleichen Paketnamen, aber verschiedene Schlüssel. Android installiert die eine nicht über die andere („App nicht installiert“ / „Konflikt mit vorhandenem Paket“). Deinstalliere vorher die andere – damit sind auch ihre Instanzen und Welten weg – oder gib deinem Build eine eigene App-ID (siehe unten).

Für den Emulator

pnpm tauri android build --apk --debug --target x86_64

Starte den Emulator mit -gpu host – mit SwiftShader stürzt der Renderer bei seiner Vulkan-Prüfung ab. Minecraft 26.x ist im Emulator nicht spielbar (seinem Vulkan fehlen nötige Erweiterungen, und OpenGL hängt dort); teste diese Versionen auf einem echten Handy.

Release-APK bauen

pnpm tauri android build --apk --target aarch64

Das ist der Release-Befehl des CI ohne --ci. Release-Builds werden mit R8 verkleinert. Ohne Signierschlüssel kommt eine unsignierte APK heraus (…-unsigned.apk) – die kann Android nicht installieren. Signiere sie mit deinem eigenen Schlüssel:

Einmal einen Keystore anlegen

keytool -genkeypair -v -keystore my-release.jks -alias my-key \
  -keyalg RSA -keysize 4096 -validity 10000

keytool gehört zum JDK. Heb Datei und Passwörter gut auf: Android installiert Updates einer App nur, wenn sie mit demselben Schlüssel signiert sind.

Die vier Variablen setzen

Gradle signiert die Release-APK selbst (signingConfigs in src-tauri/gen/android/app/build.gradle.kts), sobald ANDROID_KEYSTORE_PATH auf eine vorhandene Datei zeigt:

export ANDROID_KEYSTORE_PATH=/pfad/zu/my-release.jks
export ANDROID_KEYSTORE_PASSWORD='…'
export ANDROID_KEY_ALIAS=my-key
export ANDROID_KEY_PASSWORD='…'      # wie das Keystore-Passwort, wenn du kein anderes gewählt hast

Unter Windows setzt du sie wie oben mit $env:NAME = "…".

Bauen und prüfen

pnpm tauri android build --apk --target aarch64
"$ANDROID_HOME"/build-tools/<version>/apksigner verify --print-certs <die.apk>

apksigner zeigt den SHA-256 deines Zertifikats – nicht den auf der Installationsseite, der gehört zu unserem offiziellen Schlüssel.

Geheimnisse des Projekts brauchst du keine. Der Schlüssel des Desktop-Updaters (TAURI_SIGNING_PRIVATE_KEY) signiert im Release-Workflow nur die Dateien des Update-Kanals, und Android-Builds erzeugen ohnehin keine Updater-Dateien (tauri.android.conf.json). Der CurseForge-Schlüssel ist wie auf dem PC freiwillig: Umgebungsvariable CURSEFORGE_API_KEY oder die Datei ~/.tauri/curseforge-api-key (%USERPROFILE%\.tauri\curseforge-api-key unter Windows). Ohne ihn klappt der Build, CurseForge ist dann einfach ausgeblendet.

Zu deiner eigenen App machen

Wenn du deinen Build neben der offiziellen App installieren oder mit Freunden teilen willst, gib ihm eine eigene App-ID und einen eigenen Namen:

WasWoÄndern
App-ID (Paketname)src-tauri/gen/android/app/build.gradle.ktsapplicationId = "dev.theredstonee.trslauncher" → zum Beispiel "io.github.deinname.trslauncher"
Name auf dem Startbildschirmsrc-tauri/gen/android/app/src/main/res/values/strings.xmlapp_name und main_activity_title
Symbolsrc-tauri/gen/android/app/src/main/res/mipmap-*/ic_launcher*.png (die ic_launcher_halloween*-Dateien sind das Event-Symbol)
Signierschlüsseldein eigener Keystoresiehe oben
Ändere nur applicationId – nicht namespace in derselben Datei und nicht identifier in src-tauri/tauri.conf.json. Das Kotlin-Paket dev.theredstonee.trslauncher steckt fest im Rust-Code (register_android_plugin in src-tauri/src/mobile.rs, die JNI-Funktion Java_dev_theredstonee_trslauncher_PushPollWorker_nativePoll in src-tauri/src/push.rs), und die Tauri-CLI bricht den Build mit „you have modified your "identifier" in the Tauri configuration“ ab, wenn der Identifier nicht mehr zum Kotlin-Ordner passt. Engine- und Push-Plugin lesen den Paketnamen zur Laufzeit – für sie ist eine neue applicationId kein Problem.

Was in deinem eigenen Build laut Code weiter funktioniert:

  • Microsoft-Anmeldung: Die App nutzt die Anmeldung per Gerätecode (du tippst einen Code auf der Microsoft-Seite ein). Sie hängt nicht am Paketnamen und nicht an einer Weiterleitung in die App.
  • TRS-Dienste (Freunde, Chat, Umhänge, TRS-API): Die App spricht mit derselben API; Paketname oder Signatur werden nicht geprüft.
  • Links wie trs-launcher://pack/<code> haben in jedem Build dasselbe Schema. Sind offizielle App und dein Build beide installiert, fragt Android, welche App sie öffnen soll.
  • Updates: siehe oben. Der Installer in der App nimmt nur eine APK mit dem eigenen Paketnamen an – er kann deinen Build also nicht durch die offizielle App ersetzen, und Android lehnt unsere APK über einem Build mit deinem Schlüssel ab.

Einen umbenannten Build haben wir selbst noch nicht getestet – wenn etwas nicht geht, melde es bitte.

Prüfungen ausführen

Dieselben Prüfungen wie im CI-Job Android:

pnpm generate                       # generate_context! braucht die gebaute Oberfläche
cd src-tauri
cargo clippy --workspace --target aarch64-linux-android -- -D warnings
cd gen/android
./gradlew --no-daemon :tauri-plugin-trs-game:testDebugUnitTest   # Touch-Overlay und Engine-Logik, ohne Gerät

Clippy läuft außerhalb von tauri android build und braucht für die C-Teile (SQLite, ring) den Compiler aus dem NDK. Das CI setzt dafür unter Linux:

bin="$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin"
export CC_aarch64_linux_android="$bin/aarch64-linux-android26-clang"
export AR_aarch64_linux_android="$bin/llvm-ar"
export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER="$bin/aarch64-linux-android26-clang"

Probleme

„A required privilege is not held by the client“

Unter Windows verlinkt tauri android build die Rust-Bibliothek per symbolischem Link nach gen/android/app/src/main/jniLibs. Ohne Entwicklermodus (oder Adminrechte) schlägt das fehl. Schalte den Entwicklermodus in den Windows-Einstellungen ein oder kopier die Bibliothek selbst (src-tauri/target/<triple>/debug/libtrs_launcher_lib.so → jniLibs/<abi>/) und starte den Gradle-Task in src-tauri/gen/android, für den Emulator gradlew assembleX86_64Debug.

NDK nicht gefunden oder falsche NDK-Version

NDK_HOME muss auf 28.2.13676358 zeigen, und 27.3.13750724 muss zusätzlich im ndk/-Ordner des SDK liegen. Liegt dein r27d woanders, setz android.ndkPath in src-tauri/gen/android/local.properties oder die Variable ANDROID_NDK_HOME (siehe Kommentar in der build.gradle.kts des Plugins).

Die SDK-Einrichtung will das Paket „tools“

Das alte SDK-Paket tools gibt es mit aktuellen cmdline-tools nicht mehr. Installiere nur cmdline-tools, platform-tools und die beiden NDKs – so macht es auch das CI.

Die Release-APK lässt sich nicht installieren

Sie ist unsigniert (…-unsigned.apk). Setz die vier Signier-Variablen und bau neu, oder nimm einen Debug-Build.

„App nicht installiert“ oder „Konflikt mit vorhandenem Paket“

Es ist schon ein Build der App mit einem anderen Schlüssel installiert – oft unsere offizielle App. Deinstalliere sie vorher (damit sind ihre Instanzen weg) oder gib deinem Build eine eigene App-ID.

„SHA-256 stimmt nicht“ beim Laden der Engine-Teile

Ein Download aus prebuilt.lock passt nicht zu seiner Prüfsumme (zum Beispiel abgebrochene Verbindung oder ein Proxy). Die Datei wird verworfen; starte den Build noch einmal.

Das Spiel stürzt im Emulator ab oder 26.x startet dort nicht

Nimm -gpu host und teste Minecraft 26.x auf einem echten Handy (siehe Für den Emulator).

Die App lässt sich auf einem älteren oder 32-Bit-Handy nicht installieren

Die App braucht Android 8.0 und einen 64-Bit-Prozessor: Es werden nur arm64-v8a und x86_64 eingepackt, weil es die Spiel-Engine nur für 64 Bit gibt.

CurseForge fehlt

Der Build hatte keinen CurseForge-API-Schlüssel. Bei eigenen Builds ist das normal – siehe den Hinweis zum Schlüssel oben.

Lizenz und Name

Der TRS Launcher ist freie Software unter der GNU General Public License v3.0 (LICENSE, Urheberrechtshinweise in NOTICE). Du darfst die App bauen, ändern und weitergeben. Gibst du eine APK weiter, verlangt die GPL, dass das unter derselben Lizenz passiert und du den vollständigen Quellcode genau dieses Builds samt deiner Änderungen zugänglich machst. Die Spiel-Engine enthält Teile anderer Projekte mit eigenen Lizenzen (Amethyst/PojavLauncher unter LGPL-3.0 und weitere) – sie stehen in NOTICE und müssen drinbleiben.

Eigene Markenregeln hat das Repository nicht. Trotzdem: Wenn du deinen Build weitergibst, gib ihm einen eigenen Namen und eine eigene App-ID, damit ihn niemand für den offiziellen TRS Launcher hält, und verweise auf deinen Quellcode – nicht auf unseren Support.

Weiter geht's

iOS-App selbst bauen

Dasselbe für iPhone und iPad – braucht einen Mac mit Xcode.

Aus dem Quellcode bauen

Der Launcher für den PC, die Prüfungen und die TRS-Client-Mod.