Files
fast-messenger/app/src/main/kotlin/dev/meloda/fast/service/OnlineService.kt
T
2024-07-16 08:00:25 +03:00

117 lines
3.4 KiB
Kotlin

package dev.meloda.fast.service
import android.app.Service
import android.content.Intent
import android.os.IBinder
import android.util.Log
import dev.meloda.fast.common.UserConfig
import dev.meloda.fast.common.extensions.createTimerFlow
import dev.meloda.fast.data.api.account.AccountUseCase
import dev.meloda.fast.data.processState
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import org.koin.android.ext.android.inject
import kotlin.coroutines.CoroutineContext
import kotlin.time.Duration.Companion.minutes
class OnlineService : Service() {
private val job = SupervisorJob()
private val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
Log.d(TAG, "error: $throwable")
throwable.printStackTrace()
}
private val coroutineContext: CoroutineContext
get() = Dispatchers.Default + job + exceptionHandler
private val coroutineScope = CoroutineScope(coroutineContext)
private val useCase: AccountUseCase by inject()
private var timerJob: Job? = null
private var onlineJob: Job? = null
override fun onBind(intent: Intent?): IBinder? {
Log.d(STATE_TAG, "onBind: intent: $intent")
return null
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (startId > 1) return START_STICKY
Log.d(STATE_TAG, "onStartCommand: flags: $flags; startId: $startId\ninstance: $this")
createTimer()
return START_STICKY
}
private fun createTimer() {
timerJob = createTimerFlow(
isNeedToEndCondition = { false },
onStartAction = ::setOnline,
onTickAction = ::setOnline,
interval = 5.minutes
).launchIn(coroutineScope)
}
private fun setOnline() {
if (onlineJob != null) return
Log.d(TAG, "setOnline()")
onlineJob = coroutineScope.launch {
val token = UserConfig.fastToken ?: UserConfig.accessToken
if (token.isBlank()) {
Log.d(TAG, "setOnline: token is empty")
return@launch
}
useCase.setOnline(
voip = false,
accessToken = token
).onEach { state ->
state.processState(
error = { error ->
Log.w(TAG, "setOnline(): error: $error")
},
success = { response ->
Log.d(TAG, "setOnline(): success: $response")
}
)
}.collect()
}.also { coroutine -> coroutine.invokeOnCompletion { onlineJob = null } }
}
override fun onLowMemory() {
Log.d(STATE_TAG, "onLowMemory")
super.onLowMemory()
}
override fun onDestroy() {
Log.d(STATE_TAG, "onDestroy")
timerJob?.cancel("OnlineService destroyed")
onlineJob?.cancel("OnlineService destroyed")
super.onDestroy()
}
companion object {
private const val TAG = "OnlineService"
private const val STATE_TAG = "OnlineServiceState"
}
}