Looking for a Jetpack Compose YouTube Video Player wrapper dependency

5k Views Asked by At

Intro

I'm new to Jetpack Compose and it is not that easy for me to understand or get everything correct on my first try.

That's why I love to have a look at other's open-source work to understand the topic a little bit better.

Problem

My current problem is that I must embed YouTube videos into my app. At first, I thought I use an embedded web view, but hey, I'm a native app dev, let's do it native!

But I stumbled a lot

  1. Is it true, that we as devs must use a local *.jar file from Google to embed the video player?
  2. Is it true, that there is no official Jetpack Compose component for that?
  3. Is it true, that there is no dependency our there which provides such functionality?
  4. Yes, I searched SO before I asked

That's why it would be awesome if someone of you could point me into the correct direction to make any progress with my tiny self-learning app.

3

There are 3 best solutions below

2
Mohamed ali On BEST ANSWER

the simplest way is first just add this line in gradle file

"implementation" ("com.pierfrancescosoffritti.androidyoutubeplayer:core:11.1.0")
@Composable
fun YoutubeScreen(
    videoId: String,
    modifier: Modifier
) {
    val ctx = LocalContext.current
    AndroidView(factory = {
        var view = YouTubePlayerView(it)
        val fragment = view.addYouTubePlayerListener(
            object : AbstractYouTubePlayerListener() {
                override fun onReady(youTubePlayer: YouTubePlayer) {
                    super.onReady(youTubePlayer)
                    youTubePlayer.loadVideo(videoId, 0f)
                }
            }
        )
        view
    })
}
10
nglauber On

Here are the answers:

  1. As the official page says, yes you have to download a JAR.

  2. Yes and it's not necessary. You can use AndroidView composable function to wrap a YouTubePlayerFragment and play a video.

    But here you need to do a small-hack because the YouTubePlayerFragment does not extends from androidx.fragment.app.Fragment. Therefore, you'll need the following:

    2.1 Create an implementation of YoutubePlayerFragment which uses androidx. You can copy from this gist.

    2.2 Then, you can use it in your composable...

@Composable
fun YoutubeScreen() {
    val ctx = LocalContext.current
    AndroidView(factory = {
        val fm = (ctx as AppCompatActivity).supportFragmentManager
        val view = FragmentContainerView(it).apply {
            id = R.id.fragment_container_view_tag
        }
        val fragment = YouTubePlayerSupportFragmentXKt().apply {
            initialize("YoutubeApiKey",
                object : YouTubePlayer.OnInitializedListener {
                    override fun onInitializationFailure(
                        provider: YouTubePlayer.Provider,
                        result: YouTubeInitializationResult
                    ) {
                        Toast.makeText(
                            context,
                            "Error playing video",
                            Toast.LENGTH_SHORT
                        ).show()
                    }

                    override fun onInitializationSuccess(
                        provider: YouTubePlayer.Provider,
                        player: YouTubePlayer,
                        wasRestored: Boolean
                    ) {
                        if (!wasRestored) {
                            player.cueVideo("YoutubeVideoId")
                        }
                    }
                })
        }
        fm.commit {
            setReorderingAllowed(true)
            add(R.id.fragment_container_view_tag, fragment)
        }
        view
    })
}

For the commit function above, you will need this dependency:

implementation "androidx.fragment:fragment-ktx:$fragment_ktx_version"

Then add this in your AndroidManifest.xml

<queries>
    <intent>
        <action android:name="com.google.android.youtube.api.service.START" />
    </intent>
</queries>

I tested the code above and it worked, but maybe you need some more working to handle orientation changes.

  1. AFAIK and I mentioned in #1, no, there is not.

  2. It's not a question :)

0
ipavlovskii On

You might use this library - https://github.com/IlyaPavlovskii/YouTubePlayer/

repositories {
    mavenCentral()
}

kotlin {
    sourceSets {
        commonMain {
            dependencies {
                implementation("io.github.ilyapavlovskii:youtubeplayer-compose:${latest_version}")
            }
        }
    }
}
val execCommand = mutableStateOf<YouTubeExecCommand?>(null)
YouTubePlayer(
    modifier = Modifier
        .fillMaxWidth()
        .height(300.dp),
    options = SimpleYouTubePlayerOptionsBuilder.builder {
        autoplay(true) // autoplay = true 
        controls(false).rel(false) // controls = false, rel = false
        ivLoadPolicy(false)
        ccLoadPolicy(false)
        fullscreen = true
    },
    execCommandState = execCommand,
    actionListener = { action ->
        when (action) {
            YouTubeEvent.Ready -> {
                execCommand.value = YouTubeExecCommand.LoadVideo(
                    videoId = YouTubeVideoId("ufKj1sBrC4Q"),
                )
            }

            is YouTubeEvent.VideoDuration -> {
                videoDuration = formatTime(action.duration)
            }

            is YouTubeEvent.TimeChanged -> {
                currentTime = formatTime(action.time)
            }

            is YouTubeEvent.OnVideoIdHandled,
            is YouTubeEvent.Error,
            is YouTubeEvent.PlaybackQualityChange,
            is YouTubeEvent.RateChange,
            is YouTubeEvent.StateChanged,
            -> println("webViewState. onAction HANDlED: $action")
        }
    },
)