Skip to content

Commit

Permalink
Merge pull request #397 from THEOplayer/release/v8.1.0
Browse files Browse the repository at this point in the history
Release/v8.1.0
  • Loading branch information
tvanlaerhoven authored Sep 23, 2024
2 parents 44abf19 + 0f733cd commit 25e5c91
Show file tree
Hide file tree
Showing 12 changed files with 822 additions and 28 deletions.
3 changes: 1 addition & 2 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
npm run lint
npm run prettier
npx lint-staged --allow-empty
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ 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).

## [8.1.0] - 24-09-23

### Added

- Added support for `bitrate` config on the GoogleIMAConfiguration, to be passed to the IMA SDK rendering settings.
- Added support on iOS and Android for `allowedMimeTypes` config on the AdsConfiguration, to be passed to the IMA SDK rendering settings.

### Fixed

- Fixed an issue where cast events were not forwarded from the native Android SDK.
- Fixed an issue where presentationMode changes on iOS would cause a UIViewControllerHierarchyInconsistency when an ad is playing.
- Fixed an issue where some ad event types could not be resolved at runtime when excluding the IMA integration on Android.

## [8.0.3] - 24-09-14

### Fixed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,19 @@
<artifactId>ads-wrapper</artifactId>
<version>8.0.0</version>
<packaging>aar</packaging>
<dependencies>
<!-- Include transitive dependencies -->
<dependency>
<groupId>com.theoplayer.theoplayer-sdk-android</groupId>
<artifactId>integration-ads</artifactId>
<version>8.0.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.theoplayer.theoplayer-sdk-android</groupId>
<artifactId>integration-ads-ima</artifactId>
<version>8.0.0</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
17 changes: 16 additions & 1 deletion android/src/main/java/com/theoplayer/PlayerConfigAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ private const val PROP_FEATURE_FLAGS = "featureFlags"
private const val PROP_AUTOPLAY_AD_BREAKS = "autoPlayAdBreaks"
private const val PROP_SESSION_ID = "sessionID"
private const val PROP_ENABLE_DEBUG_MODE = "enableDebugMode"
private const val PROP_BITRATE = "bitrate"
private const val PROP_ALLOWED_MIMETYPES = "allowedMimeTypes"

