I am looking for a way to return real time progress to my UI when my service is running, trying now using a shared hilt viewModel both for progress % and for the result but injecting into Service gives:
Injection of an @HiltViewModel class is prohibited since it does not create a ViewModel instance correctly.
Access the ViewModel via the Android APIs (e.g. ViewModelProvider) instead.
my composables:
Button(onClick = {
val intent = Intent(context, TestService::class.java).also {
it.action = TestService.Actions.START.toString()
it.putExtra("imageUri", imageUri) // Pass the image URI to the service
}
ContextCompat.startForegroundService(context, intent)
}) {
Text(text = "Start Service")
}
ProgressBar()
@Composable
fun ProgressBar() {
val serviceViewModel: ServiceViewModel = viewModel()
val progress by serviceViewModel.progress.collectAsState()
val result by serviceViewModel.result.collectAsState()
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
LinearProgressIndicator(
progress = { progress },
) // Use state
Text("Progress: ${progress}%")
}
}
my service :
@AndroidEntryPoint
class TestService : Service(){
@Inject
lateinit var serviceViewModel: ServiceViewModel
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
when(intent?.action) {
Actions.STOP.toString() -> stopSelf()
Actions.START.toString() -> start(intent)
}
return START_NOT_STICKY
}
//.... other stuff
val progressCallback: (Float) -> Unit = { progress ->
serviceViewModel.updateProgress(progress)
}
//....calling progressCallback
and my viewmodel:
@HiltViewModel
class ServiceViewModel @Inject constructor() : ViewModel(){
private val _progress = MutableStateFlow(0f)
val progress: StateFlow<Float> = _progress.asStateFlow()
private val _result = MutableStateFlow<Extracted?>(null)
val result: StateFlow<Extracted?> = _result.asStateFlow()
fun updateProgress(newProgress: Float) {
viewModelScope.launch {
_progress.value = newProgress
}
}
fun updateResult(newResult: Extracted) {
viewModelScope.launch {
_result.value = newResult
}
}
}
I tried ViewModelProvider(this)[ServiceViewModel::class.java]
, solution to the error in stack overflow but seems deprecated and the only way I got it to work created multiple instances.
I also tried broadcast receiver but the composable does not see the broadcast.
fri3erg is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.