Skip to content

Comments

Override default ExoPlayer layouts with custom ones to prevent overriding by other versions of the ExoPlayer library.#5841

Merged
andremion merged 3 commits intodevelopfrom
bug/fix-exoplayer-layout-incompatibility-with-legacy-versions
Jun 26, 2025
Merged

Override default ExoPlayer layouts with custom ones to prevent overriding by other versions of the ExoPlayer library.#5841
andremion merged 3 commits intodevelopfrom
bug/fix-exoplayer-layout-incompatibility-with-legacy-versions

Conversation

@VelikovPetar
Copy link
Contributor

@VelikovPetar VelikovPetar commented Jun 19, 2025

🎯 Goal

Resolves: https://linear.app/stream/issue/AND-610/exoplayer-compatibility-issue
Resolves a crash happening when attempting to play a video attachment from the SDK, while the integrator app includes the legacy com.google.android.exoplayer library.

Crash details:

  1. We are using the androidx.media3:media3-ui:1.6.1, while a customer is using the old com.google.android.exoplayer:exoplayer:2.13.3 (notice the package name difference)
  2. Both versions have the layout R.layout.exo_player_view used as a root view for the PlayerView . However, the one from media3 uses views from the androidx.media3.ui package, but the one from google uses views from the com.google.android.exoplayer2.ui package.
  3. In the integrator app, the R.layout.exo_player_view resource gets overridden by the one from google version, and when we try to render our own PlayerView , it fails to resolve the internal UIs, because they are different classes (from different package names).

Fix details:
Override the PlayerView properties: player_layout_id (default value is R.layout.exo_player_view) and the controller_layout_id (default value is R.layout.exo_player_control_view). We are overriding them with copied values from their default layouts, but we are using different layout IDs (stream_compose_exo_player_view and stream_compose_exo_player_control_view). This prevents the PlayerView layouts to be overridden by layouts from a different version of the library, because they now have a different name.

🛠 Implementation details

  1. Implement new stream_compose_exo_player_view and stream_compose_exo_player_control_view - copies of the default R.layout.exo_player_view and R.layout.exo_player_control_view
  2. Implement new base PlayerView layout stream_compose_player_view which uses the new root and controller layouts
  3. Inflate the PlayerView from the stream_compose_player_view instead of directly instantiating the view (PlayerView(context))

🎨 UI Changes

Before After
exoplayer-crash-before.mp4
exoplayer-crash-after.mp4

🧪 Testing

  1. Apply the provided patch
  2. Run the Compose sample
  3. Open a channel with a video attachment
  4. Click on the attached video
  5. Click play - the video should play and not crash
Add the legacy exoplayer dependency
Index: stream-chat-android-compose-sample/src/main/java/io/getstream/chat/android/compose/sample/feature/channel/list/ChannelsActivity.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/stream-chat-android-compose-sample/src/main/java/io/getstream/chat/android/compose/sample/feature/channel/list/ChannelsActivity.kt b/stream-chat-android-compose-sample/src/main/java/io/getstream/chat/android/compose/sample/feature/channel/list/ChannelsActivity.kt
--- a/stream-chat-android-compose-sample/src/main/java/io/getstream/chat/android/compose/sample/feature/channel/list/ChannelsActivity.kt	(revision b3ce00b49c8430c92f4a1e9debc1feeb2b192568)
+++ b/stream-chat-android-compose-sample/src/main/java/io/getstream/chat/android/compose/sample/feature/channel/list/ChannelsActivity.kt	(date 1750327445400)
@@ -48,6 +48,11 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.viewinterop.AndroidView
+import com.google.android.exoplayer2.ExoPlayer
+import com.google.android.exoplayer2.MediaItem
+import com.google.android.exoplayer2.ui.PlayerView
+import com.google.android.exoplayer2.ui.StyledPlayerView
 import io.getstream.chat.android.client.ChatClient
 import io.getstream.chat.android.compose.sample.ChatApp
 import io.getstream.chat.android.compose.sample.ChatHelper
@@ -76,7 +81,6 @@
 import io.getstream.chat.android.compose.ui.mentions.MentionList
 import io.getstream.chat.android.compose.ui.theme.ChannelOptionsTheme
 import io.getstream.chat.android.compose.ui.theme.ChatTheme
-import io.getstream.chat.android.compose.ui.threads.ThreadList
 import io.getstream.chat.android.compose.viewmodel.channels.ChannelListViewModel
 import io.getstream.chat.android.compose.viewmodel.channels.ChannelViewModelFactory
 import io.getstream.chat.android.compose.viewmodel.mentions.MentionListViewModel
@@ -197,6 +201,22 @@
 //                MyCustomUi()
     }
 
