react-native-theoplayer 7.0.0 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +0 -2
  3. package/android/build.gradle +1 -8
  4. package/android/src/main/java/com/theoplayer/PlayerConfigAdapter.kt +59 -2
  5. package/android/src/main/java/com/theoplayer/ReactTHEOplayerContext.kt +33 -12
  6. package/android/src/main/java/com/theoplayer/media/MediaPlaybackService.kt +1 -1
  7. package/android/src/main/java/com/theoplayer/media/MediaSessionConfig.kt +18 -0
  8. package/android/src/main/java/com/theoplayer/media/MediaSessionConfigAdapter.kt +23 -0
  9. package/ios/THEOplayerRCTSourceDescriptionBuilder.swift +1 -11
  10. package/ios/THEOplayerRCTTrackMetadataAggregator.swift +2 -0
  11. package/ios/ads/THEOplayerRCTAdsAPI+DAI.swift +1 -1
  12. package/ios/ads/THEOplayerRCTAdsAPI.swift +1 -1
  13. package/ios/ads/THEOplayerRCTAdsEventHandler.swift +2 -2
  14. package/ios/ads/THEOplayerRCTSourceDescriptionBuilder+Ads.swift +3 -3
  15. package/ios/ads/THEOplayerRCTView+Ads.swift +35 -1
  16. package/ios/ads/THEOplayerRCTView+AdsConfig.swift +33 -14
  17. package/ios/backgroundAudio/THEOplayerRCTRemoteCommandsManager.swift +2 -2
  18. package/ios/backgroundAudio/THEOplayerRCTView+BackgroundAudioConfig.swift +0 -12
  19. package/ios/pip/THEOplayerRCTPipControlsManager.swift +3 -3
  20. package/lib/commonjs/internal/THEOplayerView.web.js +11 -1
  21. package/lib/commonjs/internal/THEOplayerView.web.js.map +1 -1
  22. package/lib/commonjs/internal/adapter/THEOplayerWebAdapter.js +1 -1
  23. package/lib/commonjs/internal/adapter/THEOplayerWebAdapter.js.map +1 -1
  24. package/lib/commonjs/internal/adapter/web/WebMediaSession.js +10 -6
  25. package/lib/commonjs/internal/adapter/web/WebMediaSession.js.map +1 -1
  26. package/lib/module/internal/THEOplayerView.web.js +11 -1
  27. package/lib/module/internal/THEOplayerView.web.js.map +1 -1
  28. package/lib/module/internal/adapter/THEOplayerWebAdapter.js +1 -1
  29. package/lib/module/internal/adapter/THEOplayerWebAdapter.js.map +1 -1
  30. package/lib/module/internal/adapter/web/WebMediaSession.js +9 -5
  31. package/lib/module/internal/adapter/web/WebMediaSession.js.map +1 -1
  32. package/lib/typescript/api/ads/AdsConfiguration.d.ts +3 -2
  33. package/lib/typescript/api/ads/AdsConfiguration.d.ts.map +1 -1
  34. package/lib/typescript/api/ads/GoogleImaConfiguration.d.ts +34 -5
  35. package/lib/typescript/api/ads/GoogleImaConfiguration.d.ts.map +1 -1
  36. package/lib/typescript/api/media/MediaControlConfiguration.d.ts +19 -1
  37. package/lib/typescript/api/media/MediaControlConfiguration.d.ts.map +1 -1
  38. package/lib/typescript/internal/THEOplayerView.web.d.ts.map +1 -1
  39. package/lib/typescript/internal/adapter/web/WebMediaSession.d.ts +3 -6
  40. package/lib/typescript/internal/adapter/web/WebMediaSession.d.ts.map +1 -1
  41. package/package.json +1 -1
  42. package/react-native-theoplayer.podspec +18 -25
  43. package/src/api/ads/AdsConfiguration.ts +3 -2
  44. package/src/api/ads/GoogleImaConfiguration.ts +37 -5
  45. package/src/api/media/MediaControlConfiguration.ts +21 -1
  46. package/src/internal/THEOplayerView.web.tsx +14 -1
  47. package/src/internal/adapter/THEOplayerWebAdapter.ts +1 -1
  48. package/src/internal/adapter/web/WebMediaSession.ts +11 -9
package/CHANGELOG.md CHANGED
@@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.1.0/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [7.1.0] - 24-04-23
9
+
10
+ ### Fixed
11
+
12
+ - Fixed a build issue on tvOS example app due to the deprecated `prepare` method.
13
+
14
+ ### Added
15
+
16
+ - Added multiple configuration options to `GoogleImaConfiguration` for both iOS and Android. These map to the corresponding IMASettings from the underlying native Google IMA SDKs.
17
+ - Added `skipForwardInterval` and `skipBackwardInterval` properties to `MediaControlConfiguration` for Android and Web, enabling configurable skip intervals for media sessions.
18
+ - Added ios bridging code to make 'forced' property available from native iOS TextTrack API.
19
+
20
+ ### Removed
21
+
22
+ - Removed support for the web-based native iOS SDK on the RN iOS Bridge.
23
+
8
24
  ## [7.0.0] - 24-04-10
