78 lines
3.7 KiB
Kotlin
78 lines
3.7 KiB
Kotlin
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() {
|
||
|
||
/**
|
||
* 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"
|
||
}
|
||
}
|