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; } /**