Improved launch speed on app startup by moving init on demand.

This commit is contained in:
souravanand001 2026-06-19 00:44:26 +05:30
parent c3bce8f807
commit f8c9ac3bf6
6 changed files with 81 additions and 41 deletions

View file

@ -151,13 +151,18 @@ class MainActivity : ComponentActivity() {
}
}
var wasHandsFreeActive = false
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.isHandsFreeModeActive.collect { active ->
if (active) {
wasHandsFreeActive = true
startSpeechRecognition(isHandsFree = true)
} else {
speechRecognizerManager.stop()
if (wasHandsFreeActive) {
wasHandsFreeActive = false
speechRecognizerManager.stop()
}
}
}
}

View file

@ -161,14 +161,10 @@ class SpeechRecognizerManager(
fun preLoadModelAsync() {
val mode = settingsRepository.getSttMode()
if (modelManager.isModelDownloaded()) {
if (mode == SttMode.PARAKEET && modelManager.isModelDownloaded()) {
scope.launch(Dispatchers.IO) {
if (mode == SttMode.PARAKEET || mode == SttMode.HYBRID || mode == SttMode.NATIVE) {
initVad()
initOfflineRecognizer()
} else if (mode == SttMode.API) {
initVad()
}
initVad()
initOfflineRecognizer()
}
}
}

View file

@ -4,23 +4,43 @@ import android.content.Context
import com.app.assistant.config.SpeechConfig
import com.app.assistant.config.TtsApiProvider
import com.app.assistant.repository.SettingsRepository
import okhttp3.OkHttpClient
class ApiTtsManager(
private val context: Context,
private val settingsRepository: SettingsRepository,
private val okHttpClient: OkHttpClient,
private val onSpeakingStateChanged: (isSpeaking: Boolean) -> Unit
) : TtsManager {
private val edgeTtsApiManager = EdgeTtsApiManager(context, settingsRepository, ::handleSpeakingStateChanged)
private val googleTtsApiManager = GoogleTtsApiManager(context, settingsRepository, ::handleSpeakingStateChanged)
private var edgeTtsApiManager: EdgeTtsApiManager? = null
private var googleTtsApiManager: GoogleTtsApiManager? = null
private fun getEdgeTtsApiManager(): EdgeTtsApiManager {
return edgeTtsApiManager ?: EdgeTtsApiManager(
context,
settingsRepository,
okHttpClient,
::handleSpeakingStateChanged
).also { edgeTtsApiManager = it }
}
private fun getGoogleTtsApiManager(): GoogleTtsApiManager {
return googleTtsApiManager ?: GoogleTtsApiManager(
context,
settingsRepository,
okHttpClient,
::handleSpeakingStateChanged
).also { googleTtsApiManager = it }
}
private val activeProvider: TtsApiProvider
get() = SpeechConfig.ACTIVE_TTS_PROVIDER
private val currentManager: TtsManager
get() = when (activeProvider) {
TtsApiProvider.EDGE_TTS -> edgeTtsApiManager
TtsApiProvider.GOOGLE_TTS -> googleTtsApiManager
TtsApiProvider.EDGE_TTS -> getEdgeTtsApiManager()
TtsApiProvider.GOOGLE_TTS -> getGoogleTtsApiManager()
}
private fun handleSpeakingStateChanged(isSpeaking: Boolean) {
@ -30,23 +50,27 @@ class ApiTtsManager(
override fun speak(text: String, queueMode: Int) {
// Stop the other manager to prevent overlapped audio if provider was changed dynamically
when (activeProvider) {
TtsApiProvider.EDGE_TTS -> googleTtsApiManager.stop()
TtsApiProvider.GOOGLE_TTS -> edgeTtsApiManager.stop()
TtsApiProvider.EDGE_TTS -> googleTtsApiManager?.stop()
TtsApiProvider.GOOGLE_TTS -> edgeTtsApiManager?.stop()
}
currentManager.speak(text, queueMode)
}
override fun stop() {
edgeTtsApiManager.stop()
googleTtsApiManager.stop()
edgeTtsApiManager?.stop()
googleTtsApiManager?.stop()
}
override fun isSpeaking(): Boolean {
return currentManager.isSpeaking()
val manager = when (activeProvider) {
TtsApiProvider.EDGE_TTS -> edgeTtsApiManager
TtsApiProvider.GOOGLE_TTS -> googleTtsApiManager
}
return manager?.isSpeaking() ?: false
}
override fun shutdown() {
edgeTtsApiManager.shutdown()
googleTtsApiManager.shutdown()
edgeTtsApiManager?.shutdown()
googleTtsApiManager?.shutdown()
}
}

View file

@ -24,6 +24,7 @@ import java.util.concurrent.ConcurrentHashMap
class EdgeTtsApiManager(
private val context: Context,
private val settingsRepository: SettingsRepository,
okHttpClient: OkHttpClient,
private val onSpeakingStateChanged: (isSpeaking: Boolean) -> Unit
) : TtsManager {
@ -43,7 +44,7 @@ class EdgeTtsApiManager(
private var playbackJob: Job? = null
private var idleTimeoutJob: Job? = null
private val client = OkHttpClient.Builder()
private val client = okHttpClient.newBuilder()
.connectTimeout(5, java.util.concurrent.TimeUnit.SECONDS)
.readTimeout(5, java.util.concurrent.TimeUnit.SECONDS)
.writeTimeout(5, java.util.concurrent.TimeUnit.SECONDS)

View file

@ -29,6 +29,7 @@ import java.util.concurrent.ConcurrentHashMap
class GoogleTtsApiManager(
private val context: Context,
private val settingsRepository: SettingsRepository,
okHttpClient: OkHttpClient,
private val onSpeakingStateChanged: (isSpeaking: Boolean) -> Unit
) : TtsManager {
@ -44,7 +45,7 @@ class GoogleTtsApiManager(
private var generatorJob: Job? = null
private var playbackJob: Job? = null
private val client = OkHttpClient.Builder()
private val client = okHttpClient.newBuilder()
.connectTimeout(10, java.util.concurrent.TimeUnit.SECONDS)
.readTimeout(10, java.util.concurrent.TimeUnit.SECONDS)
.writeTimeout(10, java.util.concurrent.TimeUnit.SECONDS)

View file

@ -7,43 +7,56 @@ import java.io.File
class TtsEngineSelector(
private val context: Context,
private val settingsRepository: SettingsRepository,
private val okHttpClient: okhttp3.OkHttpClient = com.app.assistant.viewmodel.MainViewModelFactory.okHttpClient,
private val onSpeakingStateChanged: (isSpeaking: Boolean) -> Unit
) : TtsManager {
private val nativeTtsManager = NativeTtsManager(context, onSpeakingStateChanged)
private val offlineTtsManager = OfflineTtsManager(context, settingsRepository, onSpeakingStateChanged)
private val apiTtsManager = ApiTtsManager(context, settingsRepository, onSpeakingStateChanged)
private var nativeTtsManager: NativeTtsManager? = null
private var offlineTtsManager: OfflineTtsManager? = null
private var apiTtsManager: ApiTtsManager? = null
private fun getNativeTtsManager(): NativeTtsManager {
return nativeTtsManager ?: NativeTtsManager(context, onSpeakingStateChanged).also { nativeTtsManager = it }
}
private fun getOfflineTtsManager(): OfflineTtsManager {
return offlineTtsManager ?: OfflineTtsManager(context, settingsRepository, onSpeakingStateChanged).also { offlineTtsManager = it }
}
private fun getApiTtsManager(): ApiTtsManager {
return apiTtsManager ?: ApiTtsManager(context, settingsRepository, okHttpClient, onSpeakingStateChanged).also { apiTtsManager = it }
}
override fun speak(text: String, queueMode: Int) {
val mode = settingsRepository.getTtsMode()
if (queueMode == TtsManager.QUEUE_FLUSH) {
nativeTtsManager.stop()
offlineTtsManager.stop()
apiTtsManager.stop()
nativeTtsManager?.stop()
offlineTtsManager?.stop()
apiTtsManager?.stop()
}
when (mode) {
TtsMode.OFFLINE -> {
if (isOfflineModelInstalled()) {
offlineTtsManager.speak(text, queueMode)
getOfflineTtsManager().speak(text, queueMode)
} else {
nativeTtsManager.speak(text, queueMode)
getNativeTtsManager().speak(text, queueMode)
}
}
TtsMode.API -> {
apiTtsManager.speak(text, queueMode)
getApiTtsManager().speak(text, queueMode)
}
else -> {
nativeTtsManager.speak(text, queueMode)
getNativeTtsManager().speak(text, queueMode)
}
}
}
override fun stop() {
nativeTtsManager.stop()
offlineTtsManager.stop()
apiTtsManager.stop()
nativeTtsManager?.stop()
offlineTtsManager?.stop()
apiTtsManager?.stop()
}
override fun isSpeaking(): Boolean {
@ -51,24 +64,24 @@ class TtsEngineSelector(
return when (mode) {
TtsMode.OFFLINE -> {
if (isOfflineModelInstalled()) {
offlineTtsManager.isSpeaking()
offlineTtsManager?.isSpeaking() ?: false
} else {
nativeTtsManager.isSpeaking()
nativeTtsManager?.isSpeaking() ?: false
}
}
TtsMode.API -> {
apiTtsManager.isSpeaking()
apiTtsManager?.isSpeaking() ?: false
}
else -> {
nativeTtsManager.isSpeaking()
nativeTtsManager?.isSpeaking() ?: false
}
}
}
override fun shutdown() {
nativeTtsManager.shutdown()
offlineTtsManager.shutdown()
apiTtsManager.shutdown()
nativeTtsManager?.shutdown()
offlineTtsManager?.shutdown()
apiTtsManager?.shutdown()
}
private fun isOfflineModelInstalled(): Boolean {