kazeia/kazeia-android/app/build.gradle.kts

193 lines
7.4 KiB
Plaintext

import java.util.Properties
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
}
// Identifiants WebDAV de distribution (Nextcloud) lus depuis local.properties
// — jamais commités. Voir local.properties + project_kazeia_installer_updates.
val localProps = Properties().apply {
val f = rootProject.file("local.properties")
if (f.exists()) f.inputStream().use { load(it) }
}
fun localProp(key: String, default: String = ""): String =
localProps.getProperty(key) ?: default
// Keystore release — identifiants lus depuis /opt/Kazeia/keystore/credentials.properties
// (hors git, à SAUVEGARDER hors machine). Voir docs/RELEASE_SIGNING.md.
// Absent (autre machine) → le build release retombe sur la clé debug avec un warning.
val releaseKeystoreProps = Properties().apply {
val f = file("/opt/Kazeia/keystore/credentials.properties")
if (f.exists()) f.inputStream().use { load(it) }
}
val hasReleaseKeystore = releaseKeystoreProps.getProperty("storeFile")
?.let { file(it).exists() } == true
android {
namespace = "com.kazeia"
compileSdk = 36
ndkVersion = "27.3.13750724"
signingConfigs {
if (hasReleaseKeystore) {
create("release") {
storeFile = file(releaseKeystoreProps.getProperty("storeFile"))
storePassword = releaseKeystoreProps.getProperty("storePassword")
keyAlias = releaseKeystoreProps.getProperty("keyAlias")
keyPassword = releaseKeystoreProps.getProperty("keyPassword")
}
}
}
defaultConfig {
applicationId = "com.kazeia"
minSdk = 28
targetSdk = 36
versionCode = 14
versionName = "0.2.2"
// WebDAV de distribution — injecté depuis local.properties.
buildConfigField("String", "WEBDAV_BASE", "\"${localProp("webdav.base")}\"")
buildConfigField("String", "WEBDAV_USER", "\"${localProp("webdav.user")}\"")
buildConfigField("String", "WEBDAV_PASS", "\"${localProp("webdav.pass")}\"")
ndk {
abiFilters += "arm64-v8a"
}
externalNativeBuild {
cmake {
cppFlags += "-std=c++17"
arguments += "-DANDROID_STL=c++_shared"
}
}
}
externalNativeBuild {
cmake {
path = file("src/main/jni/CMakeLists.txt")
version = "3.22.1"
}
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
if (hasReleaseKeystore) {
signingConfig = signingConfigs.getByName("release")
} else {
logger.warn("⚠ keystore release absent (/opt/Kazeia/keystore/) — release signé en DEBUG. Voir docs/RELEASE_SIGNING.md")
signingConfig = signingConfigs.getByName("debug")
}
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
buildFeatures {
viewBinding = true
buildConfig = true
}
sourceSets {
getByName("main") {
jniLibs.srcDirs("src/main/jniLibs")
}
}
packaging {
resources {
// DJL `tokenizers` embarque des natifs desktop (macOS/Windows) inutiles
// sur Android (~23 Mo) ; seul l'arm64 de `tokenizer-native` sert. On les
// exclut pour alléger l'APK (payload self-update OTA).
excludes += "native/lib/osx-**"
excludes += "native/lib/win-**"
excludes += "native/lib/linux-**"
// JNA (transitif via sqlcipher/DJL) embarque des natifs aix/darwin/win
// (~2,3 Mo) inutiles sur Android — aucun natif android-aarch64 fourni et
// JNA non utilisé dans le code. APK = binaires utiles uniquement.
excludes += "com/sun/jna/**"
}
}
}
// Reproductibilité des jniLibs : les .so (gitignorés, 5 chaînes de build) doivent
// correspondre au manifest versionné. Un build RELEASE avec des libs divergentes
// échoue ; le debug reste libre (itération engine). Cf scripts/jnilibs.sh.
val verifyJniLibs = tasks.register<Exec>("verifyJniLibs") {
commandLine("bash", rootProject.file("scripts/jnilibs.sh").absolutePath, "verify")
}
tasks.matching { it.name == "preReleaseBuild" }.configureEach {
dependsOn(verifyJniLibs)
}
dependencies {
// Tests unitaires JVM (src/test/) — logique pure : CrisisGuard, VectorIndex, Chunker.
// Lancer : ./gradlew :app:testDebugUnitTest
testImplementation("junit:junit:4.13.2")
// Android
implementation("androidx.core:core-ktx:1.15.0")
implementation("androidx.appcompat:appcompat:1.7.0")
implementation("androidx.recyclerview:recyclerview:1.4.0")
implementation("com.google.android.material:material:1.12.0")
implementation("androidx.constraintlayout:constraintlayout:2.2.1")
// Coroutines
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
// Lifecycle (StateFlow observation)
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.7")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7")
// ONNX Runtime (for Silero VAD)
implementation("com.microsoft.onnxruntime:onnxruntime-android-qnn:1.24.3")
// LiteRT + QNN (for Whisper NPU)
implementation("com.google.ai.edge.litert:litert:1.4.2")
implementation("com.google.ai.edge.litert:litert-api:1.4.2")
implementation("com.qualcomm.qti:qnn-litert-delegate:2.44.0")
implementation("com.qualcomm.qti:qnn-runtime:2.44.0")
// (ExecuTorch jar + fbjni + soloader retirés 2026-06-18 : seul le TTS legacy
// Qwen3 les utilisait, supprimé avec la bascule CosyVoice. Le LLM .pte passe
// par libkazeia_pte autonome, pas par org.pytorch.executorch.)
// Tokeniseur HF (DJL) — pour PteLlmEngine (.pte NPU) : tokenise le ChatML Qwen
// côté Kotlin puis passe les IDs au natif (tokeniseur natif de l'engine cassé pour Qwen).
// L'artefact `tokenizers` ne porte QUE les natifs desktop (osx/win) ; le natif Android
// arm64 (libdjl_tokenizer.so) vit dans l'AAR `ai.djl.android:tokenizer-native`, dont la
// seule version publiée est 0.33.0 → on aligne les DEUX sur 0.33.0 (DJL exige l'égalité).
implementation("ai.djl.huggingface:tokenizers:0.33.0")
implementation("ai.djl.android:tokenizer-native:0.33.0")
// OkHttp — client WebDAV pour téléchargement modèles depuis Nextcloud
implementation("com.squareup.okhttp3:okhttp:4.12.0")
// WorkManager — orchestration du téléchargement modèles (foreground, reprise)
implementation("androidx.work:work-runtime-ktx:2.9.1")
// SQLCipher for encrypted conversation history (RGPD / secret médical)
implementation("net.zetetic:sqlcipher-android:4.5.4@aar")
implementation("androidx.sqlite:sqlite-ktx:2.4.0")
// EncryptedSharedPreferences pour stocker la passphrase SQLCipher
// (clef wrappée par Android Keystore, persistante).
implementation("androidx.security:security-crypto:1.1.0-alpha06")
// Unity as a Library (UaaL) — DISABLED
// implementation(project(":unityLibrary"))
// implementation("androidx.games:games-activity:3.0.5")
// compileOnly(files("../unityLibrary/unityLibrary/libs/unity-classes.jar"))
}