Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/broadcast api #235

Merged
merged 30 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4c60957
Add external event router module for Android
tvanlaerhoven Dec 1, 2023
a64d57c
Rename broadcast api
tvanlaerhoven Dec 1, 2023
7aae2a3
Rename broadcast api
tvanlaerhoven Dec 1, 2023
8e9f55a
Fix typing
tvanlaerhoven Dec 1, 2023
97cf4d7
Move adapters
tvanlaerhoven Dec 1, 2023
c43d8d9
Add web broadcast
tvanlaerhoven Dec 1, 2023
190094d
Update theoplayer dependency
tvanlaerhoven Dec 1, 2023
5b477d7
Setup iOS BroadcastModule
wvanhaevre Dec 1, 2023
c971f1c
Lookup native modules responding to specific selector
wvanhaevre Dec 1, 2023
0d5ae4b
remove import
wvanhaevre Dec 1, 2023
1300828
Rename module on RN side
wvanhaevre Dec 1, 2023
ab63b2d
Convert AdAggregator to AdAdapter that also generates native ads from…
wvanhaevre Dec 5, 2023
49091f8
Add AdEventAdapter
wvanhaevre Dec 5, 2023
85e40c5
Update broadcast api
tvanlaerhoven Dec 4, 2023
3508c33
Add conversion warning
tvanlaerhoven Dec 4, 2023
25dd656
Move broadcast api
tvanlaerhoven Dec 4, 2023
c31ba0a
Remove console import
tvanlaerhoven Dec 4, 2023
56c34cb
Update EventBroadcastAPI
wvanhaevre Dec 5, 2023
f2f7df5
Update Broadcast module name
wvanhaevre Dec 5, 2023
822211a
pack broadcast classes as part of ios bridge
wvanhaevre Dec 5, 2023
b0151c5
Use correct metaData field for subType
wvanhaevre Dec 5, 2023
3d5c644
Pass node when broadcasting an event
wvanhaevre Dec 5, 2023
959a111
Remove ima integration check on adadapter
wvanhaevre Dec 5, 2023
594badd
Update native ad conversion
tvanlaerhoven Dec 5, 2023
4216376
print exception on Broadcast module issue
wvanhaevre Dec 7, 2023
a0bc14b
Move broadcast to player
tvanlaerhoven Dec 6, 2023
87b24fa
Rework to internal broadcast event dispatcher for iOS
wvanhaevre Dec 8, 2023
35e7516
Freeze event before bridging
tvanlaerhoven Dec 8, 2023
784846e
Use single quote imports
wvanhaevre Dec 10, 2023
9ac1c68
Update changelog
wvanhaevre Dec 11, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.1.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Changed

- Extended event dispatching mechanism with broadcast functionality.

## [3.2.1] - 23-12-07

### Fixed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.theoplayer.ads.AdsModule
import com.theoplayer.cache.CacheModule
import com.theoplayer.drm.ContentProtectionModule
import com.theoplayer.cast.CastModule
import com.theoplayer.broadcast.EventBroadcastModule
import com.theoplayer.player.PlayerModule

class ReactTHEOplayerPackage : ReactPackage {
Expand All @@ -17,7 +18,8 @@ class ReactTHEOplayerPackage : ReactPackage {
AdsModule(reactContext),
ContentProtectionModule(reactContext),
CastModule(reactContext),
CacheModule(reactContext)
CacheModule(reactContext),
EventBroadcastModule(reactContext)
)
}

Expand Down
3 changes: 2 additions & 1 deletion android/src/main/java/com/theoplayer/ReactTHEOplayerView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.theoplayer.android.api.ads.wrapper.AdsApiWrapper
import com.theoplayer.android.api.cast.Cast
import com.theoplayer.android.api.error.THEOplayerException
import com.theoplayer.android.api.player.Player
import com.theoplayer.broadcast.EventBroadcastAdapter
import com.theoplayer.presentation.PresentationManager
import com.theoplayer.source.SourceAdapter

Expand All @@ -22,7 +23,7 @@ class ReactTHEOplayerView(private val reactContext: ThemedReactContext) :

private val eventEmitter: PlayerEventEmitter =
PlayerEventEmitter(reactContext.reactApplicationContext, this)

val broadcast = EventBroadcastAdapter(this)
var presentationManager: PresentationManager? = null
var playerContext: ReactTHEOplayerContext? = null
private var isInitialized: Boolean = false
Expand Down
299 changes: 295 additions & 4 deletions android/src/main/java/com/theoplayer/ads/AdAdapter.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package com.theoplayer.ads

