Merge remote-tracking branch 'official/master'

This commit is contained in:
Yavor Ivanov 2023-02-13 15:39:22 +02:00
commit 3266eb2d67
12 changed files with 152 additions and 18 deletions

18
API.md
View File

@ -164,6 +164,21 @@ protected List<ReactPackage> getPackages() {
); );
} }
``` ```
#### Enable custom feature in gradle file
##### Enable client side ads insertion
To enable client side ads insertion CSAI with google IMA SDK, you need to enable it in your gradle file.
```gradle
buildscript {
ext {
...
RNVUseExoplayerIMA = true
...
}
}
```
</details> </details>
### Windows installation ### Windows installation
@ -370,6 +385,9 @@ Example:
adTagUrl="https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/vmap_ad_samples&sz=640x480&cust_params=sample_ar%3Dpremidpostoptimizedpodbumper&ciu_szs=300x250&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&env=vp&impl=s&cmsid=496&vid=short_onecue&correlator=" adTagUrl="https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/vmap_ad_samples&sz=640x480&cust_params=sample_ar%3Dpremidpostoptimizedpodbumper&ciu_szs=300x250&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&env=vp&impl=s&cmsid=496&vid=short_onecue&correlator="
``` ```
Note: On android, you need enable IMA SDK in gradle file, see: [enableclient side ads insertion](#enable-client-side-ads-insertion)
Platforms: Android, iOS Platforms: Android, iOS
#### allowsExternalPlayback #### allowsExternalPlayback

View File

@ -4,6 +4,18 @@ def safeExtGet(prop, fallback) {
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
} }
def useExoplayerIMA = safeExtGet("RNVUseExoplayerIMA", false)
println "useExoplayerIMA:" + useExoplayerIMA
// This string is used to define build path.
// As react native build output directory is react-native path of the module.
// We need to force a new path on each configuration change.
// If you add a new build parameter, please add the new value in this string
def configStringPath = (
'useExoplayerIMA' + useExoplayerIMA \
).md5()
android { android {
compileSdkVersion safeExtGet('compileSdkVersion', 31) compileSdkVersion safeExtGet('compileSdkVersion', 31)
buildToolsVersion safeExtGet('buildToolsVersion', '30.0.2') buildToolsVersion safeExtGet('buildToolsVersion', '30.0.2')
@ -24,6 +36,19 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
buildDir 'buildOutput_' + configStringPath
sourceSets {
main {
java {
if (useExoplayerIMA) {
exclude 'com/google/ads/interactivemedia/v3/api'
exclude 'com/google/android/exoplayer2/ext/ima'
}
}
}
}
} }
repositories { repositories {
@ -45,7 +70,9 @@ dependencies {
implementation('com.google.android.exoplayer:extension-okhttp:2.18.1') { implementation('com.google.android.exoplayer:extension-okhttp:2.18.1') {
exclude group: 'com.squareup.okhttp3', module: 'okhttp' exclude group: 'com.squareup.okhttp3', module: 'okhttp'
} }
implementation 'com.google.android.exoplayer:extension-ima:2.18.1'
if (useExoplayerIMA) {
implementation 'com.google.android.exoplayer:extension-ima:2.18.1'
}
implementation "com.squareup.okhttp3:okhttp:" + '$OKHTTP_VERSION' implementation "com.squareup.okhttp3:okhttp:" + '$OKHTTP_VERSION'
} }

View File

@ -0,0 +1,11 @@
package com.google.ads.interactivemedia.v3.api;
import androidx.annotation.InspectableProperty;
public abstract class AdEvent {
public abstract InspectableProperty getType();
public interface AdEventListener {
public void onAdEvent(AdEvent adEvent);
}
}

View File

@ -0,0 +1,65 @@
package com.google.android.exoplayer2.ext.ima;
import androidx.annotation.Nullable;
import com.facebook.react.uimanager.ThemedReactContext;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.source.ads.AdsLoader;
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
import com.google.android.exoplayer2.ui.AdViewProvider;
import com.google.android.exoplayer2.upstream.DataSpec;
import java.io.IOException;
public class ImaAdsLoader implements AdsLoader {
public void setPlayer(ExoPlayer player) {
}
@Override
public void setPlayer(@Nullable Player player) {
}
public void release() {
}
@Override
public void setSupportedContentTypes(int... ints) {
}
@Override
public void start(AdsMediaSource adsMediaSource, DataSpec dataSpec, Object o, AdViewProvider adViewProvider, EventListener eventListener) {
}
@Override
public void stop(AdsMediaSource adsMediaSource, EventListener eventListener) {
}
@Override
public void handlePrepareComplete(AdsMediaSource adsMediaSource, int i, int i1) {
}
@Override
public void handlePrepareError(AdsMediaSource adsMediaSource, int i, int i1, IOException e) {
}
public static class Builder {
public Builder(ThemedReactContext themedReactContext) {
}
public Builder setAdEventListener(Object reactExoplayerView) {
return this;
}
public ImaAdsLoader build() {
return null;
}
}
}

View File

@ -14,6 +14,8 @@ buildscript {
// Otherwise we default to the side-by-side NDK version from AGP. // Otherwise we default to the side-by-side NDK version from AGP.
ndkVersion = "21.4.7075529" ndkVersion = "21.4.7075529"
} }
RNVUseExoplayerIMA = true
} }
repositories { repositories {
google() google()

View File

@ -5,7 +5,7 @@
* @format * @format
*/ */
const path = require('path'); const path = require('path');
const blacklist = require('metro-config/src/defaults/blacklist'); const blacklist = require('metro-config/src/defaults/exclusionList');
module.exports = { module.exports = {
resolver: { resolver: {

View File

@ -44,7 +44,7 @@ class RCTResourceLoaderDelegate: NSObject, AVAssetResourceLoaderDelegate, URLSes
} }
func resourceLoader(_ resourceLoader:AVAssetResourceLoader, didCancel loadingRequest:AVAssetResourceLoadingRequest) { func resourceLoader(_ resourceLoader:AVAssetResourceLoader, didCancel loadingRequest:AVAssetResourceLoadingRequest) {
NSLog("didCancelLoadingRequest") RCTLog("didCancelLoadingRequest")
} }
func setLicenseResult(_ license:String!) { func setLicenseResult(_ license:String!) {

View File

@ -111,10 +111,14 @@ enum RCTVideoUtils {
title = value as! String title = value as! String
} }
let language:String! = currentOption?.extendedLanguageTag ?? "" let language:String! = currentOption?.extendedLanguageTag ?? ""
let selectedOption: AVMediaSelectionOption? = player.currentItem?.currentMediaSelection.selectedMediaOption(in: group!)
let audioTrack = [ let audioTrack = [
"index": NSNumber(value: i), "index": NSNumber(value: i),
"title": title, "title": title,
"language": language "language": language ?? "",
"selected": currentOption?.displayName == selectedOption?.displayName
] as [String : Any] ] as [String : Any]
audioTracks.add(audioTrack) audioTracks.add(audioTrack)
} }
@ -137,10 +141,13 @@ enum RCTVideoUtils {
title = value as! String title = value as! String
} }
let language:String! = currentOption?.extendedLanguageTag ?? "" let language:String! = currentOption?.extendedLanguageTag ?? ""
let selectedOpt = player.currentItem?.currentMediaSelection
let selectedOption: AVMediaSelectionOption? = player.currentItem?.currentMediaSelection.selectedMediaOption(in: group!)
let textTrack = TextTrack([ let textTrack = TextTrack([
"index": NSNumber(value: i), "index": NSNumber(value: i),
"title": title, "title": title,
"language": language "language": language,
"selected": currentOption?.displayName == selectedOption?.displayName
]) ])
textTracks.append(textTrack) textTracks.append(textTrack)
} }

