mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-29 00:10:32 +05:30
fix: crash when ending player service / fragment
This commit is contained in:
parent
df087054d9
commit
a56b8ccf0b
@ -4,9 +4,7 @@ import android.content.BroadcastReceiver
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.os.Handler
|
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.os.Looper
|
|
||||||
import androidx.annotation.OptIn
|
import androidx.annotation.OptIn
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.ServiceCompat
|
import androidx.core.app.ServiceCompat
|
||||||
@ -43,8 +41,6 @@ import kotlinx.coroutines.withContext
|
|||||||
* A service to play downloaded audio in the background
|
* A service to play downloaded audio in the background
|
||||||
*/
|
*/
|
||||||
class OfflinePlayerService : LifecycleService() {
|
class OfflinePlayerService : LifecycleService() {
|
||||||
val handler = Handler(Looper.getMainLooper())
|
|
||||||
|
|
||||||
private var player: ExoPlayer? = null
|
private var player: ExoPlayer? = null
|
||||||
private var nowPlayingNotification: NowPlayingNotification? = null
|
private var nowPlayingNotification: NowPlayingNotification? = null
|
||||||
private lateinit var videoId: String
|
private lateinit var videoId: String
|
||||||
@ -209,14 +205,18 @@ class OfflinePlayerService : LifecycleService() {
|
|||||||
saveWatchPosition()
|
saveWatchPosition()
|
||||||
|
|
||||||
nowPlayingNotification?.destroySelf()
|
nowPlayingNotification?.destroySelf()
|
||||||
|
|
||||||
player?.stop()
|
|
||||||
player?.release()
|
|
||||||
player = null
|
|
||||||
nowPlayingNotification = null
|
nowPlayingNotification = null
|
||||||
|
|
||||||
watchPositionTimer.destroy()
|
watchPositionTimer.destroy()
|
||||||
unregisterReceiver(playerActionReceiver)
|
|
||||||
|
runCatching {
|
||||||
|
player?.stop()
|
||||||
|
player?.release()
|
||||||
|
}
|
||||||
|
player = null
|
||||||
|
|
||||||
|
runCatching {
|
||||||
|
unregisterReceiver(playerActionReceiver)
|
||||||
|
}
|
||||||
|
|
||||||
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
||||||
stopSelf()
|
stopSelf()
|
||||||
|
@ -31,7 +31,6 @@ import com.github.libretube.api.RetrofitInstance
|
|||||||
import com.github.libretube.api.obj.Segment
|
import com.github.libretube.api.obj.Segment
|
||||||
import com.github.libretube.api.obj.Streams
|
import com.github.libretube.api.obj.Streams
|
||||||
import com.github.libretube.constants.IntentData
|
import com.github.libretube.constants.IntentData
|
||||||
import com.github.libretube.constants.PreferenceKeys
|
|
||||||
import com.github.libretube.db.DatabaseHelper
|
import com.github.libretube.db.DatabaseHelper
|
||||||
import com.github.libretube.enums.NotificationId
|
import com.github.libretube.enums.NotificationId
|
||||||
import com.github.libretube.enums.PlayerEvent
|
import com.github.libretube.enums.PlayerEvent
|
||||||
@ -42,7 +41,6 @@ import com.github.libretube.extensions.toID
|
|||||||
import com.github.libretube.extensions.updateParameters
|
import com.github.libretube.extensions.updateParameters
|
||||||
import com.github.libretube.helpers.PlayerHelper
|
import com.github.libretube.helpers.PlayerHelper
|
||||||
import com.github.libretube.helpers.PlayerHelper.checkForSegments
|
import com.github.libretube.helpers.PlayerHelper.checkForSegments
|
||||||
import com.github.libretube.helpers.PreferenceHelper
|
|
||||||
import com.github.libretube.helpers.ProxyHelper
|
import com.github.libretube.helpers.ProxyHelper
|
||||||
import com.github.libretube.obj.PlayerNotificationData
|
import com.github.libretube.obj.PlayerNotificationData
|
||||||
import com.github.libretube.parcelable.PlayerData
|
import com.github.libretube.parcelable.PlayerData
|
||||||
@ -372,7 +370,7 @@ class OnlinePlayerService : LifecycleService() {
|
|||||||
|
|
||||||
val (uri, mimeType) =
|
val (uri, mimeType) =
|
||||||
if (!PlayerHelper.useHlsOverDash && streams.audioStreams.isNotEmpty() && !PlayerHelper.disablePipedProxy) {
|
if (!PlayerHelper.useHlsOverDash && streams.audioStreams.isNotEmpty() && !PlayerHelper.disablePipedProxy) {
|
||||||
PlayerHelper.createDashSource(streams, this,) to MimeTypes.APPLICATION_MPD
|
PlayerHelper.createDashSource(streams, this) to MimeTypes.APPLICATION_MPD
|
||||||
} else {
|
} else {
|
||||||
ProxyHelper.unwrapStreamUrl(streams.hls.orEmpty())
|
ProxyHelper.unwrapStreamUrl(streams.hls.orEmpty())
|
||||||
.toUri() to MimeTypes.APPLICATION_M3U8
|
.toUri() to MimeTypes.APPLICATION_M3U8
|
||||||
@ -427,12 +425,17 @@ class OnlinePlayerService : LifecycleService() {
|
|||||||
PlayingQueue.resetToDefaults()
|
PlayingQueue.resetToDefaults()
|
||||||
|
|
||||||
if (this::nowPlayingNotification.isInitialized) nowPlayingNotification.destroySelf()
|
if (this::nowPlayingNotification.isInitialized) nowPlayingNotification.destroySelf()
|
||||||
|
|
||||||
player?.stop()
|
|
||||||
player?.release()
|
|
||||||
|
|
||||||
watchPositionTimer.destroy()
|
watchPositionTimer.destroy()
|
||||||
unregisterReceiver(playerActionReceiver)
|
handler.removeCallbacksAndMessages(null)
|
||||||
|
|
||||||
|
runCatching {
|
||||||
|
player?.stop()
|
||||||
|
player?.release()
|
||||||
|
}
|
||||||
|
|
||||||
|
runCatching {
|
||||||
|
unregisterReceiver(playerActionReceiver)
|
||||||
|
}
|
||||||
|
|
||||||
// called when the user pressed stop in the notification
|
// called when the user pressed stop in the notification
|
||||||
// stop the service from being in the foreground and remove the notification
|
// stop the service from being in the foreground and remove the notification
|
||||||
|
@ -300,12 +300,19 @@ class OfflinePlayerActivity : BaseActivity() {
|
|||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
saveWatchPosition()
|
saveWatchPosition()
|
||||||
|
|
||||||
playerViewModel.player = null
|
|
||||||
player.release()
|
|
||||||
watchPositionTimer.destroy()
|
|
||||||
nowPlayingNotification?.destroySelf()
|
nowPlayingNotification?.destroySelf()
|
||||||
|
nowPlayingNotification = null
|
||||||
|
watchPositionTimer.destroy()
|
||||||
|
|
||||||
unregisterReceiver(playerActionReceiver)
|
playerViewModel.player = null
|
||||||
|
runCatching {
|
||||||
|
player.stop()
|
||||||
|
player.release()
|
||||||
|
}
|
||||||
|
|
||||||
|
runCatching {
|
||||||
|
unregisterReceiver(playerActionReceiver)
|
||||||
|
}
|
||||||
|
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
@ -783,18 +783,31 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
|
|
||||||
|
saveWatchPosition()
|
||||||
|
|
||||||
|
viewModel.nowPlayingNotification?.destroySelf()
|
||||||
|
viewModel.nowPlayingNotification = null
|
||||||
|
watchPositionTimer.destroy()
|
||||||
|
handler.removeCallbacksAndMessages(null)
|
||||||
|
|
||||||
if (this::exoPlayer.isInitialized) {
|
if (this::exoPlayer.isInitialized) {
|
||||||
exoPlayer.removeListener(playerListener)
|
exoPlayer.removeListener(playerListener)
|
||||||
|
|
||||||
// the player could also be a different instance because a new player fragment
|
|
||||||
// got created in the meanwhile
|
|
||||||
if (!viewModel.isOrientationChangeInProgress && viewModel.player == exoPlayer) {
|
|
||||||
viewModel.player = null
|
|
||||||
viewModel.trackSelector = null
|
|
||||||
}
|
|
||||||
|
|
||||||
exoPlayer.pause()
|
exoPlayer.pause()
|
||||||
|
|
||||||
|
runCatching {
|
||||||
|
// the player could also be a different instance because a new player fragment
|
||||||
|
// got created in the meanwhile
|
||||||
|
if (!viewModel.isOrientationChangeInProgress) {
|
||||||
|
if (viewModel.player == exoPlayer) {
|
||||||
|
viewModel.player = null
|
||||||
|
viewModel.trackSelector = null
|
||||||
|
}
|
||||||
|
|
||||||
|
exoPlayer.stop()
|
||||||
|
exoPlayer.release()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (PlayerHelper.pipEnabled) {
|
if (PlayerHelper.pipEnabled) {
|
||||||
// disable the auto PiP mode for SDK >= 32
|
// disable the auto PiP mode for SDK >= 32
|
||||||
PictureInPictureCompat
|
PictureInPictureCompat
|
||||||
@ -802,35 +815,29 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.removeCallbacksAndMessages(null)
|
|
||||||
|
|
||||||
runCatching {
|
runCatching {
|
||||||
// unregister the receiver for player actions
|
// unregister the receiver for player actions
|
||||||
context?.unregisterReceiver(playerActionReceiver)
|
context?.unregisterReceiver(playerActionReceiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// restore the orientation that's used by the main activity
|
||||||
|
(context as MainActivity).requestOrientationChange()
|
||||||
|
|
||||||
_binding = null
|
_binding = null
|
||||||
|
|
||||||
stopVideoPlay()
|
|
||||||
|
|
||||||
watchPositionTimer.destroy()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun stopVideoPlay() {
|
private fun killPlayerFragment() {
|
||||||
try {
|
viewModel.isFullscreen.value = false
|
||||||
saveWatchPosition()
|
viewModel.isMiniPlayerVisible.value = false
|
||||||
|
|
||||||
viewModel.nowPlayingNotification?.destroySelf()
|
// dismiss the fullscreen dialog if it's currently visible
|
||||||
viewModel.nowPlayingNotification = null
|
// otherwise it would stay alive while being detached from this fragment
|
||||||
|
fullscreenDialog.dismiss()
|
||||||
|
binding.player.currentWindow = null
|
||||||
|
|
||||||
if (!viewModel.isOrientationChangeInProgress) {
|
binding.playerMotionLayout.transitionToEnd()
|
||||||
exoPlayer.stop()
|
mainActivity.supportFragmentManager.commit {
|
||||||
exoPlayer.release()
|
remove(this@PlayerFragment)
|
||||||
}
|
|
||||||
|
|
||||||
(context as MainActivity).requestOrientationChange()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1512,22 +1519,6 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
!BackgroundHelper.isBackgroundServiceRunning(requireContext())
|
!BackgroundHelper.isBackgroundServiceRunning(requireContext())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun killPlayerFragment() {
|
|
||||||
stopVideoPlay()
|
|
||||||
viewModel.isFullscreen.value = false
|
|
||||||
viewModel.isMiniPlayerVisible.value = false
|
|
||||||
|
|
||||||
// dismiss the fullscreen dialog if it's currently visible
|
|
||||||
// otherwise it would stay alive while being detached from this fragment
|
|
||||||
fullscreenDialog.dismiss()
|
|
||||||
binding.player.currentWindow = null
|
|
||||||
|
|
||||||
binding.playerMotionLayout.transitionToEnd()
|
|
||||||
mainActivity.supportFragmentManager.commit {
|
|
||||||
remove(this@PlayerFragment)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the activity needs to be recreated due to an orientation change
|
* Check if the activity needs to be recreated due to an orientation change
|
||||||
* If true, the activity will be automatically restarted
|
* If true, the activity will be automatically restarted
|
||||||
|
Loading…
x
Reference in New Issue
Block a user