bindings/android/README.md
Android bindings provide a Kotlin API for GenieX using a JNI bridge pattern with 4 layers:
┌─────────────────────────────────────────────────────────┐
│ Layer 4: Public API (Kotlin) │
│ ModelWrapper.kt - Coroutine-based high-level API │
│ (LlmWrapper, VlmWrapper) │
└────────────────┬────────────────────────────────────────┘
│ calls
┌────────────────▼────────────────────────────────────────┐
│ Layer 3: JNI Interface (Kotlin) │
│ Model.kt - Declares external native methods │
│ (Llm, Vlm) │
└────────────────┬────────────────────────────────────────┘
│ JNI boundary
┌────────────────▼────────────────────────────────────────┐
│ Layer 2: JNI Bridge (C++) │
│ model_bridge_jni.cpp - Implements JNI methods │
│ Java_com_geniex_sdk_jni_Model_* functions │
└────────────────┬────────────────────────────────────────┘
│ calls C API
┌────────────────▼────────────────────────────────────────┐
│ Layer 1: Core Library (C) │
│ libgeniex.so - Provides ml_* API from ml.h │
│ (ml_llm_create, ml_llm_generate, etc.) │
└─────────────────────────────────────────────────────────┘
Each AI capability (LLM, VLM) follows this pattern:
app/src/main/java/com/geniex/sdk/LlmWrapper.ktLlmWrapper.builder().llmCreateInput(...).build()app/src/main/java/com/geniex/sdk/jni/Llm.ktexternal fun create(llmCreateInputObj: LlmCreateInput): Long
external fun destroy(handle: Long)
external fun generate(handle: Long, prompt: String, config: GenerationConfig, cb: LLMTokenCallback): LlmGenerateResult
external fun stopStream(handle: Long)
external fun applyChatTemplate(handle: Long, messages: Array<ChatMessage>, tools: String?, enableThinking: Boolean): LlmApplyChatTemplateOutput
app/src/main/cpp/llm_bridge_jni.cppJava_com_geniex_sdk_jni_Llm_create → calls ml_llm_create()Java_com_geniex_sdk_jni_Llm_destroy → calls ml_llm_destroy()Java_com_geniex_sdk_jni_Llm_generate → calls ml_llm_generate()Java_com_geniex_sdk_jni_Llm_stopStream → manages stop flagsJava_com_geniex_sdk_jni_Llm_applyChatTemplate → calls ml_llm_apply_chat_template()../../../build-android/out/libgeniex.so../../../include/ml.h../../../src/*.cpp (llm.cpp, vlm.cpp, etc.)| Component | Wrapper | JNI Interface | JNI Bridge | Core API |
|---|---|---|---|---|
| Vision-Language | VlmWrapper.kt | Vlm.kt | vlm_bridge_jni.cpp | mlvlm* |
../../../build_android.shapp/src/main/cpp/CMakeLists.txtlibnpu_jni.so (JNI bridge wrapper loaded by GenieXSdk.kt)libgeniex.so (core ML library linked by JNI wrapper)libgeniex_plugin.so (NPU backend for NPU acceleration)init {
System.loadLibrary("npu_jni") // Loads Layer 2 JNI bridge
}
../../../build-android/out/npu/GenieXSdk.init() calls registerPlugin() to dynamically load plugin librariesbindings/android/
├── app/
│ ├── src/main/
│ │ ├── cpp/ # Layer 2: JNI Bridge (C++)
│ │ │ ├── llm_bridge_jni.cpp
│ │ │ ├── vlm_bridge_jni.cpp
│ │ │ ├── geniex_sdk.cpp # SDK initialization & plugin registration
│ │ │ ├── jniutils.cpp/.h # JNI type conversion utilities
│ │ │ ├── jni_cb.cpp/.h # Callback handling for streaming
│ │ │ ├── qnn/CMakeLists.txt # NPU backend build config (QNN library)
│ │ │ └── CMakeLists.txt
│ │ └── java/com/geniex/sdk/
│ │ ├── jni/ # Layer 3: JNI Interface (Kotlin)
│ │ │ ├── Llm.kt
│ │ │ └── Vlm.kt
│ │ ├── LlmWrapper.kt # Layer 4: Public API
│ │ ├── VlmWrapper.kt
│ │ ├── GenieXSdk.kt # SDK entry point
│ │ └── bean/ # Data classes
│ └── build.gradle.kts # Build configuration
└── README.md # This file
../../include/ml.h # Layer 1: Core C API header
../../src/*.cpp # Layer 1: Core implementation
../../build-android/out/
├── libgeniex.so # Layer 1: Core library
└── npu/ # NPU plugin libraries (QNN-based)
└── libgeniex_plugin.so
Generating the repo folder in maven format.
Under GenieX-bridge/bindings/android:
tmpVersion in app/update.gradle to the new version../gradlew assembleRelease../gradlew publish to obtain the repo folder.TODO: document the Maven Central publishing procedure.
TODO: document the GitHub-based Android artifact publishing instructions.
SDK logs are routed to logcat under the tag GenieXSdk at the corresponding
Android priority (VERBOSE/DEBUG/INFO/WARN/ERROR). Filter from your
app via the standard logcat tooling:
adb logcat -s GenieXSdk