Merge branch 'implement-ima-sdk' into master

# Conflicts:
#	android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java
#	examples/basic/package.json
#	examples/basic/yarn.lock
#	ios/Video/RCTVideo.h
#	ios/Video/RCTVideo.m
#	ios/Video/RCTVideoManager.m
#	react-native-video.podspec
This commit is contained in:
Olgun Kaya
2021-06-15 15:42:07 +03:00
17 changed files with 785 additions and 54 deletions

View File

@@ -5,6 +5,7 @@
#import "RCTVideoPlayerViewControllerDelegate.h"
#import <React/RCTComponent.h>
#import <React/RCTBridgeModule.h>
@import GoogleInteractiveMediaAds;
#if __has_include(<react-native-video/RCTVideoCache.h>)
#import <react-native-video/RCTVideoCache.h>
@@ -14,11 +15,11 @@
@class RCTEventDispatcher;
#if __has_include(<react-native-video/RCTVideoCache.h>)
@interface RCTVideo : UIView <RCTVideoPlayerViewControllerDelegate, DVAssetLoaderDelegatesDelegate, AVAssetResourceLoaderDelegate>
@interface RCTVideo : UIView <RCTVideoPlayerViewControllerDelegate, DVAssetLoaderDelegatesDelegate, AVAssetResourceLoaderDelegate, IMAAdsLoaderDelegate, IMAAdsManagerDelegate>
#elif TARGET_OS_TV
@interface RCTVideo : UIView <RCTVideoPlayerViewControllerDelegate, AVAssetResourceLoaderDelegate>
#else
@interface RCTVideo : UIView <RCTVideoPlayerViewControllerDelegate, AVPictureInPictureControllerDelegate, AVAssetResourceLoaderDelegate>
@interface RCTVideo : UIView <RCTVideoPlayerViewControllerDelegate, AVPictureInPictureControllerDelegate, AVAssetResourceLoaderDelegate, IMAAdsLoaderDelegate, IMAAdsManagerDelegate>
#endif
@property (nonatomic, copy) RCTDirectEventBlock onVideoLoadStart;
@@ -55,6 +56,12 @@ typedef NS_ENUM(NSInteger, RCTVideoError) {
RCTVideoErrorNoFairplayDRM,
RCTVideoErrorNoDRMData
};
/// Playhead used by the SDK to track content video progress and insert mid-rolls.
@property(nonatomic, strong) IMAAVPlayerContentPlayhead *contentPlayhead;
/// Entry point for the SDK. Used to make ad requests.
@property(nonatomic, strong) IMAAdsLoader *adsLoader;
/// Main point of interaction with the SDK. Created by the SDK as the result of an ad request.
@property(nonatomic, strong) IMAAdsManager *adsManager;
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;

View File

