react-native-theoplayer 8.4.0 → 8.6.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.
- package/CHANGELOG.md +28 -0
- package/android/build.gradle +15 -4
- package/android/src/main/java/com/theoplayer/ReactTHEOplayerContext.kt +14 -0
- package/android/src/main/java/com/theoplayer/ads/AdEventAdapter.kt +2 -2
- package/android/src/main/java/com/theoplayer/presentation/PresentationManager.kt +22 -8
- package/android/src/main/java/com/theoplayer/presentation/PresentationModeChangeContext.kt +4 -1
- package/android/src/main/java/com/theoplayer/source/SourceAdapter.kt +48 -0
- package/android/src/main/java/com/theoplayer/util/PayloadBuilder.kt +1 -0
- package/ios/ads/THEOplayerRCTAdsEventHandler.swift +77 -36
- package/ios/presentationMode/THEOplayerRCTPresentationModeManager.swift +46 -25
- package/ios/presentationMode/THEOplayerRCTView+PresentationMode.swift +1 -1
- package/lib/commonjs/api/event/PlayerEvent.js +1 -0
- package/lib/commonjs/api/event/PlayerEvent.js.map +1 -1
- package/lib/commonjs/api/source/SourceDescription.js.map +1 -1
- package/lib/commonjs/api/version/SdkVersions.js +2 -0
- package/lib/commonjs/api/version/SdkVersions.js.map +1 -0
- package/lib/commonjs/internal/adapter/THEOplayerWebAdapter.js +5 -1
- package/lib/commonjs/internal/adapter/THEOplayerWebAdapter.js.map +1 -1
- package/lib/module/api/event/PlayerEvent.js +1 -0
- package/lib/module/api/event/PlayerEvent.js.map +1 -1
- package/lib/module/api/source/SourceDescription.js.map +1 -1
- package/lib/module/api/version/SdkVersions.js +2 -0
- package/lib/module/api/version/SdkVersions.js.map +1 -0
- package/lib/module/internal/adapter/THEOplayerWebAdapter.js +5 -1
- package/lib/module/internal/adapter/THEOplayerWebAdapter.js.map +1 -1
- package/lib/typescript/api/ads/AdsConfiguration.d.ts +13 -0
- package/lib/typescript/api/ads/AdsConfiguration.d.ts.map +1 -1
- package/lib/typescript/api/event/AdEvent.d.ts +2 -2
- package/lib/typescript/api/event/PlayerEvent.d.ts +8 -1
- package/lib/typescript/api/event/PlayerEvent.d.ts.map +1 -1
- package/lib/typescript/api/source/SourceDescription.d.ts +6 -0
- package/lib/typescript/api/source/SourceDescription.d.ts.map +1 -1
- package/lib/typescript/api/version/SdkVersions.d.ts +15 -0
- package/lib/typescript/api/version/SdkVersions.d.ts.map +1 -0
- package/lib/typescript/internal/adapter/THEOplayerWebAdapter.d.ts.map +1 -1
- package/package.json +15 -15
- package/react-native-theoplayer.podspec +6 -6
- package/src/api/ads/AdsConfiguration.ts +14 -0
- package/src/api/event/AdEvent.ts +2 -2
- package/src/api/event/PlayerEvent.ts +8 -0
- package/src/api/source/SourceDescription.ts +7 -0
- package/src/api/version/SdkVersions.ts +15 -0
- package/src/internal/adapter/THEOplayerWebAdapter.ts +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,11 +5,39 @@ 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
|
+
## [8.6.0] - 24-10-25
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Added `AdEvent.AD_CLICKED` and `AdEvent.AD_TAPPED` ad events for iOS and Android. The events are dispatched when a user taps or clicks on an ad that has a `clickThrough` link.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Upgrade example app to support React Native v0.75.
|
|
17
|
+
|
|
18
|
+
## [8.5.0] - 24-10-21
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- Added `SdkVersion` interface to be used by the sdk and its connectors to report version info.
|
|
23
|
+
- Added the `THEOads` SGAI ad integration for Android. See [THEOads](https://www.theoplayer.com/product/theoads) for more details.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- Fixed an issue on Web where all text tracks other than the selected would be set to `disabled` when enabling a text track.
|
|
28
|
+
- Fixed an issue on iOS where the player would crash when changing the presentationMode from fullscreen to picture-in-picture during ad playout.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- On iOS, after closing picture-in-picture the player returns back to the previous presentationMode instead of always returning to inline.
|
|
33
|
+
|
|
8
34
|
## [8.4.0] - 24-10-10
|
|
9
35
|
|
|
10
36
|
### Added
|
|
11
37
|
|
|
12
38
|
- Added a `posterStyle` property on `THEOplayerView` to allow overriding the default 16:9 poster style.
|
|
39
|
+
- Added a `theoads` property on `PlayerConfiguration.ads` to allow play-out of THEOads sources on Web platforms.
|
|
40
|
+
- Added a `hlsDateRange` property on `SourceDescription` to enable parsing and exposing date ranges from HLS playlists. This flag was already available on `PlayerConfiguration`, which applies for all HLS sources.
|
|
13
41
|
|
|
14
42
|
### Fixed
|
|
15
43
|
|
package/android/build.gradle
CHANGED
|
@@ -28,7 +28,8 @@ static def versionString(version) {
|
|
|
28
28
|
// Extensions
|
|
29
29
|
def enabledGoogleIMA = safeExtGet("THEOplayer_extensionGoogleIMA", 'false').toBoolean()
|
|
30
30
|
def enabledGoogleDAI = safeExtGet("THEOplayer_extensionGoogleDAI", 'false').toBoolean()
|
|
31
|
-
def
|
|
31
|
+
def enabledTHEOads = safeExtGet("THEOplayer_extensionTHEOads", 'false').toBoolean()
|
|
32
|
+
def enabledAds = enabledGoogleIMA || enabledGoogleDAI || enabledTHEOads
|
|
32
33
|
def enabledCast = safeExtGet("THEOplayer_extensionCast", 'false').toBoolean()
|
|
33
34
|
def enabledMediaSession = safeExtGet("THEOplayer_extensionMediaSession", 'true').toBoolean()
|
|
34
35
|
|
|
@@ -61,6 +62,7 @@ android {
|
|
|
61
62
|
// Extension buildConfig fields
|
|
62
63
|
buildConfigField "boolean", "EXTENSION_GOOGLE_IMA", "${enabledGoogleIMA}"
|
|
63
64
|
buildConfigField "boolean", "EXTENSION_GOOGLE_DAI", "${enabledGoogleDAI}"
|
|
65
|
+
buildConfigField "boolean", "EXTENSION_THEOADS", "${enabledTHEOads}"
|
|
64
66
|
buildConfigField "boolean", "EXTENSION_ADS", "${enabledAds}"
|
|
65
67
|
buildConfigField "boolean", "EXTENSION_CAST", "${enabledCast}"
|
|
66
68
|
buildConfigField "boolean", "EXTENSION_MEDIASESSION", "${enabledMediaSession}"
|
|
@@ -106,9 +108,9 @@ repositories {
|
|
|
106
108
|
maven { url "https://maven.theoplayer.com/releases" }
|
|
107
109
|
}
|
|
108
110
|
|
|
109
|
-
// The minimum supported THEOplayer version is 8.
|
|
110
|
-
def theoplayer_sdk_version = safeExtGet('THEOplayer_sdk', '[8.
|
|
111
|
-
def theoplayer_mediasession_version = safeExtGet('THEOplayer_mediasession', '[8.
|
|
111
|
+
// The minimum supported THEOplayer version is 8.3.0
|
|
112
|
+
def theoplayer_sdk_version = safeExtGet('THEOplayer_sdk', '[8.3.0, 9.0.0)')
|
|
113
|
+
def theoplayer_mediasession_version = safeExtGet('THEOplayer_mediasession', '[8.0.0, 9.0.0)')
|
|
112
114
|
|
|
113
115
|
dependencies {
|
|
114
116
|
//noinspection GradleDynamicVersion
|
|
@@ -139,6 +141,14 @@ dependencies {
|
|
|
139
141
|
compileOnly "com.theoplayer.theoplayer-sdk-android:integration-ads-dai:${theoplayer_sdk_version}"
|
|
140
142
|
}
|
|
141
143
|
|
|
144
|
+
if (enabledTHEOads) {
|
|
145
|
+
println('Enable THEOplayer THEOads extension.')
|
|
146
|
+
implementation "com.theoplayer.theoplayer-sdk-android:integration-ads-theoads:${theoplayer_sdk_version}"
|
|
147
|
+
} else {
|
|
148
|
+
println('Disable THEOplayer THEOads extension.')
|
|
149
|
+
compileOnly "com.theoplayer.theoplayer-sdk-android:integration-ads-theoads:${theoplayer_sdk_version}"
|
|
150
|
+
}
|
|
151
|
+
|
|
142
152
|
if (enabledCast) {
|
|
143
153
|
println('Enable THEOplayer cast extension.')
|
|
144
154
|
implementation "com.theoplayer.theoplayer-sdk-android:integration-cast:${theoplayer_sdk_version}"
|
|
@@ -153,6 +163,7 @@ configurations.configureEach {
|
|
|
153
163
|
resolutionStrategy {
|
|
154
164
|
force "com.theoplayer.theoplayer-sdk-android:integration-ads-ima:${theoplayer_sdk_version}"
|
|
155
165
|
force "com.theoplayer.theoplayer-sdk-android:integration-ads-dai:${theoplayer_sdk_version}"
|
|
166
|
+
force "com.theoplayer.theoplayer-sdk-android:integration-ads-theoads:${theoplayer_sdk_version}"
|
|
156
167
|
}
|
|
157
168
|
}
|
|
158
169
|
|
|
@@ -18,6 +18,8 @@ import com.theoplayer.android.api.ads.dai.GoogleDaiIntegration
|
|
|
18
18
|
import com.theoplayer.android.api.ads.dai.GoogleDaiIntegrationFactory
|
|
19
19
|
import com.theoplayer.android.api.ads.ima.GoogleImaIntegration
|
|
20
20
|
import com.theoplayer.android.api.ads.ima.GoogleImaIntegrationFactory
|
|
21
|
+
import com.theoplayer.android.api.ads.theoads.TheoAdsIntegration
|
|
22
|
+
import com.theoplayer.android.api.ads.theoads.TheoAdsIntegrationFactory
|
|
21
23
|
import com.theoplayer.android.api.cast.CastIntegration
|
|
22
24
|
import com.theoplayer.android.api.cast.CastIntegrationFactory
|
|
23
25
|
import com.theoplayer.android.api.event.EventListener
|
|
@@ -80,6 +82,7 @@ class ReactTHEOplayerContext private constructor(
|
|
|
80
82
|
|
|
81
83
|
var daiIntegration: GoogleDaiIntegration? = null
|
|
82
84
|
var imaIntegration: GoogleImaIntegration? = null
|
|
85
|
+
private var theoAdsIntegration: TheoAdsIntegration? = null
|
|
83
86
|
var castIntegration: CastIntegration? = null
|
|
84
87
|
var wasPlayingOnHostPause: Boolean = false
|
|
85
88
|
private var isHostPaused: Boolean = false
|
|
@@ -295,6 +298,17 @@ class ReactTHEOplayerContext private constructor(
|
|
|
295
298
|
} catch (e: Exception) {
|
|
296
299
|
Log.w(TAG, "Failed to configure Google DAI integration ${e.message}")
|
|
297
300
|
}
|
|
301
|
+
try {
|
|
302
|
+
if (BuildConfig.EXTENSION_THEOADS) {
|
|
303
|
+
theoAdsIntegration = TheoAdsIntegrationFactory.createTheoAdsIntegration(
|
|
304
|
+
playerView
|
|
305
|
+
).also {
|
|
306
|
+
playerView.player.addIntegration(it)
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
} catch (e: Exception) {
|
|
310
|
+
Log.w(TAG, "Failed to configure THEOAds integration ${e.message}")
|
|
311
|
+
}
|
|
298
312
|
try {
|
|
299
313
|
if (BuildConfig.EXTENSION_CAST) {
|
|
300
314
|
castIntegration = CastIntegrationFactory.createCastIntegration(
|
|
@@ -115,8 +115,8 @@ class AdEventAdapter(private val adsApi: AdsApiWrapper, eventEmitter: AdEventEmi
|
|
|
115
115
|
GoogleImaAdEventType.AD_BREAK_STARTED, AdsEventTypes.AD_BREAK_BEGIN -> "adbreakbegin"
|
|
116
116
|
GoogleImaAdEventType.AD_BREAK_ENDED, AdsEventTypes.AD_BREAK_END -> "adbreakend"
|
|
117
117
|
GoogleImaAdEventType.AD_BREAK_FETCH_ERROR -> "aderror"
|
|
118
|
-
GoogleImaAdEventType.CLICKED -> "adclicked"
|
|
119
|
-
GoogleImaAdEventType.TAPPED -> "adtapped"
|
|
118
|
+
GoogleImaAdEventType.CLICKED, AdsEventTypes.AD_CLICKED -> "adclicked"
|
|
119
|
+
GoogleImaAdEventType.TAPPED, AdsEventTypes.AD_TAPPED -> "adtapped"
|
|
120
120
|
GoogleImaAdEventType.ICON_TAPPED -> "adicontapped"
|
|
121
121
|
GoogleImaAdEventType.ICON_FALLBACK_IMAGE_CLOSED -> "adiconfallbackimageclosed"
|
|
122
122
|
AdsEventTypes.ADD_AD -> "addad"
|
|
@@ -40,6 +40,8 @@ class PresentationManager(
|
|
|
40
40
|
|
|
41
41
|
var currentPresentationMode: PresentationMode = PresentationMode.INLINE
|
|
42
42
|
private set
|
|
43
|
+
var currentPresentationModeChangeContext: PresentationModeChangeContext? = null
|
|
44
|
+
private set
|
|
43
45
|
|
|
44
46
|
var pipConfig: PipConfig = PipConfig()
|
|
45
47
|
|
|
@@ -54,12 +56,14 @@ class PresentationManager(
|
|
|
54
56
|
}
|
|
55
57
|
onPictureInPictureModeChanged = object : BroadcastReceiver() {
|
|
56
58
|
override fun onReceive(context: Context?, intent: Intent?) {
|
|
57
|
-
|
|
59
|
+
val transitioningToPip = intent
|
|
60
|
+
?.getBooleanExtra("isTransitioningToPip", false) ?: false
|
|
58
61
|
val inPip = intent?.getBooleanExtra("isInPictureInPictureMode", false) ?: false
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
// Dispatch event on every PiP mode change
|
|
63
|
+
when {
|
|
64
|
+
transitioningToPip -> onEnterPip(true)
|
|
65
|
+
inPip -> onEnterPip()
|
|
66
|
+
else -> onExitPip()
|
|
63
67
|
}
|
|
64
68
|
}
|
|
65
69
|
}
|
|
@@ -104,9 +108,11 @@ class PresentationManager(
|
|
|
104
108
|
PresentationMode.INLINE -> {
|
|
105
109
|
setFullscreen(false)
|
|
106
110
|
}
|
|
111
|
+
|
|
107
112
|
PresentationMode.FULLSCREEN -> {
|
|
108
113
|
setFullscreen(true)
|
|
109
114
|
}
|
|
115
|
+
|
|
110
116
|
PresentationMode.PICTURE_IN_PICTURE -> {
|
|
111
117
|
setFullscreen(false)
|
|
112
118
|
enterPip()
|
|
@@ -144,8 +150,13 @@ class PresentationManager(
|
|
|
144
150
|
}
|
|
145
151
|
}
|
|
146
152
|
|
|
147
|
-
private fun onEnterPip() {
|
|
148
|
-
updatePresentationMode(
|
|
153
|
+
private fun onEnterPip(transitioningToPip: Boolean = false) {
|
|
154
|
+
updatePresentationMode(
|
|
155
|
+
PresentationMode.PICTURE_IN_PICTURE,
|
|
156
|
+
if (transitioningToPip)
|
|
157
|
+
PresentationModeChangeContext(PresentationModeChangePipContext.TRANSITIONING_TO_PIP)
|
|
158
|
+
else null
|
|
159
|
+
)
|
|
149
160
|
}
|
|
150
161
|
|
|
151
162
|
private fun onExitPip() {
|
|
@@ -241,11 +252,14 @@ class PresentationManager(
|
|
|
241
252
|
presentationMode: PresentationMode,
|
|
242
253
|
context: PresentationModeChangeContext? = null
|
|
243
254
|
) {
|
|
244
|
-
if (presentationMode == currentPresentationMode
|
|
255
|
+
if (presentationMode == currentPresentationMode &&
|
|
256
|
+
context == currentPresentationModeChangeContext
|
|
257
|
+
) {
|
|
245
258
|
return
|
|
246
259
|
}
|
|
247
260
|
val prevPresentationMode = currentPresentationMode
|
|
248
261
|
currentPresentationMode = presentationMode
|
|
262
|
+
currentPresentationModeChangeContext = context
|
|
249
263
|
eventEmitter.emitPresentationModeChange(presentationMode, prevPresentationMode, context)
|
|
250
264
|
|
|
251
265
|
// Resume playing when going to PiP and player was playing
|
|
@@ -9,7 +9,10 @@ enum class PresentationModeChangePipContext {
|
|
|
9
9
|
CLOSED,
|
|
10
10
|
|
|
11
11
|
// The PiP window transitioned back into the app.
|
|
12
|
-
RESTORED
|
|
12
|
+
RESTORED,
|
|
13
|
+
|
|
14
|
+
// The app transitioning to PiP frame
|
|
15
|
+
TRANSITIONING_TO_PIP
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
data class PresentationModeChangeContext(
|
|
@@ -3,6 +3,7 @@ package com.theoplayer.source
|
|
|
3
3
|
import android.text.TextUtils
|
|
4
4
|
import android.util.Log
|
|
5
5
|
import com.google.gson.Gson
|
|
6
|
+
import com.theoplayer.android.api.ads.theoads.TheoAdDescription
|
|
6
7
|
import com.theoplayer.android.api.error.THEOplayerException
|
|
7
8
|
import com.facebook.react.bridge.ReadableMap
|
|
8
9
|
import com.facebook.react.bridge.WritableMap
|
|
@@ -17,6 +18,7 @@ import com.theoplayer.android.api.source.addescription.GoogleImaAdDescription
|
|
|
17
18
|
import com.theoplayer.android.api.player.track.texttrack.TextTrackKind
|
|
18
19
|
import com.theoplayer.android.api.source.metadata.ChromecastMetadataImage
|
|
19
20
|
import com.theoplayer.BuildConfig
|
|
21
|
+
import com.theoplayer.android.api.ads.theoads.TheoAdsLayoutOverride
|
|
20
22
|
import com.theoplayer.android.api.error.ErrorCode
|
|
21
23
|
import com.theoplayer.android.api.source.AdIntegration
|
|
22
24
|
import com.theoplayer.android.api.source.dash.DashPlaybackConfiguration
|
|
@@ -52,7 +54,16 @@ private const val PROP_ADS = "ads"
|
|
|
52
54
|
private const val PROP_DASH = "dash"
|
|
53
55
|
private const val PROP_DASH_IGNORE_AVAILABILITYWINDOW = "ignoreAvailabilityWindow"
|
|
54
56
|
private const val PROP_HEADERS = "headers"
|
|
57
|
+
private const val PROP_AD_TAG_PARAMETERS = "adTagParameters"
|
|
58
|
+
private const val PROP_BACKDROP_DOUBLE_BOX = "backdropDoubleBox"
|
|
59
|
+
private const val PROP_BACKDROP_LSHAPE = "backdropLShape"
|
|
60
|
+
private const val PROP_CUSTOM_ASSET_KEY = "customAssetKey"
|
|
61
|
+
private const val PROP_OVERRIDE_LAYOUT = "overrideLayout"
|
|
62
|
+
private const val PROP_NETWORK_CODE = "networkCode"
|
|
63
|
+
private const val PROP_USE_ID3 = "useId3"
|
|
64
|
+
|
|
55
65
|
private const val ERROR_IMA_NOT_ENABLED = "Google IMA support not enabled."
|
|
66
|
+
private const val ERROR_THEOADS_NOT_ENABLED = "THEOads support not enabled."
|
|
56
67
|
private const val ERROR_UNSUPPORTED_CSAI_INTEGRATION = "Unsupported CSAI integration"
|
|
57
68
|
private const val ERROR_MISSING_CSAI_INTEGRATION = "Missing CSAI integration"
|
|
58
69
|
|
|
@@ -252,6 +263,9 @@ class SourceAdapter {
|
|
|
252
263
|
AdIntegration.GOOGLE_IMA.adIntegration -> parseImaAdFromJS(
|
|
253
264
|
jsonAdDescription
|
|
254
265
|
)
|
|
266
|
+
AdIntegration.THEO_ADS.adIntegration -> parseTheoAdFromJS(
|
|
267
|
+
jsonAdDescription
|
|
268
|
+
)
|
|
255
269
|
else -> {
|
|
256
270
|
throw THEOplayerException(
|
|
257
271
|
ErrorCode.AD_ERROR,
|
|
@@ -285,6 +299,40 @@ class SourceAdapter {
|
|
|
285
299
|
.build()
|
|
286
300
|
}
|
|
287
301
|
|
|
302
|
+
@Throws(JSONException::class)
|
|
303
|
+
private fun parseTheoAdFromJS(jsonAdDescription: JSONObject): TheoAdDescription {
|
|
304
|
+
if (!BuildConfig.EXTENSION_THEOADS) {
|
|
305
|
+
throw THEOplayerException(ErrorCode.AD_ERROR, ERROR_THEOADS_NOT_ENABLED)
|
|
306
|
+
}
|
|
307
|
+
return TheoAdDescription(
|
|
308
|
+
adTagParameters = parseAdTagParameters(jsonAdDescription.optJSONObject(PROP_AD_TAG_PARAMETERS)),
|
|
309
|
+
backdropDoubleBox = jsonAdDescription.optString(PROP_BACKDROP_DOUBLE_BOX),
|
|
310
|
+
backdropLShape = jsonAdDescription.optString(PROP_BACKDROP_LSHAPE),
|
|
311
|
+
customAssetKey = jsonAdDescription.optString(PROP_CUSTOM_ASSET_KEY),
|
|
312
|
+
networkCode = jsonAdDescription.optString(PROP_NETWORK_CODE),
|
|
313
|
+
overrideLayout = parseOverrideLayout(jsonAdDescription.optString(PROP_OVERRIDE_LAYOUT)),
|
|
314
|
+
useId3 = jsonAdDescription.optBoolean(PROP_USE_ID3),
|
|
315
|
+
)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
private fun parseAdTagParameters(params: JSONObject?): Map<String, String> =
|
|
319
|
+
params?.keys()?.asSequence()
|
|
320
|
+
?.mapNotNull { key -> key to params.optString(key) }
|
|
321
|
+
?.toMap() ?: emptyMap()
|
|
322
|
+
|
|
323
|
+
private fun parseOverrideLayout(override: String?): TheoAdsLayoutOverride? {
|
|
324
|
+
if (override == null) {
|
|
325
|
+
return null
|
|
326
|
+
}
|
|
327
|
+
when (override) {
|
|
328
|
+
"single" -> return TheoAdsLayoutOverride.SINGLE
|
|
329
|
+
"single-if-mobile" -> return TheoAdsLayoutOverride.SINGLE
|
|
330
|
+
"l-shape" -> return TheoAdsLayoutOverride.LSHAPE
|
|
331
|
+
"double" -> return TheoAdsLayoutOverride.DOUBLE
|
|
332
|
+
}
|
|
333
|
+
return null
|
|
334
|
+
}
|
|
335
|
+
|
|
288
336
|
@Throws(JSONException::class)
|
|
289
337
|
private fun parseTextTrackFromJS(jsonTextTrack: JSONObject): TextTrackDescription {
|
|
290
338
|
val builder = TextTrackDescription.Builder(jsonTextTrack.optString(PROP_SRC))
|
|
@@ -109,6 +109,7 @@ class PayloadBuilder {
|
|
|
109
109
|
val contextPayload = Arguments.createMap()
|
|
110
110
|
context.pip?.let { pipCtx ->
|
|
111
111
|
contextPayload.putString(EVENT_PROP_PIP, when (pipCtx) {
|
|
112
|
+
PresentationModeChangePipContext.TRANSITIONING_TO_PIP -> "transitioning-to-pip"
|
|
112
113
|
PresentationModeChangePipContext.RESTORED -> "restored"
|
|
113
114
|
else -> "closed"
|
|
114
115
|
})
|
|
@@ -15,14 +15,16 @@ let EVENT_TYPE_AD_FIRST_QUARTILE: String = "adfirstquartile"
|
|
|
15
15
|
let EVENT_TYPE_AD_THIRD_QUARTILE: String = "adthirdquartile"
|
|
16
16
|
let EVENT_TYPE_AD_MIDPOINT: String = "admidpoint"
|
|
17
17
|
let EVENT_TYPE_AD_LOADED: String = "adloaded"
|
|
18
|
+
let EVENT_TYPE_AD_TAPPED: String = "adtapped"
|
|
19
|
+
let EVENT_TYPE_AD_CLICKED: String = "adclicked"
|
|
18
20
|
|
|
19
21
|
class THEOplayerRCTAdsEventHandler {
|
|
20
22
|
// MARK: Members
|
|
21
23
|
private weak var player: THEOplayer?
|
|
22
|
-
|
|
24
|
+
|
|
23
25
|
// MARK: Events
|
|
24
26
|
var onNativeAdEvent: RCTDirectEventBlock?
|
|
25
|
-
|
|
27
|
+
|
|
26
28
|
// MARK: Ad Listeners
|
|
27
29
|
private var adBeginListener: EventListener?
|
|
28
30
|
private var adEndListener: EventListener?
|
|
@@ -33,27 +35,29 @@ class THEOplayerRCTAdsEventHandler {
|
|
|
33
35
|
private var adMidpointListener: EventListener?
|
|
34
36
|
private var adThirdQuartileListener: EventListener?
|
|
35
37
|
private var adLoadedListener: EventListener?
|
|
36
|
-
|
|
38
|
+
private var adTappedListener: EventListener?
|
|
39
|
+
private var adClickedListener: EventListener?
|
|
40
|
+
|
|
37
41
|
// MARK: - destruction
|
|
38
42
|
func destroy() {
|
|
39
43
|
// dettach listeners
|
|
40
44
|
self.dettachListeners()
|
|
41
45
|
}
|
|
42
|
-
|
|
46
|
+
|
|
43
47
|
// MARK: - player setup / breakdown
|
|
44
48
|
func setPlayer(_ player: THEOplayer) {
|
|
45
49
|
self.player = player;
|
|
46
|
-
|
|
50
|
+
|
|
47
51
|
// attach listeners
|
|
48
52
|
self.attachListeners()
|
|
49
53
|
}
|
|
50
|
-
|
|
54
|
+
|
|
51
55
|
// MARK: - attach/dettach Listeners
|
|
52
56
|
private func attachListeners() {
|
|
53
57
|
guard let player = self.player else {
|
|
54
58
|
return
|
|
55
59
|
}
|
|
56
|
-
|
|
60
|
+
|
|
57
61
|
#if canImport(THEOplayerGoogleIMAIntegration)
|
|
58
62
|
// AD_BEGIN
|
|
59
63
|
self.adBeginListener = player.ads.addEventListener(type: AdsEventTypes.AD_BEGIN) { [weak self] event in
|
|
@@ -67,7 +71,7 @@ class THEOplayerRCTAdsEventHandler {
|
|
|
67
71
|
}
|
|
68
72
|
}
|
|
69
73
|
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBegin listener attached to THEOplayer.ads") }
|
|
70
|
-
|
|
74
|
+
|
|
71
75
|
// AD_END
|
|
72
76
|
self.adEndListener = player.ads.addEventListener(type: AdsEventTypes.AD_END) { [weak self] event in
|
|
73
77
|
if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_END event from THEOplayer Ads") }
|
|
@@ -80,7 +84,7 @@ class THEOplayerRCTAdsEventHandler {
|
|
|
80
84
|
}
|
|
81
85
|
}
|
|
82
86
|
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdEnd listener attached to THEOplayer.ads") }
|
|
83
|
-
|
|
87
|
+
|
|
84
88
|
// AD_BREAK_BEGIN
|
|
85
89
|
self.adBreakBeginListener = player.ads.addEventListener(type: AdsEventTypes.AD_BREAK_BEGIN) { [weak self] event in
|
|
86
90
|
if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_BREAK_BEGIN event from THEOplayer Ads") }
|
|
@@ -93,7 +97,7 @@ class THEOplayerRCTAdsEventHandler {
|
|
|
93
97
|
}
|
|
94
98
|
}
|
|
95
99
|
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBreakBegin listener attached to THEOplayer.ads") }
|
|
96
|
-
|
|
100
|
+
|
|
97
101
|
// AD_BREAK_END
|
|
98
102
|
self.adBreakEndListener = player.ads.addEventListener(type: AdsEventTypes.AD_BREAK_END) { [weak self] event in
|
|
99
103
|
if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_BREAK_END event from THEOplayer Ads") }
|
|
@@ -106,7 +110,7 @@ class THEOplayerRCTAdsEventHandler {
|
|
|
106
110
|
}
|
|
107
111
|
}
|
|
108
112
|
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBreakEnd listener attached to THEOplayer.ads") }
|
|
109
|
-
|
|
113
|
+
|
|
110
114
|
// AD_ERROR
|
|
111
115
|
self.adErrorListener = player.ads.addEventListener(type: AdsEventTypes.AD_ERROR) { [weak self] event in
|
|
112
116
|
if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_ERROR event from THEOplayer Ads") }
|
|
@@ -119,7 +123,7 @@ class THEOplayerRCTAdsEventHandler {
|
|
|
119
123
|
}
|
|
120
124
|
}
|
|
121
125
|
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdError listener attached to THEOplayer.ads") }
|
|
122
|
-
|
|
126
|
+
|
|
123
127
|
// AD_FIRST_QUARTILE
|
|
124
128
|
self.adFirstQuartileListener = player.ads.addEventListener(type: AdsEventTypes.AD_FIRST_QUARTILE) { [weak self] event in
|
|
125
129
|
if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_FIRST_QUARTILE event from THEOplayer Ads") }
|
|
@@ -132,7 +136,7 @@ class THEOplayerRCTAdsEventHandler {
|
|
|
132
136
|
}
|
|
133
137
|
}
|
|
134
138
|
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdFirstQuartile listener attached to THEOplayer.ads") }
|
|
135
|
-
|
|
139
|
+
|
|
136
140
|
// AD_MIDPOINT
|
|
137
141
|
self.adMidpointListener = player.ads.addEventListener(type: AdsEventTypes.AD_MIDPOINT) { [weak self] event in
|
|
138
142
|
if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_MIDPOINT event from THEOplayer Ads") }
|
|
@@ -145,7 +149,7 @@ class THEOplayerRCTAdsEventHandler {
|
|
|
145
149
|
}
|
|
146
150
|
}
|
|
147
151
|
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdMidpoint listener attached to THEOplayer.ads") }
|
|
148
|
-
|
|
152
|
+
|
|
149
153
|
// AD_THIRD_QUARTILE
|
|
150
154
|
self.adThirdQuartileListener = player.ads.addEventListener(type: AdsEventTypes.AD_THIRD_QUARTILE) { [weak self] event in
|
|
151
155
|
if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_THIRD_QUARTILE event from THEOplayer Ads") }
|
|
@@ -158,7 +162,7 @@ class THEOplayerRCTAdsEventHandler {
|
|
|
158
162
|
}
|
|
159
163
|
}
|
|
160
164
|
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdThirdQuartile listener attached to THEOplayer.ads") }
|
|
161
|
-
|
|
165
|
+
|
|
162
166
|
// AD_LOADED
|
|
163
167
|
self.adLoadedListener = player.ads.addEventListener(type: AdsEventTypes.AD_LOADED) { [weak self] event in
|
|
164
168
|
if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_LOADED event from THEOplayer Ads") }
|
|
@@ -170,69 +174,106 @@ class THEOplayerRCTAdsEventHandler {
|
|
|
170
174
|
])
|
|
171
175
|
}
|
|
172
176
|
}
|
|
173
|
-
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE]
|
|
177
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdLoaded listener attached to THEOplayer.ads") }
|
|
178
|
+
|
|
179
|
+
// AD_TAPPED
|
|
180
|
+
self.adTappedListener = player.ads.addEventListener(type: AdsEventTypes.AD_TAPPED) { [weak self] event in
|
|
181
|
+
if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_TAPPED event from THEOplayer Ads") }
|
|
182
|
+
if let forwardedAdEvent = self?.onNativeAdEvent,
|
|
183
|
+
let ad = event.ad {
|
|
184
|
+
forwardedAdEvent([
|
|
185
|
+
AD_EVENT_PROP_TYPE: EVENT_TYPE_AD_TAPPED,
|
|
186
|
+
AD_EVENT_PROP_AD: THEOplayerRCTAdAdapter.fromAd(ad: ad)
|
|
187
|
+
])
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdTapped listener attached to THEOplayer.ads") }
|
|
191
|
+
|
|
192
|
+
// AD_CLICKED
|
|
193
|
+
self.adClickedListener = player.ads.addEventListener(type: AdsEventTypes.AD_CLICKED) { [weak self] event in
|
|
194
|
+
if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_CLICKED event from THEOplayer Ads") }
|
|
195
|
+
if let forwardedAdEvent = self?.onNativeAdEvent,
|
|
196
|
+
let ad = event.ad {
|
|
197
|
+
forwardedAdEvent([
|
|
198
|
+
AD_EVENT_PROP_TYPE: EVENT_TYPE_AD_CLICKED,
|
|
199
|
+
AD_EVENT_PROP_AD: THEOplayerRCTAdAdapter.fromAd(ad: ad)
|
|
200
|
+
])
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdClicked listener attached to THEOplayer.ads") }
|
|
174
204
|
#endif
|
|
175
|
-
|
|
176
205
|
}
|
|
177
|
-
|
|
206
|
+
|
|
178
207
|
private func dettachListeners() {
|
|
179
208
|
guard let player = self.player else {
|
|
180
209
|
return
|
|
181
210
|
}
|
|
182
|
-
|
|
211
|
+
|
|
183
212
|
#if canImport(THEOplayerGoogleIMAIntegration)
|
|
184
213
|
// AD_BEGIN
|
|
185
214
|
if let adBeginListener = self.adBeginListener {
|
|
186
215
|
player.ads.removeEventListener(type: AdsEventTypes.AD_BEGIN, listener: adBeginListener)
|
|
187
|
-
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBegin listener
|
|
216
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBegin listener detached from THEOplayer.ads") }
|
|
188
217
|
}
|
|
189
|
-
|
|
218
|
+
|
|
190
219
|
// AD_END
|
|
191
220
|
if let adEndListener = self.adEndListener {
|
|
192
221
|
player.ads.removeEventListener(type: AdsEventTypes.AD_END, listener: adEndListener)
|
|
193
|
-
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdEnd listener
|
|
222
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdEnd listener detached from THEOplayer.ads") }
|
|
194
223
|
}
|
|
195
|
-
|
|
224
|
+
|
|
196
225
|
// AD_BREAK_BEGIN
|
|
197
226
|
if let adBreakBeginListener = self.adBreakBeginListener {
|
|
198
227
|
player.ads.removeEventListener(type: AdsEventTypes.AD_BREAK_BEGIN, listener: adBreakBeginListener)
|
|
199
|
-
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBreakBegin listener
|
|
228
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBreakBegin listener detached from THEOplayer.ads") }
|
|
200
229
|
}
|
|
201
|
-
|
|
230
|
+
|
|
202
231
|
// AD_BREAK_END
|
|
203
232
|
if let adBreakEndListener = self.adBreakEndListener {
|
|
204
233
|
player.ads.removeEventListener(type: AdsEventTypes.AD_BREAK_END, listener: adBreakEndListener)
|
|
205
|
-
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBreakEnd listener
|
|
234
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBreakEnd listener detached from THEOplayer.ads") }
|
|
206
235
|
}
|
|
207
|
-
|
|
236
|
+
|
|
208
237
|
// AD_ERROR
|
|
209
238
|
if let adErrorListener = self.adErrorListener {
|
|
210
239
|
player.ads.removeEventListener(type: AdsEventTypes.AD_ERROR, listener: adErrorListener)
|
|
211
|
-
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdError listener
|
|
240
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdError listener detached from THEOplayer.ads") }
|
|
212
241
|
}
|
|
213
|
-
|
|
242
|
+
|
|
214
243
|
// AD_FIRST_QUARTILE
|
|
215
244
|
if let adFirstQuartileListener = self.adFirstQuartileListener {
|
|
216
245
|
player.ads.removeEventListener(type: AdsEventTypes.AD_FIRST_QUARTILE, listener: adFirstQuartileListener)
|
|
217
|
-
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adFirstQuartileListener listener
|
|
246
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adFirstQuartileListener listener detached from THEOplayer.ads") }
|
|
218
247
|
}
|
|
219
|
-
|
|
248
|
+
|
|
220
249
|
// AD_MIDPOINT
|
|
221
250
|
if let adMidpointListener = self.adMidpointListener {
|
|
222
251
|
player.ads.removeEventListener(type: AdsEventTypes.AD_MIDPOINT, listener: adMidpointListener)
|
|
223
|
-
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adMidpointListener listener
|
|
252
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adMidpointListener listener detached from THEOplayer.ads") }
|
|
224
253
|
}
|
|
225
|
-
|
|
254
|
+
|
|
226
255
|
// AD_THIRD_QUARTILE
|
|
227
256
|
if let adThirdQuartileListener = self.adThirdQuartileListener {
|
|
228
257
|
player.ads.removeEventListener(type: AdsEventTypes.AD_THIRD_QUARTILE, listener: adThirdQuartileListener)
|
|
229
|
-
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adThirdQuartileListener listener
|
|
258
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adThirdQuartileListener listener detached from THEOplayer.ads") }
|
|
230
259
|
}
|
|
231
|
-
|
|
260
|
+
|
|
232
261
|
// AD_LOADED
|
|
233
262
|
if let adLoadedListener = self.adLoadedListener {
|
|
234
263
|
player.ads.removeEventListener(type: AdsEventTypes.AD_LOADED, listener: adLoadedListener)
|
|
235
|
-
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adLoadedListener listener
|
|
264
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adLoadedListener listener detached from THEOplayer.ads") }
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// AD_TAPPED
|
|
268
|
+
if let adTappedListener = self.adLoadedListener {
|
|
269
|
+
player.ads.removeEventListener(type: AdsEventTypes.AD_TAPPED, listener: adTappedListener)
|
|
270
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adTapped listener detached from THEOplayer.ads") }
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// AD_CLICKED
|
|
274
|
+
if let adClickedListener = self.adLoadedListener {
|
|
275
|
+
player.ads.removeEventListener(type: AdsEventTypes.AD_CLICKED, listener: adClickedListener)
|
|
276
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adClicked listener detached from THEOplayer.ads") }
|
|
236
277
|
}
|
|
237
278
|
#endif
|
|
238
279
|
|