diff --git a/androidenhancedvideoplayer/build.gradle b/androidenhancedvideoplayer/build.gradle
index 801a7a5..19999c4 100644
--- a/androidenhancedvideoplayer/build.gradle
+++ b/androidenhancedvideoplayer/build.gradle
@@ -69,6 +69,8 @@ dependencies {
// exoplayer
implementation "androidx.media3:media3-exoplayer:$mediaVersion"
implementation "androidx.media3:media3-ui:$mediaVersion"
+ implementation "androidx.media3:media3-cast:$mediaVersion"
+ implementation 'androidx.appcompat:appcompat:1.3.1'
}
afterEvaluate {
diff --git a/androidenhancedvideoplayer/src/main/AndroidManifest.xml b/androidenhancedvideoplayer/src/main/AndroidManifest.xml
index 8bdb7e1..e8f2b3c 100644
--- a/androidenhancedvideoplayer/src/main/AndroidManifest.xml
+++ b/androidenhancedvideoplayer/src/main/AndroidManifest.xml
@@ -1,4 +1,9 @@
+
+
+
diff --git a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/CastOptionsProvider.kt b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/CastOptionsProvider.kt
new file mode 100644
index 0000000..bcaab72
--- /dev/null
+++ b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/CastOptionsProvider.kt
@@ -0,0 +1,25 @@
+package com.profusion.androidenhancedvideoplayer
+
+import android.content.Context
+import com.google.android.gms.cast.CastMediaControlIntent
+import com.google.android.gms.cast.LaunchOptions
+import com.google.android.gms.cast.framework.CastOptions
+import com.google.android.gms.cast.framework.OptionsProvider
+import com.google.android.gms.cast.framework.SessionProvider
+
+class CastOptionsProvider : OptionsProvider {
+ override fun getCastOptions(context: Context): CastOptions {
+ val launchOptions = LaunchOptions.Builder()
+ .setAndroidReceiverCompatible(true)
+ .build()
+ return CastOptions.Builder()
+ .setLaunchOptions(launchOptions)
+ .setReceiverApplicationId(CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID)
+ .setStopReceiverApplicationWhenEndingSession(true)
+ .build()
+ }
+
+ override fun getAdditionalSessionProviders(p0: Context): MutableList? {
+ return null
+ }
+}
diff --git a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/EnhancedVideoPlayer.kt b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/EnhancedVideoPlayer.kt
index 9d66cad..33da7f5 100644
--- a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/EnhancedVideoPlayer.kt
+++ b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/EnhancedVideoPlayer.kt
@@ -10,9 +10,7 @@ import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.*
-import androidx.compose.runtime.getValue
import androidx.compose.runtime.saveable.rememberSaveable
-import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.*
@@ -22,6 +20,11 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.unit.*
import androidx.compose.ui.viewinterop.AndroidView
+import androidx.media3.cast.CastPlayer
+import androidx.media3.cast.SessionAvailabilityListener
+import androidx.media3.common.BasePlayer
+import androidx.media3.common.C
+import androidx.media3.common.MediaItem
import androidx.media3.common.Player
import androidx.media3.common.TrackSelectionParameters
import androidx.media3.common.Tracks
@@ -29,6 +32,7 @@ import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.AspectRatioFrameLayout
import androidx.media3.ui.PlayerView
+import com.google.android.gms.cast.framework.CastContext
import com.profusion.androidenhancedvideoplayer.R
import com.profusion.androidenhancedvideoplayer.components.playerOverlay.ControlsCustomization
import com.profusion.androidenhancedvideoplayer.components.playerOverlay.PlayerControls
@@ -74,6 +78,7 @@ fun EnhancedVideoPlayer(
zoomToFit: Boolean = true,
enableImmersiveMode: Boolean = true,
disableControls: Boolean = false,
+ disableCast: Boolean = false,
currentTimeTickInMs: Long = CURRENT_TIME_TICK_IN_MS,
controlsVisibilityDurationInMs: Long = PLAYER_CONTROLS_VISIBILITY_DURATION_IN_MS,
controlsCustomization: ControlsCustomization = ControlsCustomization(),
@@ -86,19 +91,25 @@ fun EnhancedVideoPlayer(
val orientation = configuration.orientation
val volumeController = remember { VolumeController(context) }
- var isPlaying by remember { mutableStateOf(exoPlayer.isPlaying) }
+ val castContext = CastContext.getSharedInstance()
+ val castPlayer = castContext?.let { CastPlayer(it) }
+ val mediaItems: List = listOfNotNull(exoPlayer.currentMediaItem)
+ var currentPlayer: Player by remember { mutableStateOf(exoPlayer) }
+ var isCasting by remember { mutableStateOf(false) }
+
+ var isPlaying by remember { mutableStateOf(currentPlayer.isPlaying) }
var isBuffering by remember {
- mutableStateOf(exoPlayer.playbackState == ExoPlayer.STATE_BUFFERING)
+ mutableStateOf(currentPlayer.playbackState == BasePlayer.STATE_BUFFERING)
}
- var hasEnded by remember { mutableStateOf(exoPlayer.playbackState == ExoPlayer.STATE_ENDED) }
+ var hasEnded by remember { mutableStateOf(currentPlayer.playbackState == BasePlayer.STATE_ENDED) }
var isControlsVisible by remember { mutableStateOf(false) }
- var speed by remember { mutableStateOf(exoPlayer.playbackParameters.speed) }
- var loop by remember { mutableStateOf(exoPlayer.repeatMode == ExoPlayer.REPEAT_MODE_ALL) }
- var currentTime by remember { mutableStateOf(exoPlayer.contentPosition) }
- var bufferedPosition by remember { mutableStateOf(exoPlayer.bufferedPosition) }
- var totalDuration by remember { mutableStateOf(exoPlayer.duration) }
+ var speed by remember { mutableStateOf(currentPlayer.playbackParameters.speed) }
+ var loop by remember { mutableStateOf(currentPlayer.repeatMode == BasePlayer.REPEAT_MODE_ALL) }
+ var currentTime by remember { mutableStateOf(currentPlayer.contentPosition) }
+ var bufferedPosition by remember { mutableStateOf(currentPlayer.bufferedPosition) }
+ var totalDuration by remember { mutableStateOf(currentPlayer.duration) }
var title by remember {
- mutableStateOf(exoPlayer.currentMediaItem?.mediaMetadata?.title?.toString())
+ mutableStateOf(currentPlayer.currentMediaItem?.mediaMetadata?.title?.toString())
}
var currentImagePreview by remember {
mutableStateOf(ImageBitmap(DEFAULT_THUMBNAIL_WIDTH, DEFAULT_THUMBNAIL_HEIGHT))
@@ -129,23 +140,47 @@ fun EnhancedVideoPlayer(
) {
mutableStateOf(
generateTrackQualityOptions(
- exoPlayer.currentTracks,
+ currentPlayer.currentTracks,
autoQualityTrack
)
)
}
+ fun setPlayer(newPlayer: Player) {
+ if (castContext != null && !disableCast && currentPlayer !== newPlayer) {
+ var mediaIndex = C.INDEX_UNSET
+ var playbackPositionMs = C.TIME_UNSET
+ var playWhenReady = false
+ val previousPlayer = currentPlayer
+
+ val playbackState = previousPlayer.playbackState
+ if (playbackState != Player.STATE_ENDED) {
+ mediaIndex = previousPlayer.currentMediaItemIndex
+ playbackPositionMs = previousPlayer.currentPosition
+ playWhenReady = previousPlayer.playWhenReady
+
+ previousPlayer.stop()
+ }
+
+ newPlayer.setMediaItems(mediaItems, mediaIndex, playbackPositionMs)
+ newPlayer.playWhenReady = playWhenReady
+ newPlayer.prepare()
+
+ currentPlayer = newPlayer
+ }
+ }
+
DisposableEffect(context) {
- val listener = object : Player.Listener {
+ val listener = object : Player.Listener, SessionAvailabilityListener {
override fun onEvents(player: Player, events: Player.Events) {
isPlaying = player.isPlaying
- isBuffering = player.playbackState == ExoPlayer.STATE_BUFFERING
- hasEnded = player.playbackState == ExoPlayer.STATE_ENDED
+ isBuffering = player.playbackState == BasePlayer.STATE_BUFFERING
+ hasEnded = player.playbackState == BasePlayer.STATE_ENDED
speed = player.playbackParameters.speed
title = player.mediaMetadata.title?.toString()
currentTime = player.contentPosition
totalDuration = player.duration
- loop = player.repeatMode == ExoPlayer.REPEAT_MODE_ALL
+ loop = player.repeatMode == BasePlayer.REPEAT_MODE_ALL
deviceVolume = player.deviceVolume
super.onEvents(player, events)
}
@@ -164,11 +199,26 @@ fun EnhancedVideoPlayer(
)
super.onTrackSelectionParametersChanged(parameters)
}
+
+ override fun onCastSessionAvailable() {
+ setPlayer(castPlayer ?: exoPlayer)
+ isCasting = true
+ isControlsVisible = true
+ }
+
+ override fun onCastSessionUnavailable() {
+ setPlayer(exoPlayer)
+ isCasting = false
+ }
}
exoPlayer.addListener(listener)
+ castPlayer?.addListener(listener)
+ castPlayer?.setSessionAvailabilityListener(listener)
onDispose {
exoPlayer.removeListener(listener)
+ castPlayer?.removeListener(listener)
+ castPlayer?.setSessionAvailabilityListener(null)
}
}
@@ -176,8 +226,8 @@ fun EnhancedVideoPlayer(
timeoutInMs = currentTimeTickInMs,
enabled = isControlsVisible
) {
- currentTime = exoPlayer.currentPosition
- bufferedPosition = exoPlayer.bufferedPosition
+ currentTime = currentPlayer.currentPosition
+ bufferedPosition = currentPlayer.bufferedPosition
}
LaunchedEffect(isFullScreen) {
@@ -198,7 +248,8 @@ fun EnhancedVideoPlayer(
isPlaying,
isBrightnessSliderDragged,
isVolumeSliderDragged,
- isTimeBarDragged
+ isTimeBarDragged,
+ isCasting
) {
if (
isControlsVisible &&
@@ -206,7 +257,8 @@ fun EnhancedVideoPlayer(
controlsVisibilityDurationInMs > 0 &&
!isBrightnessSliderDragged &&
!isTimeBarDragged &&
- !isVolumeSliderDragged
+ !isVolumeSliderDragged &&
+ !isCasting
) {
delay(controlsVisibilityDurationInMs)
isControlsVisible = false
@@ -258,22 +310,25 @@ fun EnhancedVideoPlayer(
} else {
AspectRatioFrameLayout.RESIZE_MODE_FIT
}
+ playerView.player = currentPlayer
}
)
if (!disableControls) {
Box(modifier = Modifier.matchParentSize()) {
SeekHandler(
- seekIncrement = exoPlayer::seekIncrement,
+ seekIncrement = currentPlayer::seekIncrement,
disableSeekForward = hasEnded,
+ isCasting = isCasting,
controlsCustomization = controlsCustomization,
toggleControlsVisibility = {
- setControlsVisibility(!isControlsVisible)
+ setControlsVisibility(!isControlsVisible || isCasting)
},
setControlsVisibility = ::setControlsVisibility,
transformSeekIncrementRatio = transformSeekIncrementRatio
)
PlayerControls(
title = title,
+ disableCast = disableCast,
isVisible = isControlsVisible,
isPlaying = isPlaying,
isBuffering = isBuffering,
@@ -285,15 +340,15 @@ fun EnhancedVideoPlayer(
brightnessMutableInteractionSource = brightnessMutableInteractionSource,
volumeMutableInteractionSource = volumeMutableInteractionSource,
timeBarMutableInteractionSource = timeBarMutableInteractionSource,
- totalDuration = totalDuration,
+ totalDuration = if (totalDuration > 0) totalDuration else 0,
currentTime = { currentTime },
bufferedPosition = { bufferedPosition },
- onPreviousClick = exoPlayer::seekToPrevious,
- onNextClick = exoPlayer::seekToNext,
+ onPreviousClick = currentPlayer::seekToPrevious,
+ onNextClick = currentPlayer::seekToNext,
onPauseToggle = when {
- hasEnded -> exoPlayer::seekToDefaultPosition
- isPlaying -> exoPlayer::pause
- else -> exoPlayer::play
+ hasEnded -> currentPlayer::seekToDefaultPosition
+ isPlaying -> currentPlayer::pause
+ else -> currentPlayer::play
},
onFullScreenToggle = {
when (isFullScreen) {
@@ -304,7 +359,7 @@ fun EnhancedVideoPlayer(
onSettingsToggle = { isSettingsOpen = !isSettingsOpen },
onSeekBarValueFinished = { value ->
currentTime = value
- exoPlayer.seekTo(value)
+ currentPlayer.seekTo(value)
},
onSeekBarValueChange = {
if (previewThumbnailBuilder != null) {
@@ -324,12 +379,12 @@ fun EnhancedVideoPlayer(
onDismissRequest = { isSettingsOpen = false },
speed = speed,
isLoopEnabled = loop,
- onSpeedSelected = exoPlayer::setPlaybackSpeed,
+ onSpeedSelected = currentPlayer::setPlaybackSpeed,
onIsLoopEnabledSelected = { value ->
- exoPlayer.repeatMode = if (value) {
- ExoPlayer.REPEAT_MODE_ALL
+ currentPlayer.repeatMode = if (value) {
+ BasePlayer.REPEAT_MODE_ALL
} else {
- ExoPlayer.REPEAT_MODE_OFF
+ BasePlayer.REPEAT_MODE_OFF
}
},
selectedQualityTrack = {
@@ -339,7 +394,7 @@ fun EnhancedVideoPlayer(
trackQualityOptions
},
onQualityChanged = { selectedQualityTrack ->
- exoPlayer.setVideoQuality(selectedQualityTrack)
+ currentPlayer.setVideoQuality(selectedQualityTrack)
},
customization = settingsControlsCustomization
)
diff --git a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/mediaRouter/MediaRouter.kt b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/mediaRouter/MediaRouter.kt
new file mode 100644
index 0000000..7ff9e93
--- /dev/null
+++ b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/mediaRouter/MediaRouter.kt
@@ -0,0 +1,27 @@
+package com.profusion.androidenhancedvideoplayer.components.mediaRouter
+
+import android.content.Context
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.viewinterop.AndroidView
+import com.google.android.gms.cast.framework.CastContext
+import com.profusion.androidenhancedvideoplayer.styling.Dimensions
+
+@Composable
+fun MediaRouter(context: Context, modifier: Modifier = Modifier) {
+ val viewModel = MediaRouterViewModel(context)
+ val castContext = CastContext.getSharedInstance()
+
+ if (castContext != null) {
+ Box(modifier = modifier) {
+ AndroidView(
+ factory = { viewModel.mediaRouteButton() },
+ modifier = Modifier.size(Dimensions.xlarge)
+ )
+ }
+ }
+}
diff --git a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/mediaRouter/MediaRouterViewModel.kt b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/mediaRouter/MediaRouterViewModel.kt
new file mode 100644
index 0000000..2b7591e
--- /dev/null
+++ b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/mediaRouter/MediaRouterViewModel.kt
@@ -0,0 +1,24 @@
+package com.profusion.androidenhancedvideoplayer.components.mediaRouter
+
+import android.content.Context
+import android.view.View
+import androidx.lifecycle.ViewModel
+import androidx.mediarouter.app.MediaRouteActionProvider
+import androidx.mediarouter.app.MediaRouteButton
+import androidx.mediarouter.media.MediaControlIntent
+import androidx.mediarouter.media.MediaRouteSelector
+
+class MediaRouterViewModel(context: Context) : ViewModel() {
+ private val mediaRouteActionProvider = MediaRouteActionProvider(context)
+
+ init {
+ mediaRouteActionProvider.onCreateMediaRouteButton()
+ mediaRouteActionProvider.routeSelector = MediaRouteSelector.Builder()
+ .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
+ .build()
+ }
+
+ fun mediaRouteButton(): View {
+ return mediaRouteActionProvider.onCreateActionView()
+ }
+}
diff --git a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/PlayerControls.kt b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/PlayerControls.kt
index 93c4868..2ff1bf9 100644
--- a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/PlayerControls.kt
+++ b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/PlayerControls.kt
@@ -33,6 +33,7 @@ data class ControlsCustomization(
fun PlayerControls(
modifier: Modifier = Modifier,
title: String? = null,
+ disableCast: Boolean = false,
isVisible: Boolean,
isPlaying: Boolean,
isBuffering: Boolean,
@@ -70,6 +71,7 @@ fun PlayerControls(
TopControls(
modifier = it,
title = title,
+ disableCast = disableCast,
shouldShowContent = shouldShowContent
)
},
diff --git a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/SeekHandler.kt b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/SeekHandler.kt
index ebda0db..1c95030 100644
--- a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/SeekHandler.kt
+++ b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/SeekHandler.kt
@@ -33,6 +33,7 @@ private const val TRANSITION_LABEL = "scaleSeekIcon"
fun SeekHandler(
seekIncrement: (Long) -> Unit,
disableSeekForward: Boolean,
+ isCasting: Boolean = false,
toggleControlsVisibility: () -> Unit,
setControlsVisibility: (value: Boolean) -> Unit,
transformSeekIncrementRatio: (tapCount: Int) -> Long,
@@ -68,6 +69,9 @@ fun SeekHandler(
delay(JOB_TIMEOUT)
forwardTapCount = 0
+ if (isCasting) {
+ setControlsVisibility(true)
+ }
}
}
@@ -81,6 +85,9 @@ fun SeekHandler(
delay(JOB_TIMEOUT)
rewindTapCount = 0
+ if (isCasting) {
+ setControlsVisibility(true)
+ }
}
}
diff --git a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/TopControls.kt b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/TopControls.kt
index 0f608ff..9c0bf24 100644
--- a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/TopControls.kt
+++ b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/TopControls.kt
@@ -1,6 +1,7 @@
package com.profusion.androidenhancedvideoplayer.components.playerOverlay
import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
@@ -9,14 +10,18 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
+import com.profusion.androidenhancedvideoplayer.components.mediaRouter.MediaRouter
import com.profusion.androidenhancedvideoplayer.styling.Dimensions
@Composable
+@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
fun TopControls(
modifier: Modifier = Modifier,
title: String? = null,
+ disableCast: Boolean = false,
shouldShowContent: Boolean = true
) {
Box(
@@ -24,16 +29,28 @@ fun TopControls(
.fillMaxWidth()
.padding(horizontal = Dimensions.large)
) {
- if (title != null && shouldShowContent) {
- Text(
- text = title,
- maxLines = 1,
- overflow = TextOverflow.Ellipsis,
- style = MaterialTheme.typography.titleLarge.copy(
- color = Color.White
- ),
- modifier = Modifier.align(Alignment.CenterStart)
- )
+ if (shouldShowContent) {
+ if (title != null) {
+ Text(
+ text = title,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
+ style = MaterialTheme.typography.titleLarge.copy(
+ color = Color.White
+ ),
+ modifier = Modifier.fillMaxWidth()
+ )
+ } else {
+ Spacer(modifier = Modifier.fillMaxWidth())
+ }
+
+ if (!disableCast) {
+ LocalContext.current.setTheme(androidx.appcompat.R.style.Theme_AppCompat_NoActionBar)
+ MediaRouter(
+ context = LocalContext.current,
+ modifier = Modifier.align(Alignment.CenterEnd)
+ )
+ }
}
}
}
diff --git a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/utils/ExoPlayerUtils.kt b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/utils/ExoPlayerUtils.kt
index ef1892d..e6b5e91 100644
--- a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/utils/ExoPlayerUtils.kt
+++ b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/utils/ExoPlayerUtils.kt
@@ -1,7 +1,7 @@
package com.profusion.androidenhancedvideoplayer.utils
-import androidx.media3.exoplayer.ExoPlayer
+import androidx.media3.common.Player
-fun ExoPlayer.seekIncrement(incrementMs: Long) {
+fun Player.seekIncrement(incrementMs: Long) {
seekTo(currentPosition + incrementMs)
}
diff --git a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/utils/TrackUtils.kt b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/utils/TrackUtils.kt
index eca0bb1..5f0bc1a 100644
--- a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/utils/TrackUtils.kt
+++ b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/utils/TrackUtils.kt
@@ -3,11 +3,11 @@ package com.profusion.androidenhancedvideoplayer.utils
import androidx.annotation.OptIn
import androidx.media3.common.C
import androidx.media3.common.Format
+import androidx.media3.common.Player
import androidx.media3.common.TrackSelectionOverride
import androidx.media3.common.TrackSelectionParameters
import androidx.media3.common.Tracks
import androidx.media3.common.util.UnstableApi
-import androidx.media3.exoplayer.ExoPlayer
import com.google.common.collect.ImmutableList
private const val NO_ROLE_FLAGS = 0
@@ -59,7 +59,7 @@ fun TrackSelectionParameters.getSelectedTrackQualityItem(
)
}
-fun ExoPlayer.setVideoQuality(track: TrackQualityItem) {
+fun Player.setVideoQuality(track: TrackQualityItem) {
trackSelectionParameters = when (track) {
is TrackQualityAuto -> {
trackSelectionParameters
diff --git a/app/build.gradle b/app/build.gradle
index c3628c6..56d75d2 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -5,7 +5,7 @@ plugins {
android {
namespace 'com.example.androidenhancedvideoplayer'
- compileSdk 33
+ compileSdk 34
defaultConfig {
applicationId "com.example.teste"
@@ -56,6 +56,7 @@ dependencies {
implementation 'androidx.compose.ui:ui-graphics'
implementation 'androidx.compose.ui:ui-tooling-preview'
implementation 'androidx.compose.material3:material3'
+ implementation 'com.google.android.gms:play-services-cast-framework:21.4.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
diff --git a/app/src/main/java/com/example/androidenhancedvideoplayer/MainActivity.kt b/app/src/main/java/com/example/androidenhancedvideoplayer/MainActivity.kt
index 8234b5e..a43ec0c 100644
--- a/app/src/main/java/com/example/androidenhancedvideoplayer/MainActivity.kt
+++ b/app/src/main/java/com/example/androidenhancedvideoplayer/MainActivity.kt
@@ -1,8 +1,8 @@
package com.example.androidenhancedvideoplayer
import android.os.Bundle
-import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
+import androidx.annotation.OptIn
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
@@ -11,7 +11,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.platform.LocalConfiguration
import androidx.core.view.WindowCompat
+import androidx.fragment.app.FragmentActivity
import androidx.media3.common.MediaItem
+import androidx.media3.common.MimeTypes
+import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.exoplayer.trackselection.AdaptiveTrackSelection
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector
@@ -21,15 +24,16 @@ import com.example.androidenhancedvideoplayer.ui.theme.AndroidEnhancedVideoPlaye
import com.example.androidenhancedvideoplayer.utils.ExampleUrl
import com.example.androidenhancedvideoplayer.utils.fillMaxSizeInLandscape
import com.example.androidenhancedvideoplayer.utils.safePaddingInPortrait
+import com.google.android.gms.cast.framework.CastContext
import com.profusion.androidenhancedvideoplayer.components.EnhancedVideoPlayer
import com.profusion.androidenhancedvideoplayer.components.playerOverlay.SettingsControlsCustomization
import kotlinx.coroutines.flow.MutableStateFlow
-class MainActivity : ComponentActivity() {
+class MainActivity : FragmentActivity() {
private lateinit var exoPlayer: ExoPlayer
private val isInPictureInPictureMode: MutableStateFlow = MutableStateFlow(false)
- @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
+ @OptIn(androidx.media3.common.util.UnstableApi::class)
private fun initializeExoPlayer() {
exoPlayer = ExoPlayer
.Builder(applicationContext)
@@ -38,7 +42,7 @@ class MainActivity : ComponentActivity() {
)
.build()
.apply {
- setMediaItem(MediaItem.fromUri(ExampleUrl.HLS_MULTI_AUDIO))
+ setMediaItem(MediaItem.Builder().setUri(ExampleUrl.DASH).setMimeType(MimeTypes.APPLICATION_MPD).build())
playWhenReady = true
addAnalyticsListener(EventLogger())
prepare()
@@ -54,6 +58,7 @@ class MainActivity : ComponentActivity() {
WindowCompat.setDecorFitsSystemWindows(window, false)
super.onCreate(savedInstanceState)
initializeExoPlayer()
+ CastContext.getSharedInstance(this)
setContent {
AndroidEnhancedVideoPlayerTheme {