I am starting a service
in a different process
from an activity
.
The service
is designed to run even when the app is closed.
After starting the service
from the activity
, I close the app. Now when I reopen the app the service
may or may not be running. But I haven't find way to know if the service
is running or not.
How can I achieve that?
FYI: I have checked all the related answers here on SO but none of them works when the service is running in a different process. This is the closest answer I have got link. But this answer seems flawed, I would also like to hear your opinion on it too.
Here's what I am currently doing:
AndroidManifest.xml
<service
android:name=".services.MyService"
android:enabled="true"
android:exported="false"
android:process=":backgroundProcess" />
MainApplication.kt
(purpose: to have only one instance of the SettingsRepository class)
class MainApplication : Application() {
val settingsRepository by lazy { SettingsRepository(this) }
}
SettingsRepository.kt
(purpose: to save the running state of the service in Preference DataStore)
class SettingsRepository(context: Context) {
private val dataStore = context.createDataStore(name = "settings_prefs")
companion object {
val SERVICE_STATE_KEY = booleanPreferencesKey("SERVICE_STATE_KEY")
}
suspend fun saveServiceStateToDataStore(state: Boolean) {
dataStore.edit {
it[SERVICE_STATE_KEY] = state
}
}
val getServiceStateFromDataStore: Flow<Boolean> = dataStore.data.map {
val state = it[SERVICE_STATE_KEY] ?: false
state
}
}
Service.kt
private lateinit var settingsRepository: SettingsRepository
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
settingsRepository = (application.applicationContext as MainApplication).settingsRepository
saveStateToDataStore(true)
return START_REDELIVER_INTENT
}
private fun saveStateToDataStore(state: Boolean): Job {
return CoroutineScope(Dispatchers.IO).launch {
settingsRepository.saveServiceStateToDataStore(state)
}
}
Activity.kt
private fun observeDataFromViewModel() {
mainViewModel.readServiceStateFromRepository.observe(this, {state ->
Toast.makeText(this, "Service state changed to $state", Toast.LENGTH_SHORT).show()
// should get the new data when service stores it in onStartCommand but doesn't get it
// maybe because the service doesn't stores the data for some reason I am not aware of.
})
}
private fun handleClickListener() {
btn_start_service.setOnClickListener {
startForegroundService(serviceIntent)
}
}
btn_stop_service.setOnClickListener {
mainViewModel.saveServiceState(false)
stopService(serviceIntent)
}
}
ViewModel.kt
class MainViewModel(application: Application) : AndroidViewModel(application) {
private val settingsRepository = (application.applicationContext as MainApplication).settingsRepository
val readServiceStateFromRepository = settingsRepository.getServiceStateFromDataStore.asLiveData()
fun saveServiceState(state: Boolean): Job {
return viewModelScope.launch(Dispatchers.IO) {
settingsRepository.saveServiceStateToDataStore(state)
}
}
}