View File

@ -1017,6 +1017,8 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
} }
if _videoLoadStarted { if _videoLoadStarted {
let audioTracks = RCTVideoUtils.getAudioTrackInfo(_player)
let textTracks = RCTVideoUtils.getTextTrackInfo(_player).map(\.json)
onVideoLoad?(["duration": NSNumber(value: duration), onVideoLoad?(["duration": NSNumber(value: duration),
"currentTime": NSNumber(value: Float(CMTimeGetSeconds(_playerItem.currentTime()))), "currentTime": NSNumber(value: Float(CMTimeGetSeconds(_playerItem.currentTime()))),
"canPlayReverse": NSNumber(value: _playerItem.canPlayReverse), "canPlayReverse": NSNumber(value: _playerItem.canPlayReverse),
@ -1030,8 +1032,8 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
"height": width != nil ? NSNumber(value: height!) : "undefinded", "height": width != nil ? NSNumber(value: height!) : "undefinded",
"orientation": orientation "orientation": orientation
], ],
"audioTracks": RCTVideoUtils.getAudioTrackInfo(_player), "audioTracks": audioTracks,
"textTracks": _textTracks ?? RCTVideoUtils.getTextTrackInfo(_player), "textTracks": textTracks,
"target": reactTag as Any]) "target": reactTag as Any])
} }
_videoLoadStarted = false _videoLoadStarted = false
@ -1090,7 +1092,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
let newRect = change.newValue let newRect = change.newValue
if !oldRect!.equalTo(newRect!) { if !oldRect!.equalTo(newRect!) {
if newRect!.equalTo(UIScreen.main.bounds) { if newRect!.equalTo(UIScreen.main.bounds) {
NSLog("in fullscreen") RCTLog("in fullscreen")
self.reactViewController().view.frame = UIScreen.main.bounds self.reactViewController().view.frame = UIScreen.main.bounds
self.reactViewController().view.setNeedsLayout() self.reactViewController().view.setNeedsLayout()

View File

@ -25,29 +25,31 @@
* way into one or the other eventually. Feel free to reuse it as desired. * way into one or the other eventually. Feel free to reuse it as desired.
*/ */
let logHeader: String = "RNV:"
func RCTLogError(_ message: String, _ file: String=#file, _ line: UInt=#line) { func RCTLogError(_ message: String, _ file: String=#file, _ line: UInt=#line) {
RCTVideoSwiftLog.error(message, file: file, line: line) RCTVideoSwiftLog.error(logHeader + message, file: file, line: line)
} }
func RCTLogWarn(_ message: String, _ file: String=#file, _ line: UInt=#line) { func RCTLogWarn(_ message: String, _ file: String=#file, _ line: UInt=#line) {
RCTVideoSwiftLog.warn(message, file: file, line: line) RCTVideoSwiftLog.warn(logHeader + message, file: file, line: line)
} }
func RCTLogInfo(_ message: String, _ file: String=#file, _ line: UInt=#line) { func RCTLogInfo(_ message: String, _ file: String=#file, _ line: UInt=#line) {
RCTVideoSwiftLog.info(message, file: file, line: line) RCTVideoSwiftLog.info(logHeader + message, file: file, line: line)
} }
func RCTLog(_ message: String, _ file: String=#file, _ line: UInt=#line) { func RCTLog(_ message: String, _ file: String=#file, _ line: UInt=#line) {
RCTVideoSwiftLog.log(message, file: file, line: line) RCTVideoSwiftLog.log(logHeader + message, file: file, line: line)
} }
func RCTLogTrace(_ message: String, _ file: String=#file, _ line: UInt=#line) { func RCTLogTrace(_ message: String, _ file: String=#file, _ line: UInt=#line) {
RCTVideoSwiftLog.trace(message, file: file, line: line) RCTVideoSwiftLog.trace(logHeader + message, file: file, line: line)
} }
func DebugLog(_ message: String) { func DebugLog(_ message: String) {
#if DEBUG #if DEBUG
print(message) print(logHeader + message)
#endif #endif
} }

