5

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.

Tobonaut
  • 2,245
  • 2
  • 26
  • 39

2 Answers2

10

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
    })
}
Mohamed ali
  • 116
  • 1
  • 2
  • If anyone troubles with black and white screen while using this composable. Try it on a real device! – Tunahan Mar 04 '23 at 00:06
7

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 :)

nglauber
  • 18,674
  • 6
  • 70
  • 75
  • Thanks for your help. I nearly got it working. I just have a problem that the fm aka there fragment manager does not know .commit and .add - I guess I have the wrong import statement. – Tobonaut Aug 26 '22 at 14:36
  • 1
    I forgot to add the fragment-ktx dependency. I edited the answer to include it. – nglauber Aug 27 '22 at 03:49
  • Again thanks, now I have to check how to work with a `ComponentActivity` instead of a `AppCombatActivity` but it compiles! <3 – Tobonaut Aug 29 '22 at 14:39
  • I think If I used replace the MainActivity's super class, I need another theming - app crashes – Tobonaut Aug 29 '22 at 14:40
  • I pushed my sample in this repo. Please, take a look... https://github.com/nglauber/JetpackComposePlayground/blob/master/app/src/main/java/br/com/nglauber/jetpackcomposeplayground/screens/YouTubeScreen.kt – nglauber Aug 29 '22 at 14:53
  • Awesome, if I will ever visit brasil, I will spend you one or two coffees. Nevertheless I cannot build your project due to "Android Studio not compatible". But that's not important. I guess I cannot use only a MD3 Theme file but also I have to set the values in the xml to get my styles back :) – Tobonaut Aug 29 '22 at 15:10
  • Never mind! A clean & rebuild fixed it! Sorry for your time! – Tobonaut Aug 29 '22 at 15:23
  • where do you define R.id.fragment_container_view_tag? – Dmitri Dec 21 '22 at 20:53
  • it is declared in the fragment library `androidx.fragment:fragment-ktx` – nglauber Dec 22 '22 at 10:02
  • The official page says "This SDK is no longer supported or maintained by YouTube. It will be fully deprecated on or after May 1, 2023" there is an alternative for mobile Apps? – user2342558 Mar 24 '23 at 11:31