Files
view-mate/app-glasses/src/main/kotlin/pw/binom/viewmate/glasses/GlassesApp.kt
T

89 lines
3.7 KiB
Kotlin

package pw.binom.viewmate.glasses
import android.app.Application
import android.content.Context
import com.rayneo.arsdk.android.MercurySDK
import java.io.File
import kotlinx.coroutines.flow.MutableStateFlow
/** Конфигурация очков: адрес WS-сервера телефона. Креды не нужны — очки просто экран. */
object GlassesConfig {
// Fallback: эмулятор — 10.0.2.2 (localhost хоста); на устройстве телефон
// находится авто-обнаружением по mDNS (_viewmate._tcp).
const val HOST_URL = "ws://10.0.2.2:8080/ws/glasses"
}
/**
* Application очков: создаёт и запускает HostConnection (WS-клиент к телефону).
* Синглтон-доступ через companion.
*/
class GlassesApp : Application() {
lateinit var hostConnection: HostConnection
private set
lateinit var movieController: MovieController
private set
/** Менеджер скачивания контента в память очков (отправку на телефон — через HostConnection). */
lateinit var downloadManager: GlassesDownloadManager
private set
private val prefs by lazy {
getSharedPreferences("viewmate_prefs", Context.MODE_PRIVATE)
}
/** Масштаб экрана очков (0.5..1.0). Загружается в onCreate (prefs — после привязки контекста). */
val scale = MutableStateFlow(1f)
/** Идёт распознавание речи (TripleClick стартовал, Click/DoubleClick/тишина завершили). */
val listening = MutableStateFlow(false)
/** Накопленный текст распознавания (для оверлея); обновляется на SttPhrase. */
val sttText = MutableStateFlow("")
/** Текст ответа ассистента (обновляется на ShowText); остаётся до новой сессии. */
val assistantText = MutableStateFlow("")
/** Текущая Activity (для закрытия приложения по команде с телефона). */
var mainActivity: MainActivity? = null
/** Применить и сохранить масштаб. */
fun applyScale(value: Float) {
val v = value.coerceIn(0.5f, 1f)
scale.value = v
prefs.edit().putFloat("scale", v).apply()
}
override fun onCreate() {
super.onCreate()
instance = this
scale.value = prefs.getFloat("scale", 1f).coerceIn(0.5f, 1f)
MercurySDK.init(this)
movieController = MovieController(applicationContext)
movieController.eventLogger = { msg -> logToFile("mc: $msg") }
downloadManager = GlassesDownloadManager(applicationContext) { msg -> hostConnection.sendToHost(msg) }
hostConnection = HostConnection(
fallbackUrl = GlassesConfig.HOST_URL,
movieController = movieController,
downloadManager = downloadManager,
context = applicationContext,
)
hostConnection.start()
log("app", "HostConnection стартует: mDNS-поиск, fallback: ${GlassesConfig.HOST_URL}")
}
companion object {
lateinit var instance: GlassesApp
private set
/** Диагностические события в filesDir/events.log (доступно из любой точки, в т.ч. MovieController). */
fun logToFile(msg: String) {
runCatching {
val f = File(instance.filesDir, "events.log")
f.appendText("${System.currentTimeMillis()} $msg\n")
}
}
}
}