Cicero
09/22/2021, 1:03 PMCicero
09/22/2021, 1:05 PMCicero
09/22/2021, 1:05 PMimport android.net.Uri
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.viewinterop.AndroidView
import com.google.android.exoplayer2.C
import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.SimpleExoPlayer
import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout
import com.google.android.exoplayer2.ui.PlayerView
import com.google.android.exoplayer2.upstream.DataSource
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import com.google.android.exoplayer2.util.Util
@Composable
fun VideoPlayerUI(
fitnessDetailItem: FitnessItemDetailImpl?,
onClickBack: () -> Unit = {},
onAddFavorite: (FitnessItemDetailImpl?) -> Unit = {}
) {
AppTopBar(
title = "Player",
iconsLeft = listOf(
ActionItemImmutable(
iconId = R.drawable.ic_back_arrow,
action = onClickBack
)
),
iconsRight = listOf(
ActionItemMutable(
action = { onAddFavorite(fitnessDetailItem) },
tint = Primary,
primaryIconId = R.drawable.ic_favorite_active,
secondaryIconId = R.drawable.ic_favorite_inactive,
state = fitnessDetailItem?.isFavorite == true
)
)
) {
AppLazyColumn {
item {
Column(modifier = Modifier.fillMaxSize()) {
val mediaPlayback = VideoPlayer1("")
AppSpacer()
Row {
AppButton(label = "TE\$T") {
mediaPlayback.playPause()
}
}
}
}
}
}
}
@Composable
fun VideoPlayer1(sourceUrl: String): MediaPlayback {
// This is the official way to access current context from Composable functions
val context = LocalContext.current
// Do not recreate the player everytime this Composable commits
val exoPlayer = remember(context) {
SimpleExoPlayer.Builder(context).build().apply {
val dataSourceFactory: DataSource.Factory = DefaultDataSourceFactory(
context,
Util.getUserAgent(context, context.packageName)
)
val source = ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(
MediaItem.fromUri(
Uri.parse(
// Big Buck Bunny from Blender Project
"<https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4>"
)
)
)
this.setMediaSource(source)
this.prepare()
}
}
exoPlayer.videoScalingMode = C.VIDEO_SCALING_MODE_SCALE_TO_FIT
exoPlayer.repeatMode = Player.REPEAT_MODE_ONE
// Gateway to traditional Android Views
DisposableEffect(
BoxWithConstraints(modifier = Modifier
.fillMaxWidth()
.height(gu(40f))) {
AndroidView(
factory = {
PlayerView(context).apply {
hideController()
useController = false
resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIXED_HEIGHT
player = exoPlayer
layoutParams = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
}
}
)
}
) {
onDispose {
exoPlayer.release()
}
}
return remember(exoPlayer) {
object : MediaPlayback {
override fun playPause() {
exoPlayer.playWhenReady = !exoPlayer.playWhenReady
}
override fun forward(durationInMillis: Long) {
exoPlayer.seekTo(exoPlayer.currentPosition + durationInMillis)
}
override fun rewind(durationInMillis: Long) {
exoPlayer.seekTo(exoPlayer.currentPosition - durationInMillis)
}
}
}
}
interface MediaPlayback {
fun playPause()
fun forward(durationInMillis: Long)
fun rewind(durationInMillis: Long)
}
Cicero
09/22/2021, 1:12 PMCicero
09/22/2021, 1:16 PMCicero
09/22/2021, 1:19 PMAppButton(label = "TE\$ST") {
mediaPlayback.playPause()
}
the method is invoked, but there is no click on the button.Cicero
09/22/2021, 1:37 PM