Merge pull request #6773 from Bnyro/master

fix: properly kill playback service and notification on player close
This commit is contained in:
Bnyro 2024-11-18 22:28:53 +01:00 committed by GitHub
commit 92d3475aa4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 34 additions and 43 deletions

View File

@ -119,8 +119,6 @@ object BackgroundHelper {
arguments: Bundle, arguments: Bundle,
onController: (MediaController) -> Unit = {} onController: (MediaController) -> Unit = {}
) { ) {
stopBackgroundPlay(context)
val sessionToken = val sessionToken =
SessionToken(context, ComponentName(context, serviceClass)) SessionToken(context, ComponentName(context, serviceClass))

View File

@ -59,7 +59,6 @@ object NavigationHelper {
forceVideo: Boolean = false forceVideo: Boolean = false
) { ) {
if (videoUrlOrId == null) return if (videoUrlOrId == null) return
BackgroundHelper.stopBackgroundPlay(context)
if (PreferenceHelper.getBoolean(PreferenceKeys.AUDIO_ONLY_MODE, false) && !forceVideo) { if (PreferenceHelper.getBoolean(PreferenceKeys.AUDIO_ONLY_MODE, false) && !forceVideo) {
BackgroundHelper.playOnBackground( BackgroundHelper.playOnBackground(

View File

@ -89,27 +89,28 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
customCommand: SessionCommand, customCommand: SessionCommand,
args: Bundle args: Bundle
): ListenableFuture<SessionResult> { ): ListenableFuture<SessionResult> {
if (customCommand.customAction == START_SERVICE_ACTION) { when (customCommand.customAction) {
PlayingQueue.resetToDefaults() START_SERVICE_ACTION -> {
PlayingQueue.resetToDefaults()
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
onServiceCreated(args) onServiceCreated(args)
notificationProvider?.intentActivity = getIntentActivity() notificationProvider?.intentActivity = getIntentActivity()
startPlayback() startPlayback()
}
}
STOP_SERVICE_ACTION -> {
onDestroy()
}
RUN_PLAYER_COMMAND_ACTION -> {
runPlayerCommand(args)
}
else -> {
handlePlayerAction(PlayerEvent.valueOf(customCommand.customAction))
} }
return super.onCustomCommand(session, controller, customCommand, args)
} }
if (customCommand.customAction == RUN_PLAYER_COMMAND_ACTION) {
runPlayerCommand(args)
return super.onCustomCommand(session, controller, customCommand, args)
}
handlePlayerAction(PlayerEvent.valueOf(customCommand.customAction))
return super.onCustomCommand(session, controller, customCommand, args) return super.onCustomCommand(session, controller, customCommand, args)
} }
@ -238,11 +239,8 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
val mediaNotificationSessionCommands = val mediaNotificationSessionCommands =
connectionResult.availableSessionCommands.buildUpon() connectionResult.availableSessionCommands.buildUpon()
.also { builder -> .also { builder ->
builder.add(startServiceCommand) builder.addSessionCommands(listOf(startServiceCommand, runPlayerActionCommand, stopServiceCommand))
builder.add(runPlayerActionCommand) builder.addSessionCommands(customLayout.mapNotNull(CommandButton::sessionCommand))
customLayout.forEach { commandButton ->
commandButton.sessionCommand?.let { builder.add(it) }
}
} }
.build() .build()
@ -332,9 +330,11 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
companion object { companion object {
private const val START_SERVICE_ACTION = "start_service_action" private const val START_SERVICE_ACTION = "start_service_action"
private const val STOP_SERVICE_ACTION = "stop_service_action"
private const val RUN_PLAYER_COMMAND_ACTION = "run_player_command_action" private const val RUN_PLAYER_COMMAND_ACTION = "run_player_command_action"
val startServiceCommand = SessionCommand(START_SERVICE_ACTION, Bundle.EMPTY) val startServiceCommand = SessionCommand(START_SERVICE_ACTION, Bundle.EMPTY)
val stopServiceCommand = SessionCommand(STOP_SERVICE_ACTION, Bundle.EMPTY)
val runPlayerActionCommand = SessionCommand(RUN_PLAYER_COMMAND_ACTION, Bundle.EMPTY) val runPlayerActionCommand = SessionCommand(RUN_PLAYER_COMMAND_ACTION, Bundle.EMPTY)
} }
} }

View File

