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'