feat: Add dynamic module ViewModel and Repository

This commit is contained in:
Cutiful 2025-05-16 11:13:12 +07:00
parent 228a11092f
commit e15601f4ad
2 changed files with 110 additions and 0 deletions

View File

@ -0,0 +1,35 @@
package com.syaroful.agrilinkvocpro.di
import com.google.android.gms.tasks.Task
import com.google.android.play.core.splitinstall.SplitInstallManager
import com.google.android.play.core.splitinstall.SplitInstallRequest
import com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener
import javax.inject.Inject
class DynamicModuleRepository @Inject constructor(
private val splitInstallManager: SplitInstallManager
) {
private var sessionId = 0
fun isModuleDownloaded(moduleName: String): Boolean {
return splitInstallManager.installedModules.contains(moduleName)
}
fun startDownload(
moduleName: String,
listener: SplitInstallStateUpdatedListener
): Task<Int> {
val request = SplitInstallRequest.newBuilder()
.addModule(moduleName)
.build()
splitInstallManager.registerListener(listener)
return splitInstallManager.startInstall(request)
.addOnSuccessListener { id -> sessionId = id }
}
fun unregisterListener(listener: SplitInstallStateUpdatedListener){
splitInstallManager.unregisterListener(listener)
}
fun getSessionId() = sessionId
}

View File

@ -0,0 +1,75 @@
package com.syaroful.agrilinkvocpro.viewModel
import androidx.lifecycle.ViewModel
import com.google.android.play.core.splitinstall.SplitInstallException
import com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener
import com.google.android.play.core.splitinstall.model.SplitInstallErrorCode
import com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus
import com.syaroful.agrilinkvocpro.DownloadState
import com.syaroful.agrilinkvocpro.di.DynamicModuleRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import javax.inject.Inject
@HiltViewModel
class DynamicModuleViewModel @Inject constructor(
private val repository: DynamicModuleRepository
) : ViewModel() {
private val _downloadState = MutableStateFlow<DownloadState>(DownloadState.Idle)
val downloadState: StateFlow<DownloadState> = _downloadState.asStateFlow()
private val listener = SplitInstallStateUpdatedListener { state ->
if (state.sessionId() == repository.getSessionId()) {
when (state.status()) {
SplitInstallSessionStatus.DOWNLOADING -> {
val progress = if (state.totalBytesToDownload() > 0)
state.bytesDownloaded().toFloat() / state.totalBytesToDownload()
else 0f
_downloadState.value = DownloadState.DownloadingWithProgress(progress)
}
SplitInstallSessionStatus.DOWNLOADED -> _downloadState.value =
DownloadState.Downloaded
SplitInstallSessionStatus.INSTALLED -> _downloadState.value =
DownloadState.Installed
SplitInstallSessionStatus.FAILED -> _downloadState.value =
DownloadState.Failed("Installation Failed")
SplitInstallSessionStatus.CANCELED -> _downloadState.value =
DownloadState.Failed("Installation Canceled")
else -> {}
}
}
}
fun isModuleDownloaded(moduleName: String): Boolean {
return repository.isModuleDownloaded(moduleName)
}
fun downloadModule(moduleName: String) {
_downloadState.value = DownloadState.Starting
repository.startDownload(moduleName, listener)
.addOnFailureListener { exception ->
val errorCode = (exception as? SplitInstallException)?.errorCode ?: -1
val errorMessage = when (errorCode) {
SplitInstallErrorCode.NETWORK_ERROR -> "No Internet Connection"
SplitInstallErrorCode.MODULE_UNAVAILABLE -> "Module Unavailable"
SplitInstallErrorCode.ACTIVE_SESSIONS_LIMIT_EXCEEDED -> "Active Session Limit Exceeded"
SplitInstallErrorCode.INSUFFICIENT_STORAGE -> "Insufficient Storage"
SplitInstallErrorCode.PLAY_STORE_NOT_FOUND -> "Play Store Not Found"
else -> "Unknown Error: $errorCode"
}
_downloadState.value = DownloadState.Failed(errorMessage)
}
}
override fun onCleared() {
super.onCleared()
repository.unregisterListener(listener)
}
}