如何解决移除最近应用列表后音乐播放器仍持续播放的问题?
问题解决方案:移除最近应用后停止音乐播放
当前代码的核心问题是没有处理Android系统在应用从最近列表移除时触发的onTaskRemoved回调,导致服务和音乐继续后台运行。只需添加以下修改即可实现需求:
1. 添加抽象方法让子类实现停止播放逻辑
在InvincibleService中新增一个抽象方法,让你的音乐Service子类负责实现具体的停止音乐逻辑:
protected abstract fun stopMusicPlayback()
2. 重写onTaskRemoved回调处理移除操作
在InvincibleService中重写onTaskRemoved方法,在这里执行停止播放、清理资源、销毁服务的操作:
override fun onTaskRemoved(rootIntent: Intent?) { // 停止音乐播放 stopMusicPlayback() // 停止Invincibility的定时任务和广播监听 invincibility?.stop() invincibility = null // 停止并销毁当前服务 stopSelf() super.onTaskRemoved(rootIntent) }
3. 子类实现停止播放逻辑
在你的音乐Service子类中实现stopMusicPlayback方法,填入具体的停止播放代码:
override fun stopMusicPlayback() { // 示例:停止MediaPlayer并释放资源 mediaPlayer?.run { if (isPlaying) stop() release() } mediaPlayer = null }
修改后的完整InvincibleService代码
abstract class InvincibleService : Service() { protected val handler = Handler(Looper.getMainLooper()) protected abstract val isInvincibilityEnabled: Boolean protected abstract val notificationId: Int private var invincibility: Invincibility? = null private val isAllowedToStartForegroundServices: Boolean get() = !isAtLeastAndroid12 || isIgnoringBatteryOptimizations // 新增抽象方法:子类实现停止音乐逻辑 protected abstract fun stopMusicPlayback() override fun onBind(intent: Intent?): Binder? { invincibility?.stop() invincibility = null return null } override fun onRebind(intent: Intent?) { invincibility?.stop() invincibility = null super.onRebind(intent) } override fun onUnbind(intent: Intent?): Boolean { if (isInvincibilityEnabled && isAllowedToStartForegroundServices) { invincibility = Invincibility() } return true } // 重写onTaskRemoved处理最近应用移除操作 override fun onTaskRemoved(rootIntent: Intent?) { stopMusicPlayback() invincibility?.stop() invincibility = null stopSelf() super.onTaskRemoved(rootIntent) } override fun onDestroy() { invincibility?.stop() invincibility = null super.onDestroy() } protected fun makeInvincible(isInvincible: Boolean = true) { if (isInvincible) { invincibility?.start() } else { invincibility?.stop() } } protected abstract fun shouldBeInvincible(): Boolean protected abstract fun notification(): Notification? private inner class Invincibility : BroadcastReceiver(), Runnable { private var isStarted = false private val intervalMs = 30_000L override fun onReceive(context: Context?, intent: Intent?) { when (intent?.action) { Intent.ACTION_SCREEN_ON -> handler.post(this) Intent.ACTION_SCREEN_OFF -> notification()?.let { notification -> handler.removeCallbacks(this) startForeground(notificationId, notification) } } } @Synchronized fun start() { if (!isStarted) { isStarted = true handler.postDelayed(this, intervalMs) registerReceiver(this, IntentFilter().apply { addAction(Intent.ACTION_SCREEN_ON) addAction(Intent.ACTION_SCREEN_OFF) }) } } @Synchronized fun stop() { if (isStarted) { handler.removeCallbacks(this) unregisterReceiver(this) isStarted = false } } override fun run() { if (shouldBeInvincible() && isAllowedToStartForegroundServices) { notification()?.let { notification -> startForeground(notificationId, notification) stopForeground(false) handler.postDelayed(this, intervalMs) } } } } }
说明
onTaskRemoved是Android系统在用户从最近应用列表中移除应用任务时触发的回调,通过重写这个方法,我们可以在用户执行该操作时立即停止音乐播放、清理服务资源并销毁服务,和Spotify、YouTube Music的行为保持一致。
内容的提问来源于stack exchange,提问作者Dhairya
相关产品推荐
相关产品推荐

