Android-Entwicklung mit Lyx
Lyx kompiliert direkt zu Android-nativen .so-Bibliotheken ohne NDK-Toolchain. Die 17 Android-Units decken den vollständigen Workflow ab: NativeActivity, JNI, Logging, Asset-Manager, OpenGL ES 2, APK-Bau und mehr.
→ Guides · Cross-Compilation · std.android Referenz
Architektur
android/jni — JNI 1.6 Typ-Aliase (JNIEnv, jobject, jclass, jint, ...)
android/native_activity — ANativeActivity-Struct + Callback-Tabelle
android/app_glue — Worker-Thread-Glue (android_app, APP_CMD_*)
android/log — Logcat-Ausgabe via stderr
android/asset — Asset Manager (APK-Assets lesen)
android/native_window — ANativeWindow (Surface-Handle)
android/input — AInputQueue, AInputEvent (Touch, Keys)
android/sensor — ASensorManager, Beschleunigungssensor, Gyroskop
android/gles2 — OpenGL ES 2.0 (Context-Setup + Render-Loop)
android/looper — ALooper (Event-Loop-Integration)
android/manifest_gen — AndroidManifest.xml-Generator
android/apk_builder — APK-Paket erstellen (ZIP + Manifest + Classes.dex-Stub)
android/zip_writer — ZIP-Schreiber (Grundlage für APK)
android/random — arc4random / Bionic-Random
android/restrictions — Katalog der unter SELinux/Bionic gesperrten Syscalls
android/ioctl — ioctl-Nummern für ASHMEM, ALSA, V4L2
Schritt 1: Kompilieren für Android
# ARM64 Shared Library (Standard — alle Android-Geräte ab API 21):
lyxc mylib.lyx --target=android --output-type=shared-lib -o libmylib.so
# Mit explizitem API-Level (Default: 26 = Android 8.0):
lyxc mylib.lyx --target=android --android-api=29 --output-type=shared-lib -o libmylib.so
# Android x86_64 (Emulator):
lyxc mylib.lyx --target=android-x86_64 --output-type=shared-lib -o libmylib_x86.so
Das erzeugte .so enthält automatisch:
.note.android.identmit dem API-Level- Bionic-kompatibles ELF64 (ARM64)
- Kein
__libc_start_main(Shared Library hat keinen_start)
Schritt 2: JNI-Funktionen exportieren
Mit @jni wird der Funktionsname automatisch in das Java-Format Java_<class>_<method> umgeschrieben:
import std.android.jni;
import std.android.log;
// Aufruf aus Java/Kotlin: com.example.MyApp.hello()
@jni(class="com/example/MyApp", method="hello")
pub fn hello(env: JNIEnv, obj: jobject): void {
// Logcat-Ausgabe:
AndroidLogWrite(ANDROID_LOG_INFO, "MyApp"c, "hello() called"c);
}
// Aufruf aus Java/Kotlin: com.example.MyApp.add(int, int)
@jni(class="com/example/MyApp", method="add")
pub fn add(env: JNIEnv, obj: jobject, a: jint, b: jint): jlong {
return a + b;
}
Java-Seite:
public class MyApp {
static { System.loadLibrary("mylib"); }
public native void hello();
public native long add(int a, int b);
}
Schritt 3: Logging (Logcat)
import std.android.log;
// Einfache Ausgabe:
AndroidLogWrite(ANDROID_LOG_DEBUG, "MyTag"c, "Debug-Nachricht"c);
AndroidLogWrite(ANDROID_LOG_ERROR, "MyTag"c, "Fehler aufgetreten"c);
| Konstante | Level | Anzeige in logcat |
|---|---|---|
ANDROID_LOG_VERBOSE | 2 | V |
ANDROID_LOG_DEBUG | 3 | D |
ANDROID_LOG_INFO | 4 | I |
ANDROID_LOG_WARN | 5 | W |
ANDROID_LOG_ERROR | 6 | E |
ANDROID_LOG_FATAL | 7 | F |
NativeActivity (ohne Java-Activity)
Für rein native Anwendungen (kein Java-Code außer dem Minimal-Glue):
import std.android.native_activity;
import std.android.app_glue;
import std.android.log;
// Einstiegspunkt für NativeActivity:
pub fn android_main(app: int64): void {
// app ist ein Zeiger auf android_app-Struktur
// Ereignisschleife:
var running: int64 := 1;
while running {
// Nachrichten verarbeiten:
var cmd: int64 := peek64(app + 0); // vereinfacht
if cmd == APP_CMD_INIT_WINDOW {
AndroidLogWrite(ANDROID_LOG_INFO, "App"c, "Window initialized"c);
}
if cmd == APP_CMD_TERM_WINDOW {
running := 0;
}
}
}
APP_CMD_*-Konstanten:
| Konstante | Wert | Bedeutung |
|---|---|---|
APP_CMD_INIT_WINDOW | 1 | Surface bereit (Render-Start) |
APP_CMD_TERM_WINDOW | 2 | Surface wird zerstört |
APP_CMD_GAINED_FOCUS | 6 | App hat Fokus |
APP_CMD_LOST_FOCUS | 7 | App hat Fokus verloren |
APP_CMD_PAUSE | 9 | App wird pausiert |
APP_CMD_RESUME | 10 | App wird fortgesetzt |
APP_CMD_STOP | 13 | App wird gestoppt |
APP_CMD_DESTROY | 14 | App wird zerstört |
Assets aus APK lesen
import std.android.asset;
// Asset-Manager aus ANativeActivity holen (via JNI übergeben):
var assetMgr: AAssetManager := 0; // aus NativeActivity.assetManager
// Asset öffnen (nur aus Lyx-Seite, wenn assetMgr als int64 übergeben):
// AAssetManager_open / AAsset_read werden via FFI aufgerufen
Asset-Zugriffsmodi:
| Konstante | Bedeutung |
|---|---|
AASSET_MODE_STREAMING | Sequentielles Lesen (vorwärts) |
AASSET_MODE_RANDOM | Beliebiger Zugriff (seek möglich) |
AASSET_MODE_BUFFER | Ganzes Asset in RAM mappen |
OpenGL ES 2 (gles2)
import std.android.gles2;
// Wichtigste GL-Konstanten:
// GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT
// GL_TRIANGLES, GL_TRIANGLE_STRIP
// GL_VERTEX_SHADER, GL_FRAGMENT_SHADER
// GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER
// GL_FLOAT, GL_UNSIGNED_SHORT
// Render-Frame (Beispiel):
// glClearColor(0.0, 0.0, 0.0, 1.0)
// glClear(GL_COLOR_BUFFER_BIT)
// ... Shader, VAO, Draw-Call ...
// eglSwapBuffers(display, surface)
APK erstellen
import std.android.apk_builder;
// Vollständiges APK aus .so + Manifest:
// ApkCreate("myapp.apk"c, "libmylib.so"c, manifest_xml, manifest_len);
Der APK-Builder nutzt android/zip_writer intern und erzeugt:
AndroidManifest.xml(ausandroid/manifest_gen)lib/arm64-v8a/libmylib.so- Minimaler
classes.dex-Stub (für NativeActivity-Aktivierung)
Eingeschränkte Syscalls (android/restrictions)
Unter Android/SELinux sind bestimmte Syscalls gesperrt:
import std.android.restrictions;
// ANDROID_BLOCKED_SYSCALLS enthält die Liste gesperrter Calls:
// fork(), execve(), ptrace(), setuid(), mount(), ...
// Für Netzwerk: bind() auf privilegierten Ports (< 1024) gesperrt
Statt fork() → Threads via std.thread. Statt execve() → Nativer JNI-Aufruf oder Intent.
Welche Unit wann?
| Szenario | Unit |
|---|---|
| Einfache JNI-Funktion aus Java aufrufen | android/jni + @jni-Annotation |
| Debug-Ausgabe in Logcat | android/log |
| Rein native App ohne Java | android/native_activity + android/app_glue |
| APK selbst bauen | android/apk_builder |
| Touch-Eingabe verarbeiten | android/input |
| Sensor-Daten (Gyro, Beschleunigung) | android/sensor |
| OpenGL ES 2 rendern | android/gles2 |
| APK-Assets lesen | android/asset |
Letzte Aktualisierung: 2026-06-08
