fix: resolve buffering on foreground return

This commit is contained in:
tunbmoon
2026-02-13 16:57:45 +08:00
parent 165fce4cec
commit bcac22c1de
4 changed files with 48 additions and 24 deletions
@@ -24,6 +24,7 @@ class Media3Player(private val context: Context) {
var onBufferingListener: ((Boolean) -> Unit)? = null
var onPlaybackStateChanged: ((isPlaying: Boolean, position: Long, bufferedPosition: Long, duration: Long) -> Unit)? = null
var onErrorListener: ((error: String, isRetriable: Boolean) -> Unit)? = null
var onRenderedFirstFrameListener: (() -> Unit)? = null
init {
NetworkUtils.setupAndroid7SSL()
@@ -54,6 +55,9 @@ class Media3Player(private val context: Context) {
}
fun attachSurface(surface: Surface?) {
if (this.surface === surface) {
return
}
this.surface = surface
try {
if (surface == null || surface.isValid) {
@@ -71,11 +75,18 @@ class Media3Player(private val context: Context) {
state.isFixingM3u8 = false
actualPlayingUrl = null
val currentSurface = surface
exoPlayer?.apply {
stop()
clearMediaItems()
clearVideoSurface()
setMediaItem(createMediaItem(url))
prepare()
if (currentSurface != null && currentSurface.isValid) {
setVideoSurface(currentSurface)
}
}
}
@@ -127,6 +138,10 @@ class Media3Player(private val context: Context) {
fun start() {
state.shouldPlayWhenReady = true
exoPlayer?.let {
val s = surface
if (s != null && s.isValid) {
it.setVideoSurface(s)
}
if (it.playbackState == androidx.media3.common.Player.STATE_IDLE) it.prepare()
it.play()
}
@@ -137,7 +152,14 @@ class Media3Player(private val context: Context) {
exoPlayer?.pause()
}
fun stop() = exoPlayer?.stop()
fun stop() {
exoPlayer?.stop()
exoPlayer?.clearVideoSurface()
}
fun clearVideoSurface() {
exoPlayer?.clearVideoSurface()
}
fun setHardwareAcceleration(enabled: Boolean) {
if (currentHardwareAcceleration != enabled) {
@@ -107,7 +107,6 @@ class PlaybackService : MediaSessionService() {
}
override fun onDestroy() {
mediaSession?.player?.stop()
mediaSession?.release()
mediaSession = null
currentPlayer = null
@@ -140,13 +140,17 @@ fun PlayerSurface(
) {
val textureViewRef = remember { mutableStateOf<TextureView?>(null) }
var surfaceReady by remember { mutableStateOf(true) }
var lastChannelUrl by remember { mutableStateOf(currentChannelUrl) }
LaunchedEffect(currentChannelUrl) {
if (currentChannelUrl.isNotEmpty()) {
if (currentChannelUrl.isNotEmpty() && currentChannelUrl != lastChannelUrl) {
lastChannelUrl = currentChannelUrl
surfaceReady = false
player?.attachSurface(null)
kotlinx.coroutines.delay(50)
surfaceReady = true
} else if (lastChannelUrl.isEmpty() && currentChannelUrl.isNotEmpty()) {
lastChannelUrl = currentChannelUrl
}
}
@@ -198,5 +202,7 @@ fun PlayerSurface(
modifier = Modifier
)
}
}
}
@@ -111,11 +111,15 @@ private fun PlayerPageContent(
viewModel.refreshPreferences()
}
var isPlayerClean by remember { mutableStateOf(false) }
LaunchedEffect(url) {
media3Player.apply {
stop()
clearVideoSurface()
exoPlayer?.clearMediaItems()
}
isPlayerClean = true
viewModel.loadChannels(url, initialChannelUrl, initialChannelId, initialVideoTitle)
}
@@ -217,9 +221,12 @@ private fun PlayerPageContent(
Lifecycle.Event.ON_STOP -> {
val backgroundPlay = com.antoniegil.astronia.util.SettingsManager.getBackgroundPlay(context)
val wasPipActive = isInPictureInPictureMode
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val isPip = activity?.isInPictureInPictureMode == true
if (isPip && !backgroundPlay) {
isInPictureInPictureMode = isPip
if ((isPip || wasPipActive) && !backgroundPlay) {
media3Player.pause()
wasPlayingBeforePause = false
return@LifecycleEventObserver
@@ -332,30 +339,20 @@ private fun PlayerPageContent(
viewModel.toggleControls()
}
) {
LaunchedEffect(media3Player) {
media3Player.surface?.let { surface ->
if (surface.isValid) {
media3Player.attachSurface(surface)
}
}
}
val onSurfaceReady = remember {
{
if (pendingAutoPlay) {
pendingAutoPlay = false
media3Player.start()
}
}
}
if (uiState.currentChannelUrl.isNotEmpty()) {
if (uiState.currentChannelUrl.isNotEmpty() && isPlayerClean) {
PlayerSurface(
player = media3Player,
aspectRatio = uiState.aspectRatio,
mirrorFlip = uiState.mirrorFlip,
isBackgroundRetained = false,
onSurfaceReady = onSurfaceReady,
isBackgroundRetained = true,
onSurfaceReady = {
if (pendingAutoPlay && !media3Player.isPlaying) {
pendingAutoPlay = false
media3Player.start()
} else if (pendingAutoPlay) {
pendingAutoPlay = false
}
},
currentChannelUrl = uiState.currentChannelUrl
)
}