diff --git a/demos/compose/README.md b/demos/compose/README.md
new file mode 100644
index 0000000000..a70fc11022
--- /dev/null
+++ b/demos/compose/README.md
@@ -0,0 +1,14 @@
+# ExoPlayer demo with Compose integration
+
+This is an experimental ExoPlayer demo app that is built fully using Compose
+features. This should be taken as Work-In-Progress, rather than experimental API
+for testing out application development with the media3 and Jetpack Compose
+libraries. Please await further announcement via Release Notes for when the
+implementation is fully integrated into the library.
+
+For an intermediate solution, use Jetpack Compose Interop with AndroidView and
+PlayerView. However, note that it provides limited functionality and some
+features may not be supported.
+
+See the [demos README](../README.md) for instructions on how to build and run
+this demo.
diff --git a/demos/compose/build.gradle b/demos/compose/build.gradle
new file mode 100644
index 0000000000..e1e3393675
--- /dev/null
+++ b/demos/compose/build.gradle
@@ -0,0 +1,76 @@
+// Copyright 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+apply from: '../../constants.gradle'
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+
+android {
+ namespace 'androidx.media3.demo.compose'
+
+ compileSdkVersion project.ext.compileSdkVersion
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ defaultConfig {
+ versionName project.ext.releaseVersion
+ versionCode project.ext.releaseVersionCode
+ minSdkVersion 21
+ targetSdkVersion project.ext.appTargetSdkVersion
+ }
+
+ buildTypes {
+ release {
+ shrinkResources true
+ minifyEnabled true
+ signingConfig signingConfigs.debug
+ }
+ debug {
+ jniDebuggable = true
+ }
+ }
+
+ lintOptions {
+ // The demo app isn't indexed, and doesn't have translations.
+ disable 'GoogleAppIndexingWarning','MissingTranslation'
+ }
+ buildFeatures {
+ viewBinding true
+ compose true
+ }
+ composeOptions {
+ kotlinCompilerExtensionVersion = "1.5.0"
+ }
+}
+
+dependencies {
+ def composeBom = platform('androidx.compose:compose-bom:2024.02.00')
+ implementation composeBom
+
+ implementation 'androidx.activity:activity-compose:1.8.2'
+ implementation 'androidx.compose.foundation:foundation-android:1.6.4'
+ implementation 'androidx.compose.material3:material3-android:1.2.1'
+ implementation 'com.google.android.material:material:' + androidxMaterialVersion
+
+ implementation project(modulePrefix + 'lib-exoplayer')
+
+ // For detecting and debugging leaks only. LeakCanary is not needed for demo app to work.
+ debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.10'
+}
diff --git a/demos/compose/src/main/AndroidManifest.xml b/demos/compose/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..a348407347
--- /dev/null
+++ b/demos/compose/src/main/AndroidManifest.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/compose/src/main/java/androidx/media3/demo/compose/MainActivity.kt b/demos/compose/src/main/java/androidx/media3/demo/compose/MainActivity.kt
new file mode 100644
index 0000000000..16d24d4f7c
--- /dev/null
+++ b/demos/compose/src/main/java/androidx/media3/demo/compose/MainActivity.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.media3.demo.compose
+
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.activity.enableEdgeToEdge
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.text.style.TextAlign
+import androidx.media3.common.MediaItem
+import androidx.media3.demo.compose.data.videos
+import androidx.media3.exoplayer.ExoPlayer
+
+class MainActivity : ComponentActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ setContent {
+ Surface(modifier = Modifier.fillMaxSize()) {
+ Column(
+ modifier = Modifier.fillMaxWidth(),
+ verticalArrangement = Arrangement.Center,
+ horizontalAlignment = Alignment.CenterHorizontally,
+ ) {
+ Text(text = "Placeholder for your Player", textAlign = TextAlign.Center)
+ PlayerScreen(videos[0])
+ }
+ }
+ }
+ }
+}
+
+@Composable
+fun PlayerScreen(videoUrl: String) {
+ val exoPlayer =
+ ExoPlayer.Builder(LocalContext.current).build().apply {
+ setMediaItem(MediaItem.fromUri(videoUrl))
+ prepare()
+ playWhenReady = true
+ }
+}
diff --git a/demos/compose/src/main/java/androidx/media3/demo/compose/data/videos.kt b/demos/compose/src/main/java/androidx/media3/demo/compose/data/videos.kt
new file mode 100644
index 0000000000..0da7be9aba
--- /dev/null
+++ b/demos/compose/src/main/java/androidx/media3/demo/compose/data/videos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.media3.demo.compose.data
+
+val videos =
+ listOf(
+ "https://html5demos.com/assets/dizzy.mp4",
+ "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/gear0/fileSequence0.aac",
+ "https://storage.googleapis.com/exoplayer-test-media-1/gen-3/screens/dash-vod-single-segment/video-vp9-360.webm",
+ )
diff --git a/demos/compose/src/main/res/drawable/divider.xml b/demos/compose/src/main/res/drawable/divider.xml
new file mode 100644
index 0000000000..1602867ace
--- /dev/null
+++ b/demos/compose/src/main/res/drawable/divider.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/demos/compose/src/main/res/mipmap-hdpi/ic_launcher.png b/demos/compose/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000000..adaa93220e
Binary files /dev/null and b/demos/compose/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/demos/compose/src/main/res/mipmap-mdpi/ic_launcher.png b/demos/compose/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000000..9b6f7d5e80
Binary files /dev/null and b/demos/compose/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/demos/compose/src/main/res/mipmap-xhdpi/ic_launcher.png b/demos/compose/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000000..2101026c9f
Binary files /dev/null and b/demos/compose/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/demos/compose/src/main/res/mipmap-xxhdpi/ic_launcher.png b/demos/compose/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..223ec8bd11
Binary files /dev/null and b/demos/compose/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/demos/compose/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/demos/compose/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..698ed68c42
Binary files /dev/null and b/demos/compose/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/demos/compose/src/main/res/values-night/themes.xml b/demos/compose/src/main/res/values-night/themes.xml
new file mode 100644
index 0000000000..454bf8cb30
--- /dev/null
+++ b/demos/compose/src/main/res/values-night/themes.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
diff --git a/demos/compose/src/main/res/values/colors.xml b/demos/compose/src/main/res/values/colors.xml
new file mode 100644
index 0000000000..dac0cb81c7
--- /dev/null
+++ b/demos/compose/src/main/res/values/colors.xml
@@ -0,0 +1,30 @@
+
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+ #FF999999
+ #292929
+ #1c1c1c
+ #363434
+ #635E5E
+ #646464
+
diff --git a/demos/compose/src/main/res/values/strings.xml b/demos/compose/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..a11306db98
--- /dev/null
+++ b/demos/compose/src/main/res/values/strings.xml
@@ -0,0 +1,26 @@
+
+
+
+ Media3 Compose Demo
+ Current playlist
+ Click to view your play list
+ Added %1$s to playlist
+ Shuffle
+ Play
+ Waiting for playlist to load…
+
+ "Without notification access the app can't warn about failed background operations"
+
diff --git a/demos/compose/src/main/res/values/themes.xml b/demos/compose/src/main/res/values/themes.xml
new file mode 100644
index 0000000000..0918919117
--- /dev/null
+++ b/demos/compose/src/main/res/values/themes.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
diff --git a/settings.gradle b/settings.gradle
index f4f29b8a97..206115c3a2 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -31,6 +31,8 @@ include modulePrefix + 'demo'
project(modulePrefix + 'demo').projectDir = new File(rootDir, 'demos/main')
include modulePrefix + 'demo-cast'
project(modulePrefix + 'demo-cast').projectDir = new File(rootDir, 'demos/cast')
+include modulePrefix + 'demo-compose'
+project(modulePrefix + 'demo-compose').projectDir = new File(rootDir, 'demos/compose')
include modulePrefix + 'demo-gl'
project(modulePrefix + 'demo-gl').projectDir = new File(rootDir, 'demos/gl')
include modulePrefix + 'demo-session'