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

[WIP] Enable Google IMA Preroll #1

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 6 additions & 5 deletions packages/brightcove-video/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ android {
}

repositories {
maven {
url "http://repo.brightcove.com/releases"
}
maven { url "http://repo.brightcove.com/releases" }
maven { url "https://maven.google.com" }
}

dependencies {
implementation "com.facebook.react:react-native:0.50.+"
api "com.brightcove.player:exoplayer:5.2.0"
implementation "com.facebook.react:react-native:+"
api "com.brightcove.player:exoplayer:6.0.1"
api "com.brightcove.player:android-ima-plugin:6.0.1"
api "com.google.ads.interactivemedia.v3:interactivemedia:3.+"
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package uk.co.news.rntbrightcovevideo;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Color;
import android.support.annotation.NonNull;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;

import com.brightcove.ima.GoogleIMAComponent;
import com.brightcove.ima.GoogleIMAEventType;

import com.brightcove.player.edge.Catalog;
import com.brightcove.player.edge.VideoListener;
import com.brightcove.player.event.Event;
Expand All @@ -17,13 +22,19 @@
import com.brightcove.player.model.Video;
import com.brightcove.player.view.BrightcoveExoPlayerVideoView;

import com.google.ads.interactivemedia.v3.api.AdDisplayContainer;
import com.google.ads.interactivemedia.v3.api.AdsManager;
import com.google.ads.interactivemedia.v3.api.AdsRequest;
import com.google.ads.interactivemedia.v3.api.ImaSdkFactory;

public class BrightcovePlayerView extends BrightcoveExoPlayerVideoView {

public static final String TAG = BrightcovePlayerView.class.getSimpleName();

private Boolean mAutoplay;
private Boolean mIsPlaying = false;
private Boolean mIsFullscreen = false;
private GoogleIMAComponent googleIMAComponent;
private float mProgress = 0;

public BrightcovePlayerView(final Context context) {
Expand Down Expand Up @@ -98,13 +109,15 @@ private void bubbleState(Boolean isPlaying, int headPos) {
}
}

public void initVideo(String videoId, String accountId, String policyKey, Boolean autoplay, Boolean isFullscreenButtonHidden) {
public void initVideo(String videoId, String accountId, String policyKey, Boolean autoplay, Boolean isFullscreenButtonHidden, String vastTag) {
View fullScreenButton = this.findViewById(com.brightcove.player.R.id.full_screen);
fullScreenButton.setVisibility(isFullscreenButtonHidden ? View.GONE : View.VISIBLE);

mAutoplay = autoplay;
Log.i(TAG, "INIT");

EventEmitter eventEmitter = setupEventEmitter();
// setupGoogleIMA(vastTag, eventEmitter);

Catalog catalog = new Catalog(eventEmitter, accountId, policyKey);
catalog.findVideoByID(videoId, createVideoListener());
Expand Down Expand Up @@ -175,4 +188,74 @@ public float getPlayheadPosition() {
return playheadPosition;
}

/**
* Setup the Brightcove IMA Plugin.
*/
private void setupGoogleIMA(final String adRulesURL, final EventEmitter eventEmitter) {
Log.i(TAG, "SETUP");

// Establish the Google IMA SDK factory instance.
final ImaSdkFactory sdkFactory = ImaSdkFactory.getInstance();

// Enable logging up ad start.
eventEmitter.on(EventType.AD_STARTED, new EventListener() {
@Override
public void processEvent(Event event) {
Log.v(TAG, event.getType());
Log.i(TAG, "STARTED");
}
});

// Enable logging any failed attempts to play an ad.
eventEmitter.on(GoogleIMAEventType.DID_FAIL_TO_PLAY_AD, new EventListener() {
@Override
public void processEvent(Event event) {
Log.i(TAG, "FAILED");
Log.v(TAG, event.getType());
}
});

// Enable Logging upon ad completion.
eventEmitter.on(EventType.AD_COMPLETED, new EventListener() {
@Override
public void processEvent(Event event) {
Log.v(TAG, event.getType());
Log.i(TAG, "COMPLETED");
}
});

final BrightcoveExoPlayerVideoView playerView = this;

// Set up a listener for initializing AdsRequests. The Google
// IMA plugin emits an ad request event as a result of
// initializeAdsRequests() being called.
eventEmitter.on(GoogleIMAEventType.ADS_REQUEST_FOR_VIDEO, new EventListener() {
@Override
public void processEvent(Event event) {
Log.i(TAG, "VIDEO REQUEST");
// Create a container object for the ads to be presented.
AdDisplayContainer container = sdkFactory.createAdDisplayContainer();
container.setPlayer(googleIMAComponent.getVideoAdPlayer());
container.setAdContainer(playerView);

// Build an ads request object and point it to the ad
// display container created above.
AdsRequest adsRequest = sdkFactory.createAdsRequest();
adsRequest.setAdTagUrl(adRulesURL);
adsRequest.setAdDisplayContainer(container);

ArrayList<AdsRequest> adsRequests = new ArrayList<AdsRequest>(1);
adsRequests.add(adsRequest);

// Respond to the event with the new ad requests.
event.properties.put(GoogleIMAComponent.ADS_REQUESTS, adsRequests);
eventEmitter.respond(event);
}
});

// Create the Brightcove IMA Plugin and pass in the event
// emitter so that the plugin can integrate with the SDK.
googleIMAComponent = new GoogleIMAComponent(playerView, eventEmitter, true);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ public void setHideFullScreenButton(RNTBrightcoveView view, Boolean hideFullScre
view.setHideFullScreenButton(hideFullScreenButton);
}

@ReactProp(name = "vastTag")
public void setVastTag(RNTBrightcoveView view, String vastTag) {
view.setVastTag(vastTag);
}

@Override
public void receiveCommand(RNTBrightcoveView view, int commandId, @Nullable ReadableArray args) {
switch (commandId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class RNTBrightcoveView extends FrameLayout {
private String mVideoId;
private String mAccountId;
private String mPolicyKey;
private String mVastTag;
private Boolean mAutoplay;
private Boolean mHideFullScreenButton;
private BrightcovePlayerView mPlayerView;
Expand Down Expand Up @@ -55,6 +56,13 @@ public void setVideoId(final String videoId) {
}
}

public void setVastTag(final String vastTag) {
if (mVastTag == null) {
mVastTag = vastTag;
initPlayerView();
}
}

public void setAccountId(final String accountId) {
if (mAccountId == null) {
mAccountId = accountId;
Expand Down Expand Up @@ -92,7 +100,8 @@ private void initPlayerView() {
addView(mPlayerView);

boolean isFullscreenButtonHidden = mHideFullScreenButton != null ? mHideFullScreenButton : false;
mPlayerView.initVideo(mVideoId, mAccountId, mPolicyKey, mAutoplay, isFullscreenButtonHidden);
mPlayerView.initVideo(mVideoId, mAccountId, mPolicyKey, mAutoplay, isFullscreenButtonHidden, mVastTag);
// mPlayerView.initVideo(mVideoId, mAccountId, mPolicyKey, mAutoplay, isFullscreenButtonHidden);
}
}

Expand Down Expand Up @@ -137,6 +146,7 @@ public void emitError(Event e) {
}

private boolean parametersSet() {
return mVideoId != null && mAccountId != null && mPolicyKey != null && mAutoplay != null && mHideFullScreenButton != null;
// return mVideoId != null && mAccountId != null && mPolicyKey != null && mAutoplay != null && mHideFullScreenButton != null;
return mVideoId != null && mAccountId != null && mPolicyKey != null && mAutoplay != null && mHideFullScreenButton != null && mVastTag != null;
}
}
1 change: 1 addition & 0 deletions packages/brightcove-video/brightcove-player.defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export default {
width: 320,
height: 180,
playerId: "default",
vastTag: null,
onError: () => {},
onPlay: () => {},
onPause: () => {},
Expand Down
1 change: 1 addition & 0 deletions packages/brightcove-video/brightcove-player.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ class BrightcoveVideo extends Component {
zIndex: this.props.zIndex
}}
policyKey={this.props.policyKey}
vastTag={this.props.vastTag}
accountId={this.props.accountId}
videoId={this.props.videoId}
autoplay={this.props.autoplay}
Expand Down
1 change: 1 addition & 0 deletions packages/brightcove-video/brightcove-player.proptypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const numberOrString = PropTypes.oneOfType([
export default {
videoId: PropTypes.string.isRequired,
accountId: PropTypes.string.isRequired,
vastTag: PropTypes.string.isRequired,
policyKey: PropTypes.string,
playerId: PropTypes.string,
width: numberOrString,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,8 @@
"$(SRCROOT)/../../../../ios/Pods/Headers/Public/Brightcove-Player-Core",
"$(SRCROOT)/../../../../React/**",
"$(SRCROOT)/../../../react-native/React/**",
"$(SRCROOT)/../../../../ios/Pods/Headers/Public/Brightcove-Player-IMA",
"$(SRCROOT)/../../../../ios/Pods/Headers/Public/GoogleAds-IMA-iOS-SDK",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC";
Expand All @@ -309,6 +311,8 @@
"$(SRCROOT)/../../../../ios/Pods/Headers/Public/Brightcove-Player-Core",
"$(SRCROOT)/../../../../React/**",
"$(SRCROOT)/../../../react-native/React/**",
"$(SRCROOT)/../../../../ios/Pods/Headers/Public/Brightcove-Player-IMA",
"$(SRCROOT)/../../../../ios/Pods/Headers/Public/GoogleAds-IMA-iOS-SDK",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@implementation RNTBrightcoveManager

RCT_EXPORT_MODULE();
RCT_EXPORT_VIEW_PROPERTY(vastTag, NSString);
RCT_EXPORT_VIEW_PROPERTY(policyKey, NSString);
RCT_EXPORT_VIEW_PROPERTY(accountId, NSString);
RCT_EXPORT_VIEW_PROPERTY(videoId, NSString);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
#import <React/RCTEventDispatcher.h>
#import <React/RCTView.h>
#import <BrightcovePlayerSDK/BrightcovePlayerSDK.h>
#import <BrightcoveIMA/BrightcoveIMA.h>
#import <GoogleInteractiveMediaAds/GoogleInteractiveMediaAds.h>

@class RCTEventDispatcher;

@interface RNTBrightcoveView : UIView

@property (nonatomic, copy) NSString *policyKey;
@property (nonatomic, copy) NSString *vastTag;
@property (nonatomic, copy) NSString *accountId;
@property (nonatomic, copy) NSString *videoId;
@property (nonatomic, assign) BOOL autoplay;
Expand Down
71 changes: 46 additions & 25 deletions packages/brightcove-video/ios/RNTBrightcove/RNTBrightcoveView.m
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,6 @@ - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher {
return self;
}

- (void)setup {
_isPlaying = NO;
_progress = 0;
_isFinished = NO;

BCOVPlayerSDKManager *manager = [BCOVPlayerSDKManager sharedManager];

_playbackController = [manager createPlaybackController];
_playbackController.delegate = self;
_playbackController.autoAdvance = YES;
_playbackController.autoPlay = [_autoplayNumber boolValue];

_playbackService = [[BCOVPlaybackService alloc] initWithAccountId:_accountId
policyKey:_policyKey];
}

- (void)requestContentFromPlaybackService {
[self.playbackService findVideoWithVideoID:_videoId parameters:nil completion:^(BCOVVideo *video, NSDictionary *jsonResponse, NSError *error) {
#pragma unused (jsonResponse)
Expand All @@ -83,12 +67,18 @@ - (void)layoutSubviews {

- (void)removeFromSuperview {
_eventDispatcher = nil;
for (UIView *subView in self.subviews)
{
[subView removeFromSuperview];
}
[super removeFromSuperview];
}

- (void)initPlayerView {
if (_policyKey && _accountId && _videoId && _autoplayNumber && _hideFullScreenButtonNumber) {
[self setup];
if (_policyKey && _accountId && _videoId && _autoplayNumber && _hideFullScreenButtonNumber && _vastTag) {
_isPlaying = NO;
_progress = 0;
_isFinished = NO;

BCOVPUIBasicControlView *controlsView = [BCOVPUIBasicControlView basicControlViewWithVODLayout];
controlsView.playbackButton.accessibilityIdentifier = @"play";
Expand All @@ -101,15 +91,39 @@ - (void)initPlayerView {

BCOVPUIPlayerViewOptions *options = [[BCOVPUIPlayerViewOptions alloc] init];

options.presentingViewController = [self fullscreenViewController];

BCOVPUIPlayerView *playerView = [[BCOVPUIPlayerView alloc] initWithPlaybackController:self.playbackController options:options controlsView:controlsView ];
BCOVPUIPlayerView *playerView = [[BCOVPUIPlayerView alloc] initWithPlaybackController:nil options:options controlsView:controlsView ];
playerView.delegate = self;

playerView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;

_playerView = playerView;
_playerView.playbackController = _playbackController;

// IMA setup start
IMASettings *imaSettings = [[IMASettings alloc] init];
imaSettings.language = @"fr-CA";

IMAAdsRenderingSettings *renderSettings = [[IMAAdsRenderingSettings alloc] init];
renderSettings.webOpenerPresentingController = nil;

BCOVIMAAdsRequestPolicy *adsRequestPolicy = [BCOVIMAAdsRequestPolicy adsRequestPolicyWithVMAPAdTagUrl:_vastTag];

BCOVPlayerSDKManager *manager = [BCOVPlayerSDKManager sharedManager];
_playbackController =
[manager createIMAPlaybackControllerWithSettings:imaSettings
adsRenderingSettings:renderSettings
adsRequestPolicy:adsRequestPolicy
adContainer:playerView
companionSlots:nil
viewStrategy:nil];

_playbackController.delegate = self;
_playbackController.autoAdvance = YES;
_playbackController.autoPlay = [_autoplayNumber boolValue];
self.playerView.playbackController = self.playbackController;

_playbackService = [[BCOVPlaybackService alloc] initWithAccountId:_accountId
policyKey:_policyKey];
// IMA setup end

[self requestContentFromPlaybackService];
}
Expand All @@ -122,6 +136,13 @@ - (void)setPolicyKey:(NSString *)policyKey {
}
}

- (void)setVASTTag:(NSString *)vastTag {
if (![vastTag isEqual:_vastTag]) {
_vastTag = vastTag;
[self initPlayerView];
}
}

- (void)setAccountId:(NSString *)accountId {
if (![accountId isEqual:_accountId]) {
_accountId = accountId;
Expand Down Expand Up @@ -228,16 +249,16 @@ - (UIViewController *)rootViewController{
}

- (RNTFullscreenPresentingAutoRotatingViewController *)fullscreenViewController {

if (_fullscreenViewController) {
return _fullscreenViewController;
}

RNTFullscreenPresentingAutoRotatingViewController* vc = [RNTFullscreenPresentingAutoRotatingViewController new];
vc.viewControllerToPresentFrom = [self rootViewController];

_fullscreenViewController = vc;

return _fullscreenViewController;

}
Expand Down