Merge pull request #7266 from Bnyro/master

fix: properly open current video from media notification
This commit is contained in:
Bnyro 2025-04-01 09:55:55 +02:00 committed by GitHub
commit aaa6f962cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 39 additions and 22 deletions

View File

@ -41,6 +41,7 @@ import com.google.common.util.concurrent.ListenableFuture
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@UnstableApi @UnstableApi
abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySession.Callback { abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySession.Callback {
@ -116,7 +117,9 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
START_SERVICE_ACTION -> { START_SERVICE_ACTION -> {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
onServiceCreated(args) onServiceCreated(args)
notificationProvider?.intentActivity = getIntentActivity() withContext(Dispatchers.Main) {
updateNotification()
}
if (::videoId.isInitialized) startPlayback() if (::videoId.isInitialized) startPlayback()
} }
@ -185,6 +188,7 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
trackSelector?.updateParameters { trackSelector?.updateParameters {
setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, isAudioOnlyPlayer) setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, isAudioOnlyPlayer)
} }
updateNotification()
} }
} }
} }
@ -239,9 +243,24 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
} }
} }
/**
* Trigger a notification update with an updated PendingIntent.
*/
private fun updateNotification() {
val notificationIntent = Intent(this, getIntentActivity()).apply {
putExtra(IntentData.maximizePlayer, true)
putExtra(IntentData.offlinePlayer, isOfflinePlayer)
putExtra(IntentData.audioOnly, isAudioOnlyPlayer)
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
}
notificationProvider?.notificationIntent = notificationIntent
mediaLibrarySession?.let {
onUpdateNotification(it, true)
}
}
abstract val isOfflinePlayer: Boolean abstract val isOfflinePlayer: Boolean
abstract var isAudioOnlyPlayer: Boolean var isAudioOnlyPlayer: Boolean = false
open val maximizePlayer: Boolean = true
val watchPositionsEnabled get() = val watchPositionsEnabled get() =
(PlayerHelper.watchPositionsAudio && isAudioOnlyPlayer) || (PlayerHelper.watchPositionsVideo && !isAudioOnlyPlayer) (PlayerHelper.watchPositionsAudio && isAudioOnlyPlayer) || (PlayerHelper.watchPositionsVideo && !isAudioOnlyPlayer)
@ -252,10 +271,7 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
notificationProvider = NowPlayingNotification( notificationProvider = NowPlayingNotification(this)
this,
offlinePlayer = isOfflinePlayer,
)
setMediaNotificationProvider(notificationProvider!!) setMediaNotificationProvider(notificationProvider!!)
createPlayerAndMediaSession() createPlayerAndMediaSession()

View File

@ -26,6 +26,7 @@ import com.github.libretube.extensions.updateParameters
import com.github.libretube.helpers.PlayerHelper import com.github.libretube.helpers.PlayerHelper
import com.github.libretube.ui.activities.MainActivity import com.github.libretube.ui.activities.MainActivity
import com.github.libretube.ui.activities.NoInternetActivity import com.github.libretube.ui.activities.NoInternetActivity
import com.github.libretube.ui.activities.OfflinePlayerActivity
import com.github.libretube.ui.fragments.DownloadTab import com.github.libretube.ui.fragments.DownloadTab
import com.github.libretube.util.PlayingQueue import com.github.libretube.util.PlayingQueue
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -41,7 +42,6 @@ import kotlin.io.path.exists
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
open class OfflinePlayerService : AbstractPlayerService() { open class OfflinePlayerService : AbstractPlayerService() {
override val isOfflinePlayer: Boolean = true override val isOfflinePlayer: Boolean = true
override var isAudioOnlyPlayer: Boolean = true
private var noInternetService: Boolean = false private var noInternetService: Boolean = false
private var downloadWithItems: DownloadWithItems? = null private var downloadWithItems: DownloadWithItems? = null
@ -94,7 +94,11 @@ open class OfflinePlayerService : AbstractPlayerService() {
} }
override fun getIntentActivity(): Class<*> { override fun getIntentActivity(): Class<*> {
return if (noInternetService) NoInternetActivity::class.java else MainActivity::class.java return when {
!noInternetService && isAudioOnlyPlayer -> MainActivity::class.java
noInternetService && isAudioOnlyPlayer -> NoInternetActivity::class.java
else -> OfflinePlayerActivity::class.java
}
} }
/** /**

View File

@ -48,7 +48,6 @@ import java.io.IOException
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class) @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
open class OnlinePlayerService : AbstractPlayerService() { open class OnlinePlayerService : AbstractPlayerService() {
override val isOfflinePlayer: Boolean = false override val isOfflinePlayer: Boolean = false
override var isAudioOnlyPlayer: Boolean = false
// PlaylistId/ChannelId for autoplay // PlaylistId/ChannelId for autoplay
private var playlistId: String? = null private var playlistId: String? = null

View File

@ -434,9 +434,13 @@ class MainActivity : BaseActivity() {
} }
if (intent?.getBooleanExtra(IntentData.maximizePlayer, false) == true) { if (intent?.getBooleanExtra(IntentData.maximizePlayer, false) == true) {
// attempt to open the current player fragment first before creating a new one // attempt to open the current video player fragment
// TODO: handle this differently if (intent?.getBooleanExtra(IntentData.audioOnly, false) == false) {
if (runOnPlayerFragment { binding.playerMotionLayout.transitionToStart(); true }) return runOnPlayerFragment { binding.playerMotionLayout.transitionToStart(); true }
return
}
// if it's an audio only session, attempt to maximize the audio player or create a new one
if (runOnAudioPlayerFragment { binding.playerMotionLayout.transitionToStart(); true }) return if (runOnAudioPlayerFragment { binding.playerMotionLayout.transitionToStart(); true }) return
val offlinePlayer = intent!!.getBooleanExtra(IntentData.offlinePlayer, false) val offlinePlayer = intent!!.getBooleanExtra(IntentData.offlinePlayer, false)

View File

@ -21,10 +21,8 @@ import com.google.common.collect.ImmutableList
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class) @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
class NowPlayingNotification( class NowPlayingNotification(
private val context: Context, private val context: Context,
private val offlinePlayer: Boolean = false var notificationIntent: Intent = Intent(),
): MediaNotification.Provider { ): MediaNotification.Provider {
var intentActivity: Class<*> = MainActivity::class.java
private val nProvider = DefaultMediaNotificationProvider.Builder(context) private val nProvider = DefaultMediaNotificationProvider.Builder(context)
.setNotificationId(NotificationId.PLAYER_PLAYBACK.id) .setNotificationId(NotificationId.PLAYER_PLAYBACK.id)
.setChannelId(PLAYER_CHANNEL_NAME) .setChannelId(PLAYER_CHANNEL_NAME)
@ -36,14 +34,10 @@ class NowPlayingNotification(
// it doesn't start a completely new MainActivity because the MainActivity's launchMode // it doesn't start a completely new MainActivity because the MainActivity's launchMode
// is set to "singleTop" in the AndroidManifest (important!!!) // is set to "singleTop" in the AndroidManifest (important!!!)
// that's the only way to launch back into the previous activity (e.g. the player view) // that's the only way to launch back into the previous activity (e.g. the player view)
val intent = Intent(context, intentActivity).apply {
putExtra(IntentData.maximizePlayer, true)
putExtra(IntentData.offlinePlayer, offlinePlayer)
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
}
return PendingIntentCompat return PendingIntentCompat
.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT, false) .getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT, false)
} }
/** /**