Сборка release: подпись ключом Binom (v2+v3) + таск assembleSigned

signingConfigs в app-phone/app-glasses берут кестор и креды из скилла
android-sign (вне git); без кестора release собирается без подписи.
assembleSigned — собрать оба приложения одним шагом.
This commit is contained in:
2026-09-04 03:08:28 +03:00
parent 5c86ed00b4
commit f68ea10342
3 changed files with 91 additions and 0 deletions
+42
View File
@@ -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<String, String> =
(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 (проверено на сыром дампе).
+39
View File
@@ -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<String, String> =
(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)
+10
View File
@@ -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")
}