@@ -45,6 +45,7 @@ static int const RCTVideoUnset = -1;
BOOL _playbackRateObserverRegistered;
BOOL _isExternalPlaybackActiveObserverRegistered;
BOOL _videoLoadStarted;
BOOL _isRequestAds;
bool _pendingSeek;
float _pendingSeekTime;
@@ -82,6 +83,7 @@ static int const RCTVideoUnset = -1;
NSString * _fullscreenOrientation;
BOOL _fullscreenPlayerPresented;
NSString *_filterName;
NSString * _adTagUrl;
BOOL _filterEnabled;
UIViewController * _presentingViewController;
#if __has_include(<react-native-video/RCTVideoCache.h>)
@@ -118,6 +120,7 @@ static int const RCTVideoUnset = -1;
_allowsExternalPlayback = YES;
_playWhenInactive = false;
_pictureInPicture = false;
_isRequestAds = false;
_ignoreSilentSwitch = @"inherit"; // inherit, ignore, obey
_mixWithOthers = @"inherit"; // inherit, mix, duck
#if TARGET_OS_IOS
@@ -152,14 +155,16 @@ static int const RCTVideoUnset = -1;
- (RCTVideoPlayerViewController*)createPlayerViewController:(AVPlayer*)player
withPlayerItem:(AVPlayerItem*)playerItem {
RCTVideoPlayerViewController* viewController = [[RCTVideoPlayerViewController alloc] init];
viewController.showsPlaybackControls = YES;
viewController.rctDelegate = self;
viewController.preferredOrientation = _fullscreenOrientation;
viewController.view.frame = self.bounds;
viewController.player = player;
return viewController;
RCTVideoPlayerViewController* viewController = [[RCTVideoPlayerViewController alloc] init];
viewController.showsPlaybackControls = YES;
viewController.rctDelegate = self;
viewController.preferredOrientation = _fullscreenOrientation;
self.contentPlayhead = [[IMAAVPlayerContentPlayhead alloc] initWithAVPlayer:player];
[self setupAdsLoader];
viewController.view.frame = self.bounds;
viewController.player = player;
return viewController;
}
/* ---------------------------------------------------------
@@ -280,8 +285,12 @@ static int const RCTVideoUnset = -1;
const Float64 currentTimeSecs = CMTimeGetSeconds(currentTime);
[[NSNotificationCenter defaultCenter] postNotificationName:@"RCTVideo_progress" object:nil userInfo:@{@"progress": [NSNumber numberWithDouble: currentTimeSecs / duration]}];
if( currentTimeSecs >= 0 && self.onVideoProgress) {
if(!_isRequestAds && currentTimeSecs >= 0.0001) {
[self requestAds];
_isRequestAds = true;
}
self.onVideoProgress(@{
@"currentTime": [NSNumber numberWithFloat:CMTimeGetSeconds(currentTime)],
@"playableDuration": [self calculatePlayableDuration],
@@ -694,7 +703,6 @@ static int const RCTVideoUnset = -1;
@"target": self.reactTag});
}
_videoLoadStarted = NO;
[self attachListeners];
[self applyModifiers];
} else if (_playerItem.status == AVPlayerItemStatusFailed && self.onVideoError) {
@@ -757,6 +765,74 @@ static int const RCTVideoUnset = -1;
}
}
- (void)setupAdsLoader {
// Re-use this IMAAdsLoader instance for the entire lifecycle of your app.
self.adsLoader = [[IMAAdsLoader alloc] initWithSettings:nil];
// NOTE: This line will cause a warning until the next step, "Get the Ads Manager".
self.adsLoader.delegate = self;
}
- (void)requestAds {
// Create an ad display container for ad rendering.
IMAAdDisplayContainer *adDisplayContainer =
[[IMAAdDisplayContainer alloc] initWithAdContainer:self companionSlots:nil];
// Create an ad request with our ad tag, display container, and optional user context.
IMAAdsRequest *request = [[IMAAdsRequest alloc] initWithAdTagUrl:_adTagUrl
adDisplayContainer:adDisplayContainer
contentPlayhead:self.contentPlayhead
userContext:nil];
[self.adsLoader requestAdsWithRequest:request];
}
#pragma mark AdsLoader Delegates
- (void)adsLoader:(IMAAdsLoader *)loader adsLoadedWithData:(IMAAdsLoadedData *)adsLoadedData {
// Grab the instance of the IMAAdsManager and set ourselves as the delegate.
self.adsManager = adsLoadedData.adsManager;
// NOTE: This line will cause a warning until the next step, "Display Ads".
self.adsManager.delegate = self;
// Create ads rendering settings and tell the SDK to use the in-app browser.
IMAAdsRenderingSettings *adsRenderingSettings = [[IMAAdsRenderingSettings alloc] init];
adsRenderingSettings.webOpenerPresentingController = _playerViewController;
// Initialize the ads manager.
[self.adsManager initializeWithAdsRenderingSettings:adsRenderingSettings];
}
- (void)adsLoader:(IMAAdsLoader *)loader failedWithErrorData:(IMAAdLoadingErrorData *)adErrorData {
// Something went wrong loading ads. Log the error and play the content.
NSLog(@"Error loading ads: %@", adErrorData.adError.message);
[_player play];
}
#pragma mark AdsManager Delegates
- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdEvent:(IMAAdEvent *)event {
if (event.type == kIMAAdEvent_LOADED) {
// When the SDK notifies us that ads have been loaded, play them.
[adsManager start];
}
}
- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdError:(IMAAdError *)error {
// Something went wrong with the ads manager after ads were loaded. Log the error and play the
// content.
NSLog(@"AdsManager error: %@", error.message);
[_player play];
}
- (void)adsManagerDidRequestContentPause:(IMAAdsManager *)adsManager {
// The SDK is going to play ads, so pause the content.
[_player pause];
}
- (void)adsManagerDidRequestContentResume:(IMAAdsManager *)adsManager {
// The SDK is done playing ads (at least for now), so resume the content.
[_player play];
}
- (void)attachListeners
{
// listen for end of file
@@ -824,6 +900,9 @@ static int const RCTVideoUnset = -1;
- (void)playerItemDidReachEnd:(NSNotification *)notification
{
if (notification.object == _player.currentItem) {
[self.adsLoader contentComplete];
}
if(self.onVideoEnd) {
self.onVideoEnd(@{@"target": self.reactTag});
}
@@ -1535,6 +1614,10 @@ static int const RCTVideoUnset = -1;
_filterEnabled = filterEnabled;
}
- (void)setAdTagUrl:(NSString *)adTagUrl {
_adTagUrl = adTagUrl;
}
#pragma mark - React View Management
- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex

View File

@@ -20,6 +20,7 @@ RCT_EXPORT_MODULE();
RCT_EXPORT_VIEW_PROPERTY(src, NSDictionary);
RCT_EXPORT_VIEW_PROPERTY(drm, NSDictionary);
RCT_EXPORT_VIEW_PROPERTY(adTagUrl, NSString);
RCT_EXPORT_VIEW_PROPERTY(maxBitRate, float);
RCT_EXPORT_VIEW_PROPERTY(resizeMode, NSString);
RCT_EXPORT_VIEW_PROPERTY(repeat, BOOL);