diff --git a/CHANGELOG.md b/CHANGELOG.md
index 61123f086..03d95a7b9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Fixed a memory leak on iOS, caused by the wrapping ViewController that was keeping a strong reference to the THEOplayerRCTView.
+### Added
+
+- Added support for the experimental media3 player pipeline on Android.
+
### Changed
- **BREAKING**: Changed the `view` parameter in the `Omid` API from a ref container to a native node handle when registering "friendly" obstructions.
diff --git a/android/build.gradle b/android/build.gradle
index 356ee5eb7..1baab076a 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -32,6 +32,7 @@ def enabledTHEOads = safeExtGet("THEOplayer_extensionTHEOads", 'false').toBoolea
def enabledAds = enabledGoogleIMA || enabledGoogleDAI || enabledTHEOads
def enabledCast = safeExtGet("THEOplayer_extensionCast", 'false').toBoolean()
def enabledMediaSession = safeExtGet("THEOplayer_extensionMediaSession", 'true').toBoolean()
+def enabledMedia3 = safeExtGet("THEOplayer_extensionMedia3", 'true').toBoolean()
android {
compileSdk safeExtGet('THEOplayer_compileSdkVersion', 34)
@@ -66,6 +67,7 @@ android {
buildConfigField "boolean", "EXTENSION_ADS", "${enabledAds}"
buildConfigField "boolean", "EXTENSION_CAST", "${enabledCast}"
buildConfigField "boolean", "EXTENSION_MEDIASESSION", "${enabledMediaSession}"
+ buildConfigField "boolean", "EXTENSION_MEDIA3", "${enabledMedia3}"
consumerProguardFiles 'proguard-rules.pro'
}
@@ -93,7 +95,9 @@ android {
rootProject.allprojects {
repositories {
+ mavenLocal()
maven { url "https://maven.theoplayer.com/releases" }
+ maven { url "https://maven.theoplayer.com/snapshots" }
maven { url("$rootDir/../node_modules/react-native-theoplayer/android/local") }
}
}
@@ -110,8 +114,8 @@ repositories {
maven { url "https://maven.theoplayer.com/releases" }
}
-// The minimum supported THEOplayer version is 8.3.0
-def theoplayer_sdk_version = safeExtGet('THEOplayer_sdk', '[8.3.0, 9.0.0)')
+// The minimum supported THEOplayer version is 8.5.0
+def theoplayer_sdk_version = safeExtGet('THEOplayer_sdk', '[8.5.0, 9.0.0)')
def theoplayer_mediasession_version = safeExtGet('THEOplayer_mediasession', '[8.0.0, 9.0.0)')
dependencies {
@@ -158,6 +162,14 @@ dependencies {
println('Disable THEOplayer cast extension.')
compileOnly "com.theoplayer.theoplayer-sdk-android:integration-cast:${theoplayer_sdk_version}"
}
+
+ if (enabledMedia3) {
+ println('Enable THEOplayer media3 extension.')
+ implementation "com.theoplayer.theoplayer-sdk-android:integration-media3:${theoplayer_sdk_version}"
+ } else {
+ println('Disable THEOplayer media3 extension.')
+ compileOnly "com.theoplayer.theoplayer-sdk-android:integration-media3:${theoplayer_sdk_version}"
+ }
}
// Make sure to align all ads extension versions
diff --git a/android/src/main/java/com/theoplayer/PlayerConfigAdapter.kt b/android/src/main/java/com/theoplayer/PlayerConfigAdapter.kt
index 27d443ad9..0f42b3df8 100644
--- a/android/src/main/java/com/theoplayer/PlayerConfigAdapter.kt
+++ b/android/src/main/java/com/theoplayer/PlayerConfigAdapter.kt
@@ -21,6 +21,7 @@ private const val PROP_UI_ENABLED = "uiEnabled"
private const val PROP_CAST_STRATEGY = "strategy"
private const val PROP_RETRY_CONFIG = "retryConfiguration"
private const val PROP_HLS_DATE_RANGE = "hlsDateRange"
+private const val PROP_USE_MEDIA3 = "useMedia3"
private const val PROP_RETRY_MAX_RETRIES = "maxRetries"
private const val PROP_RETRY_MIN_BACKOFF = "minimumBackoff"
private const val PROP_RETRY_MAX_BACKOFF = "maximumBackoff"
@@ -39,6 +40,12 @@ private const val PROP_ALLOWED_MIMETYPES = "allowedMimeTypes"
class PlayerConfigAdapter(private val configProps: ReadableMap?) {
+ /**
+ * Whether the Media3 extension is used for play-out.
+ */
+ var useMedia3: Boolean = false
+ private set
+
/**
* Get general THEOplayerConfig object; these properties apply:
* - license: The license for the player.
@@ -63,6 +70,9 @@ class PlayerConfigAdapter(private val configProps: ReadableMap?) {
if (hasKey(PROP_HLS_DATE_RANGE)) {
hlsDateRange(getBoolean(PROP_HLS_DATE_RANGE))
}
+ if (hasKey(PROP_USE_MEDIA3)) {
+ useMedia3 = getBoolean(PROP_USE_MEDIA3)
+ }
pipConfiguration(PipConfiguration.Builder().build())
}
}.build()
diff --git a/android/src/main/java/com/theoplayer/ReactTHEOplayerContext.kt b/android/src/main/java/com/theoplayer/ReactTHEOplayerContext.kt
index 93e59c852..9e29bb868 100644
--- a/android/src/main/java/com/theoplayer/ReactTHEOplayerContext.kt
+++ b/android/src/main/java/com/theoplayer/ReactTHEOplayerContext.kt
@@ -24,6 +24,8 @@ import com.theoplayer.android.api.cast.CastIntegration
import com.theoplayer.android.api.cast.CastIntegrationFactory
import com.theoplayer.android.api.event.EventListener
import com.theoplayer.android.api.event.player.*
+import com.theoplayer.android.api.media3.Media3PlayerIntegration
+import com.theoplayer.android.api.media3.Media3PlayerIntegrationFactory
import com.theoplayer.android.api.player.Player
import com.theoplayer.android.connector.mediasession.MediaSessionConnector
import com.theoplayer.audio.AudioBecomingNoisyManager
@@ -84,6 +86,8 @@ class ReactTHEOplayerContext private constructor(
var imaIntegration: GoogleImaIntegration? = null
private var theoAdsIntegration: TheoAdsIntegration? = null
var castIntegration: CastIntegration? = null
+ @Suppress("UnstableApiUsage")
+ private var media3Integration: Media3PlayerIntegration? = null
var wasPlayingOnHostPause: Boolean = false
private var isHostPaused: Boolean = false
@@ -321,6 +325,23 @@ class ReactTHEOplayerContext private constructor(
} catch (e: Exception) {
Log.w(TAG, "Failed to configure Cast integration ${e.message}")
}
+ try {
+ if (BuildConfig.EXTENSION_MEDIA3) {
+ @Suppress("UnstableApiUsage")
+ media3Integration =
+ Media3PlayerIntegrationFactory.createMedia3PlayerIntegration { _, _ ->
+ // selectedSource -> represents the TypedSource the player picked to play.
+ // source -> represents the SourceDescription passed to the player.
+ // return true -> the Media3 integration pipeline will be used to play the selected source.
+ // return false -> the default pipeline will be used to play the selected source.
+ configAdapter.useMedia3
+ }
+ playerView.player.addIntegration(media3Integration)
+ }
+ } catch (e: Exception) {
+ Log.w(TAG, "Failed to configure Cast integration ${e.message}")
+ }
+
// Add other future integrations here.
}
diff --git a/example/android/gradle.properties b/example/android/gradle.properties
index d58199b3a..3675dabe0 100644
--- a/example/android/gradle.properties
+++ b/example/android/gradle.properties
@@ -41,7 +41,7 @@ newArchEnabled=false
hermesEnabled=true
# Version of the THEOplayer SDK, if not specified, the latest available version within bounds is set.
-#THEOplayer_sdk=[8.3.0, 9.0.0)
+#THEOplayer_sdk=[8.5.0, 9.0.0)
# Override Android sdk versions
#THEOplayer_compileSdkVersion = 34
@@ -63,6 +63,7 @@ THEOplayer_extensionGoogleDAI = true
THEOplayer_extensionCast = true
THEOplayer_extensionTHEOads = true
THEOplayer_extensionMediaSession = true
+THEOplayer_extensionMedia3 = true
# Optionally limit timeUpdate rate, which could improve performance.
# Possible values: (default: UNLIMITED)
diff --git a/src/api/config/PlayerConfiguration.ts b/src/api/config/PlayerConfiguration.ts
index 4d70204bc..26cbd5eb3 100644
--- a/src/api/config/PlayerConfiguration.ts
+++ b/src/api/config/PlayerConfiguration.ts
@@ -88,6 +88,17 @@ export interface PlayerConfiguration {
*
- This parameter only applies to Web and Android platforms.
*/
liveOffset?: number;
+
+ /**
+ * Sets whether the Media3 extension is used for play-out on Android.
+ *
+ * @experimental
+ * @remarks
+ *
- This parameter only applies to Android platforms.
+ *
+ * @defaultValue `false`.
+ */
+ useMedia3?: boolean;
}
/**