+    private fun createPlayerView(context: Context): PlayerView {
+        return PlayerView(context).apply {
+            val url = "https://us-east.stream-io-cdn.com/102398/attachments/07ea4932-52cc-4206-9feb-2b5ab38e2faa.PXL_20250607_215602930_LS.mp4?Key-Pair-Id=APKAIHG36VEWPDULE23Q&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly91cy1lYXN0LnN0cmVhbS1pby1jZG4uY29tLzEwMjM5OC9hdHRhY2htZW50cy8wN2VhNDkzMi01MmNjLTQyMDYtOWZlYi0yYjVhYjM4ZTJmYWEuUFhMXzIwMjUwNjA3XzIxNTYwMjkzMF9MUy5tcDQqIiwiQ29uZGl0aW9uIjp7IkRhdGVMZXNzVGhhbiI6eyJBV1M6RXBvY2hUaW1lIjoxNzUwOTM4MjM2fX19XX0_&Signature=Io8JqMwcggLV8rrmRUahnu7H5kuD24iINpucddL5OuD-tXKvsJc4Bb0gjcSOONovyZJgfqNV~5TbuCFrQ3cV5HUnuxoo3s00Cf9-krF93hTiw34LE2~MCGJ-TQGhQK6ldYpTQkaKCKTXC7XucbNTmElzcV2k6GkowhXekTVayOroUwQcExpzbvyDN2qm61LVowwSbzpTLSBjEw-TLzrJrvEpyDRoZoWGPHNRhNMj1hvlWP4MCBEQ143Gq26-w3ix9Ny3Ago30zDzaOzquFjj11gmR-edBXRUoc-f2GHDHHu~CAHIXcIAr1szcrJzFz7XCRuNjJuiWnM0MlZobpt6xQ__"
+            val player = ExoPlayer.Builder(context)
+                .build()
+            player.setMediaItem(MediaItem.fromUri(url))
+            this.player = player
+            useController = true
+            controllerShowTimeoutMs = 0 // Always show the controller
+            setShowNextButton(false)
+            setShowPreviousButton(false)
+            setShowFastForwardButton(false)
+            setShowRewindButton(false)
+        }
+    }
+
     @OptIn(ExperimentalMaterial3Api::class)
     @Composable
     private fun MentionsContent() {
@@ -210,10 +230,15 @@
 
     @Composable
     private fun ThreadsContent() {
-        ThreadList(
-            viewModel = threadsViewModel,
-            modifier = Modifier.fillMaxSize(),
-            onThreadClick = ::openThread,
+        // ThreadList(
+        //     viewModel = threadsViewModel,
+        //     modifier = Modifier.fillMaxSize(),
+        //     onThreadClick = ::openThread,
+        // )
+        AndroidView(
+            factory = { context ->
+                createPlayerView(context)
+            },
         )
     }
 
Index: stream-chat-android-compose-sample/build.gradle.kts
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/stream-chat-android-compose-sample/build.gradle.kts b/stream-chat-android-compose-sample/build.gradle.kts
--- a/stream-chat-android-compose-sample/build.gradle.kts	(revision b3ce00b49c8430c92f4a1e9debc1feeb2b192568)
+++ b/stream-chat-android-compose-sample/build.gradle.kts	(date 1750327188126)
@@ -131,6 +131,10 @@
 }
 
 dependencies {
+    // Exoplayer Legacy
+    implementation("com.google.android.exoplayer:exoplayer:2.13.3")
+    implementation("com.google.android.exoplayer:exoplayer-ui:2.13.3")
+
     implementation(project(":stream-chat-android-compose"))
     implementation(project(":stream-chat-android-offline"))
 

…ent overriding by other versions of the ExoPlayer library.
@github-actions
Copy link
Contributor

github-actions bot commented Jun 19, 2025

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 3.16 MB 3.16 MB 0.00 MB 🟢
stream-chat-android-offline 3.38 MB 3.38 MB 0.00 MB 🟢
stream-chat-android-ui-components 10.43 MB 10.43 MB 0.00 MB 🟢
stream-chat-android-compose 12.53 MB 12.53 MB 0.00 MB 🟢

@VelikovPetar VelikovPetar marked this pull request as ready for review June 19, 2025 11:23
@VelikovPetar VelikovPetar requested a review from a team as a code owner June 19, 2025 11:23
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
0.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

Copy link
Contributor

@andremion andremion left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job! 👏🏻

@andremion andremion merged commit fe89455 into develop Jun 26, 2025
12 of 13 checks passed
@andremion andremion deleted the bug/fix-exoplayer-layout-incompatibility-with-legacy-versions branch June 26, 2025 11:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants