agent: связь с сервером + UI-экраны + ASR Qwen3 + settings
This commit is contained in:
@@ -1,9 +1,77 @@
|
||||
package pw.binom.agentik.android
|
||||
|
||||
import android.app.Application
|
||||
import androidx.work.BackoffPolicy
|
||||
import androidx.work.Constraints
|
||||
import androidx.work.ExistingPeriodicWorkPolicy
|
||||
import androidx.work.NetworkType
|
||||
import androidx.work.PeriodicWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import pw.binom.agentik.android.agent.AgentConnection
|
||||
import pw.binom.agentik.android.agent.real.HttpAgentConnection
|
||||
import pw.binom.agentik.android.asr.QwenDownloadWorker
|
||||
import pw.binom.agentik.android.settings.SettingsRepository
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Точка входа приложения. Пока пустая: сюда будут подниматься настройки
|
||||
* (адрес агента и токен) и хранилище.
|
||||
* Точка входа приложения. Поднимает фоновые сервисы:
|
||||
* - периодический [QwenDownloadWorker]: раз в 6 часов проверяет/докачивает голосовую модель
|
||||
* Qwen3-ASR по Wi-Fi (UNMETERED). Зарегистрирован через [ExistingPeriodicWorkPolicy.KEEP],
|
||||
* чтобы перезапуск приложения не сбрасывал уже запланированный запуск и не дёргал воркер
|
||||
* лишний раз.
|
||||
* - singleton-фабрика [agentConnection] — единая точка подключения к агенту,
|
||||
* живёт до вызова `close()` (никогда в этой PR — приложение короткоживущее).
|
||||
* В фазах тестирования можно подменить на stub: `(application as AgentikApp).agentConnection = StubAgentConnection(...)`.
|
||||
* - [settingsRepository] — JSON-персистентность [pw.binom.agentik.android.settings.Settings]
|
||||
* в `filesDir/settings.json`. Передаётся в UI через [MainActivity].
|
||||
*/
|
||||
class AgentikApp : Application()
|
||||
class AgentikApp : Application() {
|
||||
|
||||
/**
|
||||
* Singleton-фабрика агента-фасада. Создаётся лениво при первом обращении,
|
||||
* живёт до вызова `close()` (никогда в этой PR — приложение короткоживущее).
|
||||
*
|
||||
* NB: используем `lateinit` (а не `by Delegates.notNull()`), чтобы
|
||||
* работал `::agentConnection.isInitialized` — `Delegates.notNull()`
|
||||
* делегат не поддерживает эту проверку.
|
||||
*/
|
||||
lateinit var agentConnection: AgentConnection
|
||||
private set
|
||||
|
||||
/**
|
||||
* Singleton-репозиторий для JSON-персистентности настроек в `filesDir/settings.json`.
|
||||
* Создаётся лениво при первом обращении (после `onCreate()`) — `Application`
|
||||
* сам передаёт себя как `Context`.
|
||||
*/
|
||||
val settingsRepository: SettingsRepository by lazy { SettingsRepository(this) }
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
if (!::agentConnection.isInitialized) {
|
||||
agentConnection = HttpAgentConnection(context = this)
|
||||
}
|
||||
scheduleQwenDownload()
|
||||
}
|
||||
|
||||
private fun scheduleQwenDownload() {
|
||||
val request = PeriodicWorkRequestBuilder<QwenDownloadWorker>(6, TimeUnit.HOURS)
|
||||
.setConstraints(
|
||||
Constraints.Builder()
|
||||
// Wi-Fi only — мобильная сеть не качает 940 МБ.
|
||||
.setRequiredNetworkType(NetworkType.UNMETERED)
|
||||
.build(),
|
||||
)
|
||||
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 30, TimeUnit.MINUTES)
|
||||
.build()
|
||||
|
||||
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
|
||||
UNIQUE_WORK_NAME,
|
||||
ExistingPeriodicWorkPolicy.KEEP,
|
||||
request,
|
||||
)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val UNIQUE_WORK_NAME = "qwen-model-download"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user