gpt4 book ai didi

android - 通过取消绑定(bind)所有有界 Activity 来停止服务

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:10:29 26 4
gpt4 key购买 nike

我有一个已启动且有界的服务(音乐播放器),我想在单击通知的关闭按钮时停止它。但是,如果有 Activity 绑定(bind)到该服务,则该服务不会停止。单击按钮时如何停止服务?

我已经尝试收集服务中的 Activity 列表并调用它们的回调以解除绑定(bind)(实际上 finish() 然后在 onStop() 上调用 unbind()) 然后我通过调用停止服务 stopSelf() 但我认为这不是一个好主意,因为生命周期问题和一些 Activity 被多次添加并维护名单很难。应该有更好的方法!尽管搜索了几个小时后我什么也没找到。

这是我的 PlayerServiceonStartCommand()

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
info("Starting Player Service ...")
started=true

if (intent == null) {
error("intent was null")
pause()
return START_STICKY
}

if (intent.hasExtra(KEY_SONGS)) {
if(intent.hasExtra(KEY_PLAYLIST_ID)) playlistId=intent.getStringExtra(KEY_PLAYLIST_ID)
initExoPlayer(intent)
} else {
info("No new song information found for intent, intent's action: ${intent.action}")
}
if (intent.action == null) intent.action = ""
when (intent.action) {
ACTION_PLAY -> if (isPlaying()) pause() else play()
ACTION_CANCEL -> {
//TODO: implement a better and the correct way
for (client in clients) {
client.onStop()
}
stopSelf()
}
else -> showNotification()
}

return START_STICKY
}

和我的 Activity :

 playerService.clients.add(object : PlayerService.Client {
override fun onStop() {
finish()
}
})

这是我的自定义通知:

private fun getCustomNotification(name: String, showMainActivity: Intent): Notification {
/*
some codes to prepare notificationLayout
*/
notificationLayout.setTextViewText(R.id.tv_name, name)
notificationLayout.setImageViewResource(R.id.btn_play, playDrawableID)
notificationLayout.setOnClickPendingIntent(R.id.btn_play, playPendingIntent)
notificationLayout.setOnClickPendingIntent(R.id.btn_cancel, cancelPendingIntent)

// Apply the layouts to the notification
return NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.logo_mouj)
.setCustomContentView(notificationLayout)
.setContentIntent(PendingIntent.getActivity(this, 0, showMainActivity, 0))
.setOngoing(true)
.build()

}

最佳答案

如果这个任务看起来令人沮丧,那可能是因为这是一个不寻常的用例,并且在某种程度上超出了 Android 设计师的想法。您可能想问问自己是否有更“类似 Android”的方式来实现您的目标(即,无需枚举绑定(bind)的客户端)。

考虑您的要求:

  1. 播放器应该在用户与应用交互时可用(通过 Activity )
  2. 当用户在后台运行应用程序时,播放器应该继续存在
  3. 当用户点击通知时播放器应该停止
  4. 应用应该在用户用完后清理干净

我认为您可能已选择通过绑定(bind)到 Service 来开始播放, 并通过 onDestroy() 结束播放-正在处理它。这是设计错误,它会给你带来很多问题。毕竟根据docs ,本地,进程中Service实际上只是表示“应用程序希望在不与用户交互的情况下执行长时间运行的操作”,并且“它本身并不是脱离主线程完成工作的手段。”

相反,通过保留每个 Activity介于两者之间 onStart()onStop() , 通过使用 startService()当游戏开始时,stopSelf()当游戏停止时,您将自动完成目标 1、2 和 4。当应用程序处于所有 Activities 的状态时在屏幕外,它将有 0 个绑定(bind)客户端。如果,除此之外,没有startService()未完成,它是操作系统立即终止的候选者。在任何其他状态下,操作系统都会保留它。

这没有任何额外的花哨逻辑来跟踪绑定(bind) Activities .当然,您可能想要 startForeground()当玩家正在玩的时候,stopForeground()完成后(大概您已经处理了该细节)。

这留下了如何实现目标 3 的问题。影响 Service 中的状态变化, 来自 Activities或通知,您可以使用 Intents (很像你已经是)。在这种情况下,Service将通过 stopSelf() 管理自己的生命周期.这再次假设您正在使用 startForeground()在适当的时候 (Oreo+),否则 Android 可能会由于 background execution limits 而终止您的应用程序.

事实上,如果你选择使用Intents , 你可能会发现你甚至不需要绑定(bind)你的 ActivitiesService根本没有(IOW,在这种情况下目标#1 是无关紧要的)。你只需要绑定(bind)到一个 Service如果您需要直接引用该服务(通过 Binder )。

关于android - 通过取消绑定(bind)所有有界 Activity 来停止服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54492025/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com