View File

@ -30,7 +30,7 @@
options.useDirectorySeparation = NO; options.useDirectorySeparation = NO;
#ifdef DEBUG #ifdef DEBUG
options.debugOutput = ^(NSString *string) { options.debugOutput = ^(NSString *string) {
NSLog(@"Video Cache: %@", string); RCTLog(@"Video Cache: %@", string);
}; };
#endif #endif
[self createTemporaryPath]; [self createTemporaryPath];
@ -48,7 +48,7 @@
error:&error]; error:&error];
#ifdef DEBUG #ifdef DEBUG
if (!success || error) { if (!success || error) {
NSLog(@"Error while! %@", error); RCTLog(@"Error while! %@", error);
} }
#endif #endif
} }
@ -64,7 +64,7 @@
[self.videoCache storeData:data forKey:key locked:NO withCallback:^(SPTPersistentCacheResponse * _Nonnull response) { [self.videoCache storeData:data forKey:key locked:NO withCallback:^(SPTPersistentCacheResponse * _Nonnull response) {
if (response.error) { if (response.error) {
#ifdef DEBUG #ifdef DEBUG
NSLog(@"An error occured while saving the video into the cache: %@", [response.error localizedDescription]); RCTLog(@"An error occured while saving the video into the cache: %@", [response.error localizedDescription]);
#endif #endif
handler(NO); handler(NO);
return; return;

View File

@ -1,6 +1,6 @@
{ {
"name": "react-native-video", "name": "react-native-video",
"version": "6.0.0-alpha.4", "version": "6.0.0-alpha.5",
"description": "A <Video /> element for react-native", "description": "A <Video /> element for react-native",
"main": "Video.js", "main": "Video.js",
"license": "MIT", "license": "MIT",