diff --git a/app-glasses/build.gradle.kts b/app-glasses/build.gradle.kts index ade865e..487ab5e 100644 --- a/app-glasses/build.gradle.kts +++ b/app-glasses/build.gradle.kts @@ -1,3 +1,5 @@ +import java.io.File + plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) @@ -5,6 +7,20 @@ plugins { alias(libs.plugins.compose.compiler) } +// Подпись release ключом Binom (assembleRelease сам подпишет APK, v2+v3). Кестор + креды — +// из скилла android-sign (вне git); переопределение: -Pbinom.keystore.dir=... / env BINOM_KEYSTORE_DIR. +val binomCertsDir: File = File( + (project.findProperty("binom.keystore.dir") as? String) + ?: System.getenv("BINOM_KEYSTORE_DIR") + ?: "${System.getProperty("user.home")}/.config/opencode/skills/android-sign/certs" +) +val binomStoreFile = File(binomCertsDir, "android-release.keystore") +val binomCreds: Map = + (File(binomCertsDir, "creds.env").let { c -> if (binomStoreFile.exists() && c.exists()) + c.readLines().filter { it.isNotBlank() && !it.startsWith("#") && it.contains('=') } + .associate { val i = it.indexOf('='); it.substring(0, i) to it.substring(i + 1).trim().removeSurrounding("\"") } + else emptyMap() }) + android { namespace = "pw.binom.viewmate.glasses" compileSdk = 35 @@ -17,9 +33,30 @@ android { versionName = (project.findProperty("versionName") as? String) ?: "0.1.0" } + // Подпись release ключом Binom (всё из binomStoreFile/binomCreds выше). + // Без кестора binomCreds пусто → release остаётся неподписанным. + if (binomCreds.isNotEmpty()) { + val binomAlias = binomCreds.getValue("ANDROID_KEYSTORE_ALIAS") + val binomStorePass = binomCreds.getValue("ANDROID_KEYSTORE_PASSWORD") + val binomKeyPass = binomCreds["ANDROID_KEY_PASSWORD"] ?: binomStorePass + signingConfigs { + create("binom") { + storeFile = binomStoreFile + storePassword = binomStorePass + keyAlias = binomAlias + keyPassword = binomKeyPass + enableV1Signing = false + enableV2Signing = true + enableV3Signing = true + } + } + } buildTypes { release { isMinifyEnabled = false + if (binomCreds.isNotEmpty()) { + signingConfig = signingConfigs.getByName("binom") + } } } @@ -61,6 +98,11 @@ dependencies { implementation(project(":lib-core")) implementation("com.squareup.okhttp3:okhttp:4.12.0") + // Локальный Qwen3-ASR на очках (движок + распознавание переезжают на очки из app-phone). + // asr-qwen3-android тянет sherpa-onnx (nativ) транзитивно; модель — в filesDir/models + // (SttModelProvider), как на телефоне. + implementation("pw.binom.asr:asr-qwen3-android:4") + // VAD на очках (WebRTC VAD — лёгкий, без моделей; схема pair-view автора) // VAD (WebRTC) убран из прода: резал речь на рваном микрофоне ARGT78 — // whisper распознаёт полный поток без VAD (проверено на сыром дампе). diff --git a/app-phone/build.gradle.kts b/app-phone/build.gradle.kts index c0116a5..7157c9a 100644 --- a/app-phone/build.gradle.kts +++ b/app-phone/build.gradle.kts @@ -1,4 +1,5 @@ import java.util.Properties +import java.io.File plugins { alias(libs.plugins.android.application) @@ -7,6 +8,20 @@ plugins { alias(libs.plugins.compose.compiler) } +// Подпись release ключом Binom (assembleRelease сам подпишет APK, v2+v3). Кестор + креды — +// из скилла android-sign (вне git); переопределение: -Pbinom.keystore.dir=... / env BINOM_KEYSTORE_DIR. +val binomCertsDir: File = File( + (project.findProperty("binom.keystore.dir") as? String) + ?: System.getenv("BINOM_KEYSTORE_DIR") + ?: "${System.getProperty("user.home")}/.config/opencode/skills/android-sign/certs" +) +val binomStoreFile = File(binomCertsDir, "android-release.keystore") +val binomCreds: Map = + (File(binomCertsDir, "creds.env").let { c -> if (binomStoreFile.exists() && c.exists()) + c.readLines().filter { it.isNotBlank() && !it.startsWith("#") && it.contains('=') } + .associate { val i = it.indexOf('='); it.substring(0, i) to it.substring(i + 1).trim().removeSurrounding("\"") } + else emptyMap() }) + // LLM-ключ из local.properties (llm.apiKey) — файл вне git; пустой = ещё не задан. // providers.gradleProperty не читает local.properties, поэтому грузим файл вручную. val llmApiKey: String = run { @@ -47,9 +62,30 @@ android { buildConfigField("String", "LLM_MODEL", "\"$llmModel\"") } + // Подпись release ключом Binom (всё из binomStoreFile/binomCreds выше). + // Без кестора binomCreds пусто → release остаётся неподписанным. + if (binomCreds.isNotEmpty()) { + val binomAlias = binomCreds.getValue("ANDROID_KEYSTORE_ALIAS") + val binomStorePass = binomCreds.getValue("ANDROID_KEYSTORE_PASSWORD") + val binomKeyPass = binomCreds["ANDROID_KEY_PASSWORD"] ?: binomStorePass + signingConfigs { + create("binom") { + storeFile = binomStoreFile + storePassword = binomStorePass + keyAlias = binomAlias + keyPassword = binomKeyPass + enableV1Signing = false + enableV2Signing = true + enableV3Signing = true + } + } + } buildTypes { release { isMinifyEnabled = false + if (binomCreds.isNotEmpty()) { + signingConfig = signingConfigs.getByName("binom") + } } } @@ -97,6 +133,9 @@ dependencies { // RayNeo Mercury BLE protocol (RayNeo X2): pair/connect/команды с телефона implementation("pw.binom.mercury:rayneo-mercury:0.1.0-SNAPSHOT") + // QR-код для паринга очков (pairCode) — рендер BitMatrix->Bitmap + implementation("com.google.zxing:core:3.5.2") + // Koog (JetBrains) — LLM-клиент (OpenAI-совместимый) implementation(libs.koog.openai.client) implementation(libs.koog.http.client.okhttp) diff --git a/build.gradle.kts b/build.gradle.kts index 0106559..b735ddd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,3 +14,13 @@ allprojects { } group = "pw.binom.viewmate" } + +// Собери оба приложения и подпиши ключом Binom (v2+v3) одним шагом. +// Кестор/креды берутся из скилла android-sign (см. signingConfigs в build.gradle.kts каждого app-модуля); +// без кестора release соберётся без подписи. +tasks.register("assembleSigned") { + group = "build" + description = "Собирает app-phone и app-glasses release-APK, подписанные ключом Binom (v2+v3)." + dependsOn(":app-phone:assembleRelease", ":app-glasses:assembleRelease") +} +