import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.WritableArray
import com.google.ads.interactivemedia.v3.api.AdPodInfo
import com.google.ads.interactivemedia.v3.api.UiElement
import com.theoplayer.android.api.ads.Ad
import com.theoplayer.android.api.ads.AdBreak
import com.theoplayer.android.api.ads.CompanionAd
import com.theoplayer.android.api.ads.GoogleImaAd
import com.theoplayer.android.api.ads.UniversalAdId
import com.theoplayer.android.api.event.ads.AdIntegrationKind
import java.lang.Exception

private const val PROP_AD_SYSTEM = "adSystem"
Expand Down Expand Up @@ -42,11 +47,13 @@ private const val PROP_COMPANION_RESOURCEURI = "resourceURI"
private const val PROP_UNIVERSAL_AD_ID_REGISTRY = "adIdRegistry"
private const val PROP_UNIVERSAL_AD_ID_VALUE = "adIdValue"

object AdAdapter {
fun fromAd(ad: Ad): WritableMap {
return fromAd(ad, true)
}
private const val INVALID_DOUBLE = -1.0
private const val INVALID_INT = -1

object AdAdapter {
/**
* Convert a list of native Ads to a ReactNative Ads.
*/
fun fromAds(ads: List<Ad>): WritableArray {
val payload = Arguments.createArray()
for (ad in ads) {
Expand All @@ -55,6 +62,16 @@ object AdAdapter {
return payload
}

/**
* Convert a native Ad to a ReactNative Ad.
*/
fun fromAd(ad: Ad): WritableMap {
return fromAd(ad, true)
}

/**
* Convert a native Ad to a ReactNative Ad, optionally include its AdBreak.
*/
private fun fromAd(ad: Ad, includeAdBreak: Boolean): WritableMap {
val adPayload = Arguments.createMap()
adPayload.putString(
Expand Down Expand Up @@ -113,6 +130,9 @@ object AdAdapter {
return adPayload
}

/**
* Convert a native AdBreak to a ReactNative AdBreak.
*/
fun fromAdBreak(adbreak: AdBreak?): WritableMap {
val adbreakPayload = Arguments.createMap()
if (adbreak == null) {
Expand Down Expand Up @@ -158,4 +178,275 @@ object AdAdapter {
}
return companionsPayload
}

/**
* Convert a ReactNative Ad to a native Ad.
*/
fun parseAd(ad: ReadableMap?): GoogleImaAd? {
if (ad == null) {
return null
}
return object: GoogleImaAd {
override fun getId(): String {
return ad.getString(PROP_AD_ID) ?: ""
}

override fun getCompanions(): List<CompanionAd> {
return emptyList()
}

override fun getType(): String? {
return ad.getString(PROP_AD_TYPE)
}

override fun getAdBreak(): AdBreak? {
return parseAdBreak(ad.getMap(PROP_AD_BREAK))
}

override fun getSkipOffset(): Int {
return if (ad.hasKey(PROP_AD_SKIPOFFSET)) ad.getInt(PROP_AD_SKIPOFFSET) else 0
}

override fun getIntegration(): AdIntegrationKind {
return AdIntegrationKind.from(ad.getString(PROP_AD_INTEGRATION))
}

override fun getImaAd(): com.google.ads.interactivemedia.v3.api.Ad {
return parseImaAd(ad)
}

override fun getAdSystem(): String {
return ad.getString(PROP_AD_SYSTEM) ?: ""
}

override fun getCreativeId(): String? {
return ad.getString(PROP_AD_CREATIVE_ID)
}

override fun getWrapperAdIds(): List<String> {
return emptyList()
}

override fun getWrapperAdSystems(): List<String> {
return emptyList()
}

override fun getWrapperCreativeIds(): List<String> {
return emptyList()
}

override fun getVastMediaBitrate(): Int {
return if (ad.hasKey(PROP_AD_BITRATE)) ad.getInt(PROP_AD_BITRATE) else 0
}

override fun getUniversalAdIds(): List<UniversalAdId> {
return emptyList()
}

override fun getTraffickingParameters(): String {
return ad.getString(PROP_AD_TRAFFICKING_PARAMETERS) ?: ""
}
}
}

fun parseAdBreak(adBreak: ReadableMap?): AdBreak? {
if (adBreak == null) {
return null
}
return object: AdBreak {
override fun getAds(): List<Ad> {
return emptyList()
}

override fun getMaxDuration(): Int {
return if (adBreak.hasKey(PROP_ADBREAK_MAXDURATION))
(1e-3 * adBreak.getInt(PROP_ADBREAK_MAXDURATION)).toInt()
else
INVALID_INT
}

override fun getMaxRemainingDuration(): Double {
return if (adBreak.hasKey(PROP_ADBREAK_MAXREMAININGDURATION))
1e-3 * adBreak.getDouble(PROP_ADBREAK_MAXREMAININGDURATION)
else
INVALID_DOUBLE
}

override fun getTimeOffset(): Int {
return if (adBreak.hasKey(PROP_ADBREAK_TIMEOFFSET))
(1e-3 * adBreak.getInt(PROP_ADBREAK_TIMEOFFSET)).toInt()
else
0
}

override fun getIntegration(): AdIntegrationKind {
return AdIntegrationKind.from(adBreak.getString(PROP_ADBREAK_INTEGRATION))
}
}
}

fun parseImaAd(ad: ReadableMap?): com.google.ads.interactivemedia.v3.api.Ad {
return object: com.google.ads.interactivemedia.v3.api.Ad {
override fun getDuration(): Double {
return ad?.run {
if (hasKey(PROP_AD_DURATION)) 1e-3 * getDouble(PROP_AD_DURATION) else INVALID_DOUBLE
} ?: INVALID_DOUBLE
}

override fun getSkipTimeOffset(): Double {
return ad?.run {
if (hasKey(PROP_AD_SKIPOFFSET)) 1e-3 * getDouble(PROP_AD_SKIPOFFSET) else INVALID_DOUBLE
} ?: INVALID_DOUBLE
}

override fun getHeight(): Int {
return ad?.run {
if (hasKey(PROP_AD_HEIGHT)) getInt(PROP_AD_HEIGHT) else INVALID_INT
} ?: INVALID_INT
}

override fun getVastMediaBitrate(): Int {
return ad?.run {
if (hasKey(PROP_AD_BITRATE)) getInt(PROP_AD_BITRATE) else INVALID_INT
} ?: INVALID_INT
}

override fun getVastMediaHeight(): Int {
return ad?.run {
if (hasKey(PROP_AD_HEIGHT)) getInt(PROP_AD_HEIGHT) else INVALID_INT
} ?: INVALID_INT
}

override fun getVastMediaWidth(): Int {
return ad?.run {
if (hasKey(PROP_AD_WIDTH)) getInt(PROP_AD_WIDTH) else INVALID_INT
} ?: INVALID_INT
}

override fun getWidth(): Int {
return ad?.run {
if (hasKey(PROP_AD_WIDTH)) getInt(PROP_AD_WIDTH) else INVALID_INT
} ?: INVALID_INT
}

override fun getAdPodInfo(): AdPodInfo {
return object: AdPodInfo {
override fun getMaxDuration(): Double {
return INVALID_DOUBLE
}

override fun getTimeOffset(): Double {
return INVALID_DOUBLE
}

override fun getAdPosition(): Int {
return INVALID_INT
}

override fun getPodIndex(): Int {
return INVALID_INT
}

override fun getTotalAds(): Int {
return INVALID_INT
}

override fun isBumper(): Boolean {
return false
}
}
}

override fun getAdId(): String {
return ad?.getString(PROP_AD_ID) ?: ""
}

override fun getAdSystem(): String {
return ad?.getString(PROP_AD_SYSTEM) ?: ""
}

override fun getAdvertiserName(): String {
return ""
}

override fun getContentType(): String {
return ad?.getString(PROP_AD_CONTENT_TYPE) ?: ""
}

override fun getCreativeAdId(): String {
return ""
}

override fun getCreativeId(): String {
return ad?.getString(PROP_AD_CREATIVE_ID) ?: ""
}

override fun getDealId(): String {
return ""
}

override fun getDescription(): String {
return ""
}

override fun getSurveyUrl(): String {
return ""
}

override fun getTitle(): String {
return ad?.getString(PROP_AD_TITLE) ?: ""
}

override fun getTraffickingParameters(): String {
return ad?.getString(PROP_AD_TRAFFICKING_PARAMETERS) ?: ""
}

@Deprecated("Deprecated in Java")
override fun getUniversalAdIdRegistry(): String {
return ""
}

@Deprecated("Deprecated in Java")
override fun getUniversalAdIdValue(): String {
return ad?.getString(PROP_UNIVERSAL_AD_ID_VALUE) ?: ""
}

override fun getCompanionAds(): List<com.google.ads.interactivemedia.v3.api.CompanionAd> {
return emptyList()
}

override fun getUiElements(): Set<UiElement> {
return emptySet()
}

override fun isLinear(): Boolean {
// Only linear ads are supported currently
return true
}

override fun isSkippable(): Boolean {
return false
}

override fun isUiDisabled(): Boolean {
return false
}

override fun getUniversalAdIds(): Array<com.google.ads.interactivemedia.v3.api.UniversalAdId> {
return emptyArray()
}

override fun getAdWrapperCreativeIds(): Array<String> {
return emptyArray()
}

override fun getAdWrapperIds(): Array<String> {
return emptyArray()
}

override fun getAdWrapperSystems(): Array<String> {
return emptyArray()
}
}
}
}
Loading
Loading