service
とは別の でを開始しprocess
ていactivity
ます。はservice
、アプリを閉じても実行されるように設計されています。service
からを起動した後activity
、アプリを閉じます。アプリを再度開くと、service
実行されている場合と実行されていない場合があります。しかし、実行中かどうかを知る方法が見つかりservice
ません。どうすればそれを達成できますか?
参考までに: SO で関連するすべての回答を確認しましたが、サービスが別のプロセスで実行されている場合はどれも機能しません。これは私が持っている最も近い答えですlink . しかし、この答えには欠陥があるようです。それについてもあなたの意見を聞きたいです。
これが私が現在行っていることです:
AndroidManifest.xml
<service
android:name=".services.MyService"
android:enabled="true"
android:exported="false"
android:process=":backgroundProcess" />
MainApplication.kt
(目的: SettingsRepository クラスのインスタンスを 1 つだけ持つため)
class MainApplication : Application() {
val settingsRepository by lazy { SettingsRepository(this) }
}
SettingsRepository.kt
(目的: サービスの実行状態を 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)
}
}
}