9
25
 
10
26
  ### Fixed
package/README.md CHANGED
@@ -168,11 +168,9 @@ This section gives an overview of features, limitations and known issues:
168
168
  - [Audio Control Management](./doc/audio-control.md)
169
169
  - [Background playback and notifications](./doc/background.md)
170
170
  - [Casting with Chromecast and Airplay](./doc/cast.md)
171
- - [Custom iOS framework](./doc/custom-ios-framework.md)
172
171
  - [Digital Rights Management (DRM)](./doc/drm.md)
173
172
  - [Fullscreen presentation](./doc/fullscreen.md)
174
173
  - [Media Caching](./doc/media-caching.md)
175
- - [Migrating to `react-native-theoplayer` v2.x](./doc/migrating-v2.md)
176
174
  - [Picture-in-Picture (PiP)](./doc/pip.md)
177
175
  - [Subtitles, Closed Captions and Metadata tracks](./doc/texttracks.md)
178
176
  - [Limitations and known issues](./doc/limitations.md)
@@ -118,14 +118,7 @@ dependencies {
118
118
  println("Using THEOplayer (${versionString(theoplayer_sdk_version)})")
119
119
  implementation "com.theoplayer.theoplayer-sdk-android:core:${theoplayer_sdk_version}"
120
120
  implementation "com.theoplayer.theoplayer-sdk-android:ads-wrapper:6.10.0"
121
-
122
- if (enabledMediaSession) {
123
- println("Enable THEOplayer MediaSession extension (${versionString(theoplayer_sdk_version)})")
124
- implementation "com.theoplayer.android-connector:mediasession:${theoplayer_sdk_version}"
125
- } else {
126
- println('Disable THEOplayer MediaSession extension.')
127
- compileOnly "com.theoplayer.android-connector:mediasession:${theoplayer_sdk_version}"
128
- }
121
+ implementation "com.theoplayer.android-connector:mediasession:${theoplayer_sdk_version}"
129
122
 
130
123
  if (enabledGoogleIMA) {
131
124
  println('Enable THEOplayer IMA extension.')
@@ -6,11 +6,14 @@ import com.google.ads.interactivemedia.v3.api.AdsRenderingSettings
6
6
  import com.google.ads.interactivemedia.v3.api.ImaSdkFactory
7
7
  import com.google.ads.interactivemedia.v3.api.ImaSdkSettings
8
8
  import com.theoplayer.android.api.THEOplayerConfig
9
+ import com.theoplayer.android.api.THEOplayerGlobal
9
10
  import com.theoplayer.android.api.cast.CastStrategy
10
11
  import com.theoplayer.android.api.cast.CastConfiguration
11
12
  import com.theoplayer.android.api.pip.PipConfiguration
12
13
  import com.theoplayer.android.api.player.NetworkConfiguration
13
14
  import com.theoplayer.android.api.ui.UIConfiguration
15
+ import com.theoplayer.media.MediaSessionConfig
16
+ import com.theoplayer.media.MediaSessionConfigAdapter
14
17
 
15
18
  private const val PROP_LICENSE = "license"
16
19
  private const val PROP_LICENSE_URL = "licenseUrl"
@@ -26,7 +29,15 @@ private const val PROP_RETRY_MIN_BACKOFF = "minimumBackoff"
26
29
  private const val PROP_RETRY_MAX_BACKOFF = "maximumBackoff"
27
30
  private const val PROP_CAST_CONFIGURATION = "cast"
28
31
  private const val PROP_ADS_CONFIGURATION = "ads"
32
+ private const val PROP_IMA_CONFIGURATION = "ima"
29
33
  private const val PROP_UI_CONFIGURATION = "ui"
34
+ private const val PROP_MEDIA_CONTROL = "mediaControl"
35
+ private const val PROP_PPID = "ppid"
36
+ private const val PROP_MAX_REDIRECTS = "maxRedirects"
37
+ private const val PROP_FEATURE_FLAGS = "featureFlags"
38
+ private const val PROP_AUTOPLAY_AD_BREAKS = "autoPlayAdBreaks"
39
+ private const val PROP_SESSION_ID = "sessionID"
40
+ private const val PROP_ENABLE_DEBUG_MODE = "enableDebugMode"
30
41
 
31
42
  class PlayerConfigAdapter(private val configProps: ReadableMap?) {
32
43
 
@@ -91,8 +102,44 @@ class PlayerConfigAdapter(private val configProps: ReadableMap?) {
91
102
  */
92
103
  fun imaSdkSettings(): ImaSdkSettings{
93
104
  return ImaSdkFactory.getInstance().createImaSdkSettings().apply {
94
- configProps?.getMap(PROP_ADS_CONFIGURATION)?.run {
95
- // TODO: bridge all settings
105
+ configProps?.getMap(PROP_ADS_CONFIGURATION)?.getMap(PROP_IMA_CONFIGURATION)?.run {
106
+ // Specifies whether VMAP and ad rules ad breaks are automatically played.
107
+ if (hasKey(PROP_AUTOPLAY_AD_BREAKS)) {
108
+ autoPlayAdBreaks = getBoolean(PROP_AUTOPLAY_AD_BREAKS)
109
+ }
110
+ // Feature flags and their states. Used to control experimental features.
111
+ if (hasKey(PROP_FEATURE_FLAGS)) {
112
+ val convertedMap: MutableMap<String, String> = mutableMapOf()
113
+ getMap(PROP_FEATURE_FLAGS)?.toHashMap()?.forEach { (key, value) ->
114
+ convertedMap[key] = value as String
115
+ }
116
+ featureFlags = convertedMap
117
+ }
118
+ // The current ISO 639-1 language code, get it from the UI config.
119
+ uiConfig().language?.let {
120
+ language = it
121
+ }
122
+ // The maximum number of VAST redirects.
123
+ if (hasKey(PROP_MAX_REDIRECTS)) {
124
+ maxRedirects = getInt(PROP_MAX_REDIRECTS)
125
+ }
126
+ // The partner provided player type.
127
+ playerType = "THEOplayer"
128
+ // The partner provided player version.
129
+ playerVersion = THEOplayerGlobal.getVersion()
130
+ // The Publisher Provided Identification (PPID) sent with ads request.
131
+ if (hasKey(PROP_PPID)) {
132
+ ppid = getString(PROP_PPID) ?: ""
133
+ }
134
+ // The session ID to identify a single user session. This should be a UUID. It
135
+ // is used exclusively for frequency capping across the user session.
136
+ if (hasKey(PROP_SESSION_ID)) {
137
+ sessionId = getString(PROP_PPID) ?: ""
138
+ }
139
+ // Toggles debug mode which will output detailed log information to the console.
140
+ if (hasKey(PROP_ENABLE_DEBUG_MODE)) {
141
+ isDebugMode = getBoolean(PROP_ENABLE_DEBUG_MODE)
142
+ }
96
143
  }
97
144
  }
98
145
  }
@@ -154,4 +201,14 @@ class PlayerConfigAdapter(private val configProps: ReadableMap?) {
154
201
  else -> null
155
202
  }
156
203
  }
204
+
205
+ /**
206
+ * Get MediaSession connector configuration; these properties apply:
207
+ * - mediaSessionEnabled: whether or not the media session should be enabled.
208
+ * - skipForwardInterval: the amount of seconds the player will skip forward.
209
+ * - skipBackwardInterval: the amount of seconds the player will skip backward.
210
+ */
211
+ fun mediaSessionConfig(): MediaSessionConfig {
212
+ return MediaSessionConfigAdapter.fromProps(configProps?.getMap(PROP_MEDIA_CONTROL))
213
+ }
157
214
  }
@@ -28,6 +28,7 @@ import com.theoplayer.audio.AudioBecomingNoisyManager
28
28
  import com.theoplayer.audio.AudioFocusManager
29
29
  import com.theoplayer.audio.BackgroundAudioConfig
30
30
  import com.theoplayer.media.MediaPlaybackService
31
+ import com.theoplayer.media.MediaSessionConfig
31
32
  import java.util.concurrent.atomic.AtomicBoolean
32
33
 
33
34
  private const val TAG = "ReactTHEOplayerContext"
@@ -42,7 +43,8 @@ private const val ALLOWED_PLAYBACK_ACTIONS = (
42
43
  PlaybackStateCompat.ACTION_SET_PLAYBACK_SPEED)
43
44
 
44
45
  class ReactTHEOplayerContext private constructor(
45
- private val reactContext: ThemedReactContext
46
+ private val reactContext: ThemedReactContext,
47
+ private val configAdapter: PlayerConfigAdapter
46
48
  ) {
47
49
  private val mainHandler = Handler(Looper.getMainLooper())
48
50
  private var isBound = AtomicBoolean()
@@ -60,6 +62,12 @@ class ReactTHEOplayerContext private constructor(
60
62
  field = value
61
63
  }
62
64
 
65
+ var mediaSessionConfig: MediaSessionConfig = configAdapter.mediaSessionConfig()
66
+ set(value) {
67
+ applyMediaSessionConfig(mediaSessionConnector, value)
68
+ field = value
69
+ }
70
+
63
71
  lateinit var playerView: THEOplayerView
64
72
 
65
73
  val player: Player
@@ -85,8 +93,8 @@ class ReactTHEOplayerContext private constructor(
85
93
  reactContext: ThemedReactContext,
86
94
  configAdapter: PlayerConfigAdapter
87
95
  ): ReactTHEOplayerContext {
88
- return ReactTHEOplayerContext(reactContext).apply {
89
- initializePlayerView(configAdapter)
96
+ return ReactTHEOplayerContext(reactContext, configAdapter).apply {
97
+ initializePlayerView()
90
98
  }
91
99
  }
92
100
  }
@@ -96,9 +104,9 @@ class ReactTHEOplayerContext private constructor(
96
104
  binder = service as MediaPlaybackService.MediaPlaybackBinder
97
105
 
98
106
  // Get media session connector from service
99
- mediaSessionConnector = binder?.mediaSessionConnector
100
- mediaSessionConnector?.player = player
101
- mediaSessionConnector?.setMediaSessionMetadata(player.source)
107
+ mediaSessionConnector = binder?.mediaSessionConnector?.also {
108
+ applyMediaSessionConfig(it, mediaSessionConfig)
109
+ }
102
110
 
103
111
  // Pass player context
104
112
  binder?.setPlayerContext(this@ReactTHEOplayerContext)
@@ -184,7 +192,7 @@ class ReactTHEOplayerContext private constructor(
184
192
  binder = null
185
193
  }
186
194
 
187
- private fun initializePlayerView(configAdapter: PlayerConfigAdapter) {
195
+ private fun initializePlayerView() {
188
196
  playerView = object : THEOplayerView(reactContext.currentActivity!!, configAdapter.playerConfig()) {
189
197
  private fun measureAndLayout() {
190
198
  measure(
@@ -205,7 +213,7 @@ class ReactTHEOplayerContext private constructor(
205
213
  // By default, the screen should remain on.
206
214
  playerView.keepScreenOn = true
207
215
 
208
- addIntegrations(configAdapter)
216
+ addIntegrations()
209
217
  addListeners()
210
218
 
211
219
  audioFocusManager = AudioFocusManager(reactContext, player)
@@ -229,17 +237,30 @@ class ReactTHEOplayerContext private constructor(
229
237
  mediaSession.setMediaButtonReceiver(null)
230
238
 
231
239
  // Create a MediaSessionConnector and attach the THEOplayer instance.
232
- mediaSessionConnector = MediaSessionConnector(mediaSession).apply {
240
+ mediaSessionConnector = MediaSessionConnector(mediaSession).also {
241
+ applyMediaSessionConfig(it, mediaSessionConfig)
242
+ }
243
+ }
244
+
245
+ private fun applyMediaSessionConfig(connector: MediaSessionConnector?, config: MediaSessionConfig) {
246
+ connector?.apply {
233
247
  debug = BuildConfig.LOG_MEDIASESSION_EVENTS
248
+
234
249
  player = this@ReactTHEOplayerContext.player
235
250
 
236
251
  // Set mediaSession active and ready to receive media button events, but not if the player
237
252
  // is backgrounded.
238
- setActive(!isHostPaused)
253
+ setActive(!isHostPaused && BuildConfig.EXTENSION_MEDIASESSION && config.mediaSessionEnabled)
254
+
255
+ skipForwardInterval = config.skipForwardInterval
256
+ skipBackwardsInterval = config.skipBackwardInterval
257
+
258
+ // Pass metadata from source description
259
+ setMediaSessionMetadata(player?.source)
239
260
  }
240
261
  }
241
262
 
242
- private fun addIntegrations(configAdapter: PlayerConfigAdapter) {
263
+ private fun addIntegrations() {
243
264
  try {
244
265
  if (BuildConfig.EXTENSION_GOOGLE_IMA) {
245
266
  imaIntegration = GoogleImaIntegrationFactory.createGoogleImaIntegration(
@@ -357,7 +378,7 @@ class ReactTHEOplayerContext private constructor(
357
378
  */
358
379
  fun onHostResume() {
359
380
  isHostPaused = false
360
- mediaSessionConnector?.setActive(true)
381
+ mediaSessionConnector?.setActive(BuildConfig.EXTENSION_MEDIASESSION)
361
382
  playerView.onResume()
362
383
  if (!player.isPaused) {
363
384
  audioFocusManager?.retrieveAudioFocus()
@@ -173,7 +173,7 @@ class MediaPlaybackService : MediaBrowserServiceCompat() {
173
173
  debug = BuildConfig.LOG_MEDIASESSION_EVENTS
174
174
 
175
175
  // Set mediaSession active
176
- setActive(true)
176
+ setActive(BuildConfig.EXTENSION_MEDIASESSION)
177
177
  }
178
178
 
179
179
  // Set the MediaBrowserServiceCompat's media session.
@@ -0,0 +1,18 @@
1
+ package com.theoplayer.media
2
+
3
+ data class MediaSessionConfig (
4
+ /**
5
+ * Whether or not the media session should be enabled.
6
+ */
7
+ var mediaSessionEnabled: Boolean = true,
8
+
9
+ /**
10
+ * The amount of seconds the player will skip forward.
11
+ */
12
+ var skipForwardInterval: Double = 5.0,
13
+
14
+ /**
15
+ * The amount of seconds the player will skip backward.
16
+ */
17
+ var skipBackwardInterval: Double = 5.0,
18
+ )
@@ -0,0 +1,23 @@
1
+ package com.theoplayer.media
2
+
3
+ import com.facebook.react.bridge.ReadableMap
4
+
5
+ object MediaSessionConfigAdapter {
6
+ private const val PROP_ENABLED = "mediaSessionEnabled"
7
+ private const val PROP_SKIP_FORWARD_INTERVAL = "skipForwardInterval"
8
+ private const val PROP_SKIP_BACKWARD_INTERVAL = "skipBackwardInterval"
9
+
10
+ fun fromProps(props: ReadableMap?): MediaSessionConfig {
11
+ return MediaSessionConfig().apply {
12
+ if (props?.hasKey(PROP_ENABLED) == true) {
13
+ mediaSessionEnabled = props.getBoolean(PROP_ENABLED)
14
+ }
15
+ if (props?.hasKey(PROP_SKIP_FORWARD_INTERVAL) == true) {
16
+ skipForwardInterval = props.getDouble(PROP_SKIP_FORWARD_INTERVAL)
17
+ }
18
+ if (props?.hasKey(PROP_SKIP_BACKWARD_INTERVAL) == true) {
19
+ skipBackwardInterval = props.getDouble(PROP_SKIP_BACKWARD_INTERVAL)
20
+ }
21
+ }
22
+ }
23
+ }
@@ -352,17 +352,7 @@ class THEOplayerRCTSourceDescriptionBuilder {
352
352
  static func buildContentProtection(_ contentProtectionData: [String:Any]) -> MultiplatformDRMConfiguration? {
353
353
  do {
354
354
  let data = try JSONSerialization.data(withJSONObject: contentProtectionData)
355
- if let integration = contentProtectionData[SD_PROP_INTEGRATION] as? String {
356
- switch integration {
357
- case DRM_INTEGRATION_ID_EZDRM: return try JSONDecoder().decode(EzdrmDRMConfiguration.self, from: data)
358
- case DRM_INTEGRATION_ID_KEYOS: return try JSONDecoder().decode(KeyOSDRMConfiguration.self, from: data)
359
- case DRM_INTEGRATION_ID_VERIMATRIX: return try JSONDecoder().decode(VerimatrixDRMConfiguration.self, from: data)
360
- default: return try JSONDecoder().decode(MultiplatformDRMConfiguration.self, from: data)
361
- }
362
- } else {
363
- PrintUtils.printLog(logText: "[NATIVE] integration type not specified... trying default drm integration")
364
- return try JSONDecoder().decode(MultiplatformDRMConfiguration.self, from: data)
365
- }
355
+ return try JSONDecoder().decode(MultiplatformDRMConfiguration.self, from: data)
366
356
  } catch {
367
357
  PrintUtils.printLog(logText: "[NATIVE] unsupported contentProtection data format")
368
358
  }
@@ -26,6 +26,7 @@ let PROP_CUES: String = "cues"
26
26
  let PROP_CUE_CONTENT: String = "content"
27
27
  let PROP_CUE_CUSTOM_ATTRIBUTES: String = "customAttributes"
28
28
  let PROP_SRC: String = "src"
29
+ let PROP_FORCED: String = "forced"
29
30
  let PROP_START_DATE: String = "startDate"
30
31
  let PROP_END_DATE: String = "endDate"
31
32
  let PROP_ATTRIBUTE_CLASS: String = "class"
@@ -73,6 +74,7 @@ class THEOplayerRCTTrackMetadataAggregator {
73
74
  entry[PROP_LABEL] = textTrack.label
74
75
  entry[PROP_TYPE] = textTrack.type
75
76
  entry[PROP_SRC] = textTrack.src
77
+ entry[PROP_FORCED] = textTrack.forced
76
78
  // process cues when texttrack contains them
77
79
  if !textTrack.cues.isEmpty {
78
80
  var cueList: [[String:Any]] = []
@@ -11,7 +11,7 @@ let ERROR_MESSAGE_DAI_GET_SNAPBACK_UNDEFINED = "Undefined dai snapback"
11
11
 
12
12
  extension THEOplayerRCTAdsAPI {
13
13
 
14
- #if GOOGLE_DAI || canImport(THEOplayerGoogleIMAIntegration)
14
+ #if canImport(THEOplayerGoogleIMAIntegration)
15
15
  @objc(daiSnapback:resolver:rejecter:)
16
16
  func daiSnapback(_ node: NSNumber, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
17
17
  DispatchQueue.main.async {
@@ -34,7 +34,7 @@ class THEOplayerRCTAdsAPI: NSObject, RCTBridgeModule {
34
34
  return false
35
35
  }
36
36
 
37
- #if (GOOGLE_IMA || GOOGLE_DAI) || canImport(THEOplayerGoogleIMAIntegration)
37
+ #if canImport(THEOplayerGoogleIMAIntegration)
38
38
  @objc(skip:)
39
39
  func skip(_ node: NSNumber) -> Void {
40
40
 
@@ -54,7 +54,7 @@ class THEOplayerRCTAdsEventHandler {
54
54
  return
55
55
  }
56
56
 
57
- #if (GOOGLE_IMA || GOOGLE_DAI) || canImport(THEOplayerGoogleIMAIntegration)
57
+ #if canImport(THEOplayerGoogleIMAIntegration)
58
58
  // AD_BEGIN
59
59
  self.adBeginListener = player.ads.addEventListener(type: AdsEventTypes.AD_BEGIN) { [weak self] event in
60
60
  if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_BEGIN event from THEOplayer Ads") }
@@ -180,7 +180,7 @@ class THEOplayerRCTAdsEventHandler {
180
180
  return
181
181
  }
182
182
 
183
- #if (GOOGLE_IMA || GOOGLE_DAI) || canImport(THEOplayerGoogleIMAIntegration)
183
+ #if canImport(THEOplayerGoogleIMAIntegration)
184
184
  // AD_BEGIN
185
185
  if let adBeginListener = self.adBeginListener {
186
186
  player.ads.removeEventListener(type: AdsEventTypes.AD_BEGIN, listener: adBeginListener)
@@ -15,7 +15,7 @@ extension THEOplayerRCTSourceDescriptionBuilder {
15
15
  static func buildAdDescriptions(_ sourceData: NSDictionary) -> [AdDescription]? {
16
16
  var adsDescriptions: [AdDescription]?
17
17
 
18
- #if GOOGLE_IMA || canImport(THEOplayerGoogleIMAIntegration)
18
+ #if canImport(THEOplayerGoogleIMAIntegration)
19
19
  if let ads = sourceData[SD_PROP_ADS] {
20
20
  adsDescriptions = []
21
21
  // case: array of ads objects
@@ -53,7 +53,7 @@ extension THEOplayerRCTSourceDescriptionBuilder {
53
53
  - returns: a THEOplayer GoogleImaAdDescription
54
54
  */
55
55
  static func buildSingleAdDescription(_ adsData: [String:Any]) -> AdDescription? {
56
- #if GOOGLE_IMA || canImport(THEOplayerGoogleIMAIntegration)
56
+ #if canImport(THEOplayerGoogleIMAIntegration)
57
57
  if let integration = adsData[SD_PROP_INTEGRATION] as? String,
58
58
  integration == AdIntegration.google_ima._rawValue {
59
59
  // timeOffset can be Int or String: 10, "01:32:54.78", "1234.56", "start", "end", "10%", ...
@@ -77,7 +77,7 @@ extension THEOplayerRCTSourceDescriptionBuilder {
77
77
  }
78
78
 
79
79
  static func buildDAITypedSource(_ typedSourceData: [String:Any], contentProtection: MultiplatformDRMConfiguration?) -> TypedSource? {
80
- #if GOOGLE_DAI || canImport(THEOplayerGoogleIMAIntegration)
80
+ #if canImport(THEOplayerGoogleIMAIntegration)
81
81
  // check for alternative Google DAI SSAI
82
82
  if let ssaiData = typedSourceData[SD_PROP_SSAI] as? [String:Any] {
83
83
  if let integration = ssaiData[SD_PROP_INTEGRATION] as? String,
@@ -5,6 +5,7 @@ import THEOplayerSDK
5
5
 
6
6
  #if canImport(THEOplayerGoogleIMAIntegration)
7
7
  import THEOplayerGoogleIMAIntegration
8
+ import GoogleInteractiveMediaAds
8
9
  #endif
9
10
 
10
11
  extension THEOplayerRCTView {
@@ -21,7 +22,40 @@ extension THEOplayerRCTView {
21
22
  return
22
23
  }
23
24
  #if canImport(THEOplayerGoogleIMAIntegration)
24
- let imaIntegration = GoogleIMAIntegrationFactory.createIntegration(on: player)
25
+ // prepare imaSettings
26
+ let imaSettings = IMASettings()
27
+ imaSettings.language = self.uiConfig.language
28
+ imaSettings.maxRedirects = self.adsConfig.adsImaConfig.maxRedirects
29
+ imaSettings.enableDebugMode = self.adsConfig.adsImaConfig.enableDebugMode
30
+ imaSettings.playerType = "THEOplayer"
31
+ imaSettings.playerVersion = THEOplayer.version
32
+ imaSettings.enableBackgroundPlayback = true
33
+ if let ppid = self.adsConfig.adsImaConfig.ppid {
34
+ imaSettings.ppid = ppid
35
+ }
36
+ #if os(iOS)
37
+ if let featureFlags = self.adsConfig.adsImaConfig.featureFlags {
38
+ imaSettings.featureFlags = featureFlags
39
+ }
40
+ #endif
41
+ if let autoPlayAdBreaks = self.adsConfig.adsImaConfig.autoPlayAdBreaks {
42
+ imaSettings.autoPlayAdBreaks = autoPlayAdBreaks
43
+ }
44
+ if let sessionID = self.adsConfig.adsImaConfig.sessionID {
45
+ imaSettings.sessionID = sessionID
46
+ }
47
+
48
+ // setup ima render settings
49
+ let imaRenderSettings = IMAAdsRenderingSettings()
50
+ let disableUi = !self.adsConfig.adSUIEnabled
51
+ if disableUi {
52
+ imaRenderSettings.disableUi = disableUi
53
+ imaRenderSettings.uiElements = []
54
+ }
55
+
56
+ // setup integration
57
+ let imaIntegration = GoogleIMAIntegrationFactory.createIntegration(on: player, with: imaSettings)
58
+ imaIntegration.renderingSettings = imaRenderSettings
25
59
  player.addIntegration(imaIntegration)
26
60
  #endif
27
61
  }
@@ -6,6 +6,16 @@ import THEOplayerSDK
6
6
  struct AdsConfig {
7
7
  var adSUIEnabled: Bool = true
8
8
  var adPreloadTypeString: String = "none"
9
+ var adsImaConfig = AdsImaConfig()
10
+ }
11
+
12
+ struct AdsImaConfig {
13
+ var maxRedirects: UInt = 4
14
+ var enableDebugMode: Bool = false
15
+ var ppid: String?
16
+ var featureFlags: [String:String]?
17
+ var autoPlayAdBreaks: Bool?
18
+ var sessionID: String?
9
19
  }
10
20
 
11
21
  #if os(iOS)
@@ -18,23 +28,32 @@ extension THEOplayerRCTView {
18
28
  if let adPreloadType = adsConfig["preload"] as? String {
19
29
  self.adsConfig.adPreloadTypeString = adPreloadType
20
30
  }
31
+ if let adsImaConfig = adsConfig["ima"] as? NSDictionary {
32
+ if let ppid = adsImaConfig["ppid"] as? String {
33
+ self.adsConfig.adsImaConfig.ppid = ppid
34
+ }
35
+ if let maxRedirects = adsImaConfig["maxRedirects"] as? UInt {
36
+ self.adsConfig.adsImaConfig.maxRedirects = maxRedirects
37
+ }
38
+ if let featureFlags = adsImaConfig["featureFlags"] as? [String:String] {
39
+ self.adsConfig.adsImaConfig.featureFlags = featureFlags
40
+ }
41
+ if let autoPlayAdBreaks = adsImaConfig["autoPlayAdBreaks"] as? Bool {
42
+ self.adsConfig.adsImaConfig.autoPlayAdBreaks = autoPlayAdBreaks
43
+ }
44
+ if let sessionID = adsImaConfig["sessionID"] as? String {
45
+ self.adsConfig.adsImaConfig.sessionID = sessionID
46
+ }
47
+ if let enableDebugMode = adsImaConfig["enableDebugMode"] as? Bool {
48
+ self.adsConfig.adsImaConfig.enableDebugMode = enableDebugMode
49
+ }
50
+ }
21
51
  }
22
52
  }
23
53
 
24
- #if (GOOGLE_IMA || GOOGLE_DAI) || canImport(THEOplayerGoogleIMAIntegration)
54
+ #if canImport(THEOplayerGoogleIMAIntegration)
25
55
  func playerAdsConfiguration() -> AdsConfiguration? {
26
- let googleBuilder = GoogleIMAConfigurationBuilder()
27
- googleBuilder.disableUI = !self.adsConfig.adSUIEnabled
28
- googleBuilder.enableBackgroundPlayback = true
29
- let googleIMAAdsConfiguration = googleBuilder.build()
30
- let daiBuilder = GoogleDAIAdsConfigurationBuilder()
31
- daiBuilder.disableUI = !self.adsConfig.adSUIEnabled
32
- daiBuilder.enableBackgroundPlayback = true
33
- let googleDaiAdsConfiguration = daiBuilder.build()
34
- return AdsConfiguration(showCountdown: self.adsConfig.adSUIEnabled,
35
- preload: self.adPreloadType(),
36
- googleIma: googleIMAAdsConfiguration,
37
- googleDai: googleDaiAdsConfiguration)
56
+ return AdsConfiguration(showCountdown: self.adsConfig.adSUIEnabled, preload: self.adPreloadType())
38
57
  }
39
58
 
40
59
  private func adPreloadType() -> THEOplayerSDK.AdPreloadType {
@@ -59,7 +78,7 @@ extension THEOplayerRCTView {
59
78
 
60
79
  func parseAdsConfig(configDict: NSDictionary) {}
61
80
 
62
- #if (GOOGLE_IMA || GOOGLE_DAI) || canImport(THEOplayerGoogleIMAIntegration)
81
+ #if canImport(THEOplayerGoogleIMAIntegration)
63
82
  func playerAdsConfiguration() -> AdsConfiguration? { return AdsConfiguration() }
64
83
  #else
65
84
  func playerAdsConfiguration() -> AdsConfiguration? { return nil }
@@ -193,7 +193,7 @@ class THEOplayerRCTRemoteCommandsManager: NSObject {
193
193
  self?.updateRemoteCommands()
194
194
  }
195
195
 
196
- #if (GOOGLE_IMA || GOOGLE_DAI) || canImport(THEOplayerGoogleIMAIntegration)
196
+ #if canImport(THEOplayerGoogleIMAIntegration)
197
197
 
198
198
  // ADBREAK_BEGIN
199
199
  self.adBreakBeginListener = player.ads.addEventListener(type: AdsEventTypes.AD_BREAK_BEGIN) { [weak self] event in
@@ -226,7 +226,7 @@ class THEOplayerRCTRemoteCommandsManager: NSObject {
226
226
  player.removeEventListener(type: PlayerEventTypes.SOURCE_CHANGE, listener: sourceChangeListener)
227
227
  }
228
228
 
229
- #if (GOOGLE_IMA || GOOGLE_DAI) || canImport(THEOplayerGoogleIMAIntegration)
229
+ #if canImport(THEOplayerGoogleIMAIntegration)
230
230
 
231
231
  // ADBREAK_BEGIN
232
232
  if let adBreakBeginListener = self.adBreakBeginListener {
@@ -7,16 +7,6 @@ struct BackgroundAudioConfig {
7
7
  var enabled: Bool = false
8
8
  }
9
9
 
10
- #if WEB
11
-
12
- extension THEOplayerRCTView {
13
- func initBackgroundAudio() {}
14
- func destroyBackgroundAudio() {}
15
- public func shouldContinueAudioPlaybackInBackground() -> Bool { return false }
16
- }
17
-
18
- #else
19
-
20
10
  extension THEOplayerRCTView: BackgroundPlaybackDelegate {
21
11
 
22
12
  func initBackgroundAudio() {
@@ -41,5 +31,3 @@ extension THEOplayerRCTView: BackgroundPlaybackDelegate {
41
31
  struct DefaultBackgroundPlaybackDelegate: BackgroundPlaybackDelegate {
42
32
  func shouldContinueAudioPlaybackInBackground() -> Bool { false }
43
33
  }
44
-
45
- #endif
@@ -43,7 +43,7 @@ class THEOplayerRCTPipControlsManager: NSObject {
43
43
  if let player = self.player,
44
44
  let duration = player.duration {
45
45
  self.isLive = duration.isInfinite
46
- #if (GOOGLE_IMA || GOOGLE_DAI) || canImport(THEOplayerGoogleIMAIntegration)
46
+ #if canImport(THEOplayerGoogleIMAIntegration)
47
47
  self.inAd = player.ads.playing
48
48
  self.updatePipControls()
49
49
  #else
@@ -91,7 +91,7 @@ class THEOplayerRCTPipControlsManager: NSObject {
91
91
  self?.updatePipControls()
92
92
  }
93
93
 
94
- #if (GOOGLE_IMA || GOOGLE_DAI) || canImport(THEOplayerGoogleIMAIntegration)
94
+ #if canImport(THEOplayerGoogleIMAIntegration)
95
95
 
96
96
  // ADBREAK_BEGIN
97
97
  self.adBreakBeginListener = player.ads.addEventListener(type: AdsEventTypes.AD_BREAK_BEGIN) { [weak self] event in
@@ -122,7 +122,7 @@ class THEOplayerRCTPipControlsManager: NSObject {
122
122
  player.removeEventListener(type: PlayerEventTypes.SOURCE_CHANGE, listener: sourceChangeListener)
123
123
  }
124
124
 
125
- #if (GOOGLE_IMA || GOOGLE_DAI) || canImport(THEOplayerGoogleIMAIntegration)
125
+ #if canImport(THEOplayerGoogleIMAIntegration)
126
126
 
127
127
  // ADBREAK_BEGIN
128
128
  if let adBreakBeginListener = self.adBreakBeginListener {
@@ -21,16 +21,26 @@ function THEOplayerView(props) {
21
21
  // Create player inside container.
22
22
  if (container.current) {
23
23
  const chromeless = config?.chromeless === true || config?.chromeless === undefined;
24
+ const ads = {
25
+ ...config?.ads,
26
+ googleIma: {
27
+ useNativeIma: true,
28
+ language: config?.ui?.language ?? 'en'
29
+ }
30
+ };
24
31
  const updatedConfig = {
25
32
  ...config,
26
- allowNativeFullscreen: true
33
+ allowNativeFullscreen: true,
34
+ ads
27
35
  };
28
36
  if (chromeless) {
29
37
  player.current = new _theoplayer.ChromelessPlayer(container.current, updatedConfig);
30
38
  } else {
31
39
  player.current = new _theoplayer.Player(container.current, {
32
40
  ...updatedConfig,
41
+ ads,
33
42
  ui: {
43
+ ...config?.ui,
34
44
  fluid: true
35
45
  }
36
46
  });
@@ -1 +1 @@
1
- {"version":3,"names":["_react","_interopRequireWildcard","require","_theoplayer","_THEOplayerWebAdapter","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","THEOplayerView","props","config","children","player","useRef","adapter","container","useEffect","current","chromeless","undefined","updatedConfig","allowNativeFullscreen","ChromelessPlayer","Player","ui","fluid","THEOplayerWebAdapter","window","nativePlayer","onPlayerReady","onPlayerDestroy","destroy","createElement","Fragment","ref","style","styles","className","display","position","width","height","maxHeight","maxWidth","aspectRatio"],"sourceRoot":"../../../src","sources":["internal/THEOplayerView.web.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","_interopRequireWildcard","require","_theoplayer","_THEOplayerWebAdapter","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","THEOplayerView","props","config","children","player","useRef","adapter","container","useEffect","current","chromeless","undefined","ads","googleIma","useNativeIma","language","ui","updatedConfig","allowNativeFullscreen","ChromelessPlayer","Player","fluid","THEOplayerWebAdapter","window","nativePlayer","onPlayerReady","onPlayerDestroy","destroy","createElement","Fragment","ref","style","styles","className","display","position","width","height","maxHeight","maxWidth","aspectRatio"],"sourceRoot":"../../../src","sources":["internal/THEOplayerView.web.tsx"],"mappings":"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","ignoreList":[]}