class PlayerConfigAdapter(private val configProps: ReadableMap?) {

Expand Down Expand Up @@ -93,7 +95,7 @@ class PlayerConfigAdapter(private val configProps: ReadableMap?) {
*
* @see <a href="https://developers.google.com/interactive-media-ads/docs/sdks/android/client-side/api/reference/com/google/ads/interactivemedia/v3/api/ImaSdkSettings">IMA SDK for Android</a>.
*/
fun imaSdkSettings(): ImaSdkSettings{
fun imaSdkSettings(): ImaSdkSettings {
return ImaSdkFactory.getInstance().createImaSdkSettings().apply {
configProps?.getMap(PROP_ADS_CONFIGURATION)?.getMap(PROP_IMA_CONFIGURATION)?.run {
// Specifies whether VMAP and ad rules ad breaks are automatically played.
Expand Down Expand Up @@ -149,6 +151,19 @@ class PlayerConfigAdapter(private val configProps: ReadableMap?) {
val preloadTypeString = getString(PROP_PRELOAD)
enablePreloading = preloadTypeString !== "none"
}
if (hasKey(PROP_ALLOWED_MIMETYPES)) {
mimeTypes = ArrayList<String>().apply {
getArray(PROP_ALLOWED_MIMETYPES)?.toArrayList()?.forEach {
add(it as String)
}
}
}
}
// bitrate is configured under the ima config
configProps?.getMap(PROP_ADS_CONFIGURATION)?.getMap(PROP_IMA_CONFIGURATION)?.run {
if (hasKey(PROP_BITRATE)) {
bitrateKbps = getInt(PROP_BITRATE)
}
}
}
}
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 @@ -52,7 +52,8 @@ class ReactTHEOplayerView(private val reactContext: ThemedReactContext) :
playerContext = ReactTHEOplayerContext.create(
reactContext,
PlayerConfigAdapter(configProps)
).apply {
)
playerContext?.apply {
adsApi.initialize(player, imaIntegration, daiIntegration)
val layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
playerView.layoutParams = layoutParams
Expand Down
4 changes: 4 additions & 0 deletions ios/ads/THEOplayerRCTView+Ads.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ extension THEOplayerRCTView {
imaRenderSettings.disableUi = disableUi
imaRenderSettings.uiElements = []
}
imaRenderSettings.bitrate = self.adsConfig.adsImaConfig.bitrate
if let allowedMimeTypes = self.adsConfig.allowedMimeTypes {
imaRenderSettings.mimeTypes = allowedMimeTypes
}

// setup integration
let imaIntegration = GoogleIMAIntegrationFactory.createIntegration(on: player, with: imaSettings)
Expand Down
8 changes: 8 additions & 0 deletions ios/ads/THEOplayerRCTView+AdsConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
import Foundation
import THEOplayerSDK

#if canImport(THEOplayerGoogleIMAIntegration)
import GoogleInteractiveMediaAds
#endif

struct AdsConfig {
var adSUIEnabled: Bool = true
var adsImaConfig = AdsImaConfig()
var allowedMimeTypes: [String]?
}

struct AdsImaConfig {
Expand All @@ -15,6 +20,7 @@ struct AdsImaConfig {
var featureFlags: [String:String]?
var autoPlayAdBreaks: Bool?
var sessionID: String?
var bitrate: Int = kIMAAutodetectBitrate
}

#if os(iOS)
Expand All @@ -24,6 +30,7 @@ extension THEOplayerRCTView {
func parseAdsConfig(configDict: NSDictionary) {
if let adsConfig = configDict["ads"] as? NSDictionary {
self.adsConfig.adSUIEnabled = adsConfig["uiEnabled"] as? Bool ?? true
self.adsConfig.allowedMimeTypes = adsConfig["allowedMimeTypes"] as? [String]
if let adsImaConfig = adsConfig["ima"] as? NSDictionary {
if let ppid = adsImaConfig["ppid"] as? String {
self.adsConfig.adsImaConfig.ppid = ppid
Expand All @@ -43,6 +50,7 @@ extension THEOplayerRCTView {
if let enableDebugMode = adsImaConfig["enableDebugMode"] as? Bool {
self.adsConfig.adsImaConfig.enableDebugMode = enableDebugMode
}
self.adsConfig.adsImaConfig.bitrate = adsImaConfig["bitrate"] as? Int ?? kIMAAutodetectBitrate
}
}
}
Expand Down
62 changes: 51 additions & 11 deletions ios/presentationMode/THEOplayerRCTPresentationModeManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import Foundation
import THEOplayerSDK
import UIKit

public class THEOplayerRCTPresentationModeManager {
// MARK: Members
Expand All @@ -10,9 +11,9 @@ public class THEOplayerRCTPresentationModeManager {
var presentationModeContext = THEOplayerRCTPresentationModeContext()
var presentationMode: THEOplayerSDK.PresentationMode = .inline

private var containerView: UIView? // view containing the playerView and it's siblings (e.g. UI)
private var fullscreenParentView: UIView? // target view for fulllscreen representation
private var inlineParentView: UIView? // target view for inline representation
private var containerView: UIView? // view containing the playerView and it's siblings (e.g. UI)
private var inlineParentView: UIView? // target view for inline representation
private var movingChildVCs: [UIViewController] = [] // list of playerView's child VCs that need to be reparented while moving the playerView

// MARK: Events
var onNativePresentationModeChange: RCTDirectEventBlock?
Expand All @@ -37,25 +38,54 @@ public class THEOplayerRCTPresentationModeManager {

// MARK: - logic

private func storeMovingVCs(for view: UIView) {
if let viewController = view.findViewController() {
viewController.children.forEach { childVC in
self.movingChildVCs.append(childVC)
}
}
}

private func clearMovingVCs() {
self.movingChildVCs = []
}

private func moveView(_ movingView: UIView, to targetView: UIView, with movingViewControllers: [UIViewController]) {
// detach the moving viewControllers from their parent
movingViewControllers.forEach { movedVC in
movedVC.removeFromParent()
}

// move the actual view
movingView.removeFromSuperview()
targetView.addSubview(movingView)
targetView.bringSubviewToFront(movingView)

// attach the moving viewControllers to their new parent
if let targetViewController = targetView.findViewController() {
movingViewControllers.forEach { movedVC in
targetViewController.addChild(movedVC)
movedVC.didMove(toParent: targetViewController)
}
}
}

private func enterFullscreen() {
self.containerView = self.view?.findParentViewOfType(RCTView.self)
self.fullscreenParentView = self.view?.findParentViewOfType(RCTRootContentView.self)
self.inlineParentView = self.containerView?.findParentViewOfType(RCTView.self)

if let containerView = self.containerView,
let fullscreenParentView = self.fullscreenParentView {
containerView.removeFromSuperview()
fullscreenParentView.addSubview(containerView)
fullscreenParentView.bringSubviewToFront(containerView)
let fullscreenParentView = self.view?.findParentViewOfType(RCTRootContentView.self) {
self.storeMovingVCs(for: containerView)
self.moveView(containerView, to: fullscreenParentView, with: self.movingChildVCs)
}
}

private func exitFullscreen() {
if let containerView = self.containerView,
let inlineParentView = self.inlineParentView {
containerView.removeFromSuperview()
inlineParentView.addSubview(containerView)
inlineParentView.bringSubviewToFront(containerView)
self.moveView(containerView, to: inlineParentView, with: self.movingChildVCs)
self.clearMovingVCs()
}
}

Expand Down Expand Up @@ -156,4 +186,14 @@ extension UIView {
}
return nil
}

func findViewController() -> UIViewController? {
if let nextResponder = self.next as? UIViewController {
return nextResponder
} else if let nextResponder = self.next as? UIView {
return nextResponder.findViewController()
} else {
return nil
}
}
}
Loading

0 comments on commit 25e5c91

Please sign in to comment.