如何解决Android:如何在活动和在不同进程中运行的服务之间进行通信?
我在与 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 类的实例)
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)
}
}
}
解决方法
使用 Messenger 类与服务器 https://developer.android.com/reference/android/app/Service.html#remote-messenger-service-sample
通信或者使用 BroadcastReceiver 从另一个进程获取服务状态
class MainActivity : AppCompatActivity() {
private var receiver: TmpReceiver? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.view_main)
val intent = Intent(this,TmpService::class.java)
receiver = TmpReceiver()
val filter = IntentFilter().apply {
addAction("SERVICE_START")
addAction("SERVICE_STOP")
}
registerReceiver(receiver,filter)
startService(intent)
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(receiver)
receiver = null
}
}
class TmpService : Service() {
override fun onBind(p0: Intent?): IBinder? {
return null
}
override fun onCreate() {
super.onCreate()
sendBroadcast("SERVICE_START")
}
override fun onDestroy() {
sendBroadcast("SERVICE_STOP")
super.onDestroy()
}
private fun sendBroadcast(action: String) {
Intent().also { intent ->
intent.action = action
sendBroadcast(intent)
}
}
}
class TmpReceiver: BroadcastReceiver() {
override fun onReceive(p0: Context?,p1: Intent?) {
Log.d("TmpReceiver","action=${p1?.action}")
}
}
您可以在服务中再注册一个接收器,以便从活动中 ping 它。
关于它仅适用于单个流程应用程序的最接近的答案
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。