@ -6,6 +6,7 @@ import android.content.Intent
import android.os.IBinder import android.os.IBinder
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import com.github.libretube.enums.NotificationId import com.github.libretube.enums.NotificationId
import com.github.libretube.helpers.BackgroundHelper
class OnClearFromRecentService : Service() { class OnClearFromRecentService : Service() {
private var nManager: NotificationManager? = null private var nManager: NotificationManager? = null
@ -22,6 +23,7 @@ class OnClearFromRecentService : Service() {
} }
override fun onTaskRemoved(rootIntent: Intent?) { override fun onTaskRemoved(rootIntent: Intent?) {
BackgroundHelper.stopBackgroundPlay(this)
nManager?.cancel(NotificationId.PLAYER_PLAYBACK.id) nManager?.cancel(NotificationId.PLAYER_PLAYBACK.id)
stopSelf() stopSelf()
} }

View File

@ -230,6 +230,8 @@ class OfflinePlayerActivity : BaseActivity() {
} }
override fun onDestroy() { override fun onDestroy() {
playerController.sendCustomCommand(AbstractPlayerService.stopServiceCommand, Bundle.EMPTY)
runCatching { runCatching {
unregisterReceiver(playerActionReceiver) unregisterReceiver(playerActionReceiver)
} }

View File

@ -7,7 +7,6 @@ import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.text.format.DateUtils import android.text.format.DateUtils
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -42,6 +41,7 @@ import com.github.libretube.helpers.NavBarHelper
import com.github.libretube.helpers.NavigationHelper import com.github.libretube.helpers.NavigationHelper
import com.github.libretube.helpers.PlayerHelper import com.github.libretube.helpers.PlayerHelper
import com.github.libretube.helpers.ThemeHelper import com.github.libretube.helpers.ThemeHelper
import com.github.libretube.services.AbstractPlayerService
import com.github.libretube.services.OfflinePlayerService import com.github.libretube.services.OfflinePlayerService
import com.github.libretube.services.OnlinePlayerService import com.github.libretube.services.OnlinePlayerService
import com.github.libretube.ui.activities.MainActivity import com.github.libretube.ui.activities.MainActivity
@ -170,8 +170,8 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
} }
binding.openVideo.setOnClickListener { binding.openVideo.setOnClickListener {
BackgroundHelper.stopBackgroundPlay(requireContext())
killFragment() killFragment()
NavigationHelper.navigateVideo( NavigationHelper.navigateVideo(
context = requireContext(), context = requireContext(),
videoUrlOrId = PlayingQueue.getCurrent()?.url, videoUrlOrId = PlayingQueue.getCurrent()?.url,
@ -202,8 +202,6 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
} }
binding.miniPlayerClose.setOnClickListener { binding.miniPlayerClose.setOnClickListener {
playerController?.release()
BackgroundHelper.stopBackgroundPlay(requireContext())
killFragment() killFragment()
} }
@ -233,6 +231,8 @@ class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
} }
private fun killFragment() { private fun killFragment() {
playerController?.sendCustomCommand(AbstractPlayerService.stopServiceCommand, Bundle.EMPTY)
viewModel.isFullscreen.value = false viewModel.isFullscreen.value = false
binding.playerMotionLayout.transitionToEnd() binding.playerMotionLayout.transitionToEnd()
activity.supportFragmentManager.commit { activity.supportFragmentManager.commit {

View File

@ -238,11 +238,6 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
PictureInPictureCompat.setPictureInPictureParams(requireActivity(), pipParams) PictureInPictureCompat.setPictureInPictureParams(requireActivity(), pipParams)
} }
if (isPlaying) {
// Stop [BackgroundMode] service if it is running.
BackgroundHelper.stopBackgroundPlay(requireContext())
}
if (isPlaying && PlayerHelper.sponsorBlockEnabled) { if (isPlaying && PlayerHelper.sponsorBlockEnabled) {
handler.postDelayed( handler.postDelayed(
this@PlayerFragment::checkForSegments, this@PlayerFragment::checkForSegments,
@ -567,23 +562,17 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
.animateDown( .animateDown(
duration = 300L, duration = 300L,
dy = 500F, dy = 500F,
onEnd = ::onManualPlayerClose onEnd = ::killPlayerFragment
) )
} }
private fun onManualPlayerClose() {
PlayingQueue.clear()
BackgroundHelper.stopBackgroundPlay(requireContext())
killPlayerFragment()
}
// actions that don't depend on video information // actions that don't depend on video information
private fun initializeOnClickActions() { private fun initializeOnClickActions() {
binding.closeImageView.setOnClickListener { binding.closeImageView.setOnClickListener {
onManualPlayerClose() killPlayerFragment()
} }
playerBinding.closeImageButton.setOnClickListener { playerBinding.closeImageButton.setOnClickListener {
onManualPlayerClose() killPlayerFragment()
} }
binding.playImageView.setOnClickListener { binding.playImageView.setOnClickListener {
@ -736,7 +725,6 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
} }
private fun playOnBackground() { private fun playOnBackground() {
BackgroundHelper.stopBackgroundPlay(requireContext())
BackgroundHelper.playOnBackground( BackgroundHelper.playOnBackground(
requireContext(), requireContext(),
videoId, videoId,
@ -878,6 +866,8 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
playerController.removeListener(playerListener) playerController.removeListener(playerListener)
playerController.pause() playerController.pause()
playerController.sendCustomCommand(AbstractPlayerService.stopServiceCommand, Bundle.EMPTY)
if (PlayerHelper.pipEnabled) { if (PlayerHelper.pipEnabled) {
// disable the auto PiP mode for SDK >= 32 // disable the auto PiP mode for SDK >= 32
PictureInPictureCompat PictureInPictureCompat