diff --git a/CHANGELOG.md b/CHANGELOG.md index 477fe82..6b975e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ > - 🏠 Internal > - 💅 Polish +## v1.9.2 (2024-10-15) + +* 🐛 Fix `Player.cast` not available before first source change. + ## v1.9.1 (2024-10-01) * 🐛 Fix `DurationDisplay` to show the time of the live point when playing a live or DVR stream. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d9f99cf..39f2529 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -79,7 +79,6 @@ dependencies { "mavenImplementation"("com.theoplayer.android-ui:android-ui:1.+") implementation(libs.theoplayer) - implementation(libs.theoplayer.ads) implementation(libs.theoplayer.ads.ima) implementation(libs.theoplayer.cast) } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 2517350..f012dcc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,4 +24,4 @@ android.nonTransitiveRClass=true android.nonFinalResIds=true org.gradle.configuration-cache=true # The version of the THEOplayer Open Video UI for Android. -version=1.9.1 +version=1.9.2 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 565dd90..24635de 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ androidx-junit = "1.2.1" androidx-espresso = "3.6.1" androidx-mediarouter = "1.7.0" dokka = "1.9.20" -theoplayer = "7.11.0" +theoplayer = "8.2.0" [libraries] androidx-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "ktx" } @@ -39,7 +39,6 @@ dokka-plugin = { group = "org.jetbrains.dokka", name = "android-documentation-pl kotlin-gradle-plugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin-gradle-plugin" } junit4 = { group = "junit", name = "junit", version.ref = "junit4" } theoplayer = { group = "com.theoplayer.theoplayer-sdk-android", name = "core", version.ref = "theoplayer" } -theoplayer-ads = { group = "com.theoplayer.theoplayer-sdk-android", name = "integration-ads", version.ref = "theoplayer" } theoplayer-ads-ima = { group = "com.theoplayer.theoplayer-sdk-android", name = "integration-ads-ima", version.ref = "theoplayer" } theoplayer-cast = { group = "com.theoplayer.theoplayer-sdk-android", name = "integration-cast", version.ref = "theoplayer" } diff --git a/ui/src/main/java/com/theoplayer/android/ui/Player.kt b/ui/src/main/java/com/theoplayer/android/ui/Player.kt index 250d135..93b098c 100644 --- a/ui/src/main/java/com/theoplayer/android/ui/Player.kt +++ b/ui/src/main/java/com/theoplayer/android/ui/Player.kt @@ -296,8 +296,6 @@ enum class StreamType { internal class PlayerImpl(override val theoplayerView: THEOplayerView?) : Player { override val player = theoplayerView?.player override val ads = theoplayerView?.player?.ads - override var cast by mutableStateOf(null) - private set override var currentTime by mutableStateOf(0.0) private set override var duration by mutableStateOf(Double.NaN) @@ -368,8 +366,6 @@ internal class PlayerImpl(override val theoplayerView: THEOplayerView?) : Player _source = player?.source error = null firstPlay = false - // The cast integration is only registered *after* rememberPlayer() is called, - // so it's not available at construction time. Check if it's available now. updateCast(theoplayerView?.cast) updateCurrentTimeAndPlaybackState() updateDuration() @@ -612,12 +608,31 @@ internal class PlayerImpl(override val theoplayerView: THEOplayerView?) : Player private val textTrackListChangeListener = EventListener { updateActiveSubtitleTrack() } - override var castState: PlayerCastState by mutableStateOf(PlayerCastState.UNAVAILABLE) - override var castReceiverName: String? by mutableStateOf(null) + private var _cast by mutableStateOf(null) + private var _castState: PlayerCastState by mutableStateOf(PlayerCastState.UNAVAILABLE) + private var _castReceiverName: String? by mutableStateOf(null) + override val cast: Cast? + get() { + // The cast integration is only registered *after* rememberPlayer() is called, + // so it might not be available at construction time. + // Always use the getter on THEOplayerView to get the current cast integration. + updateCast(theoplayerView?.cast) + return _cast + } + override val castState: PlayerCastState + get() { + updateCast(theoplayerView?.cast) + return _castState + } + override val castReceiverName: String? + get() { + updateCast(theoplayerView?.cast) + return _castReceiverName + } private fun updateCast(cast: Cast?) { - if (this.cast == cast) return - this.cast?.let { oldCast -> + if (_cast == cast) return + _cast?.let { oldCast -> oldCast.chromecast.removeEventListener( ChromecastEventTypes.STATECHANGE, chromecastStateChangeListener @@ -627,7 +642,7 @@ internal class PlayerImpl(override val theoplayerView: THEOplayerView?) : Player chromecastErrorListener ) } - this.cast = cast + _cast = cast cast?.let { cast.chromecast.addEventListener( ChromecastEventTypes.STATECHANGE, @@ -639,8 +654,8 @@ internal class PlayerImpl(override val theoplayerView: THEOplayerView?) : Player } private fun updateCastState() { - castState = cast?.chromecast?.state ?: PlayerCastState.UNAVAILABLE - castReceiverName = cast?.chromecast?.receiverName + _castState = cast?.chromecast?.state ?: PlayerCastState.UNAVAILABLE + _castReceiverName = cast?.chromecast?.receiverName } private val chromecastStateChangeListener = @@ -657,6 +672,7 @@ internal class PlayerImpl(override val theoplayerView: THEOplayerView?) : Player updateActiveVideoTrack() updateAudioTracks() updateSubtitleTracks() + updateCast(theoplayerView?.cast) updateCastState() player?.addEventListener(PlayerEventTypes.PLAY, playListener) player?.addEventListener(PlayerEventTypes.PAUSE, pauseListener) @@ -710,7 +726,6 @@ internal class PlayerImpl(override val theoplayerView: THEOplayerView?) : Player ads?.addEventListener(AdsEventTypes.AD_BREAK_BEGIN, adListener) ads?.addEventListener(AdsEventTypes.AD_SKIP, adListener) ads?.addEventListener(AdsEventTypes.AD_BREAK_END, adListener) - updateCast(theoplayerView?.cast) fullscreenHandler?.onFullscreenChangeListener = fullscreenListener }