Skip to content

Commit

Permalink
ETPAND-9585: TrueX Integration (#60)
Browse files Browse the repository at this point in the history
* Add support for TrueX
  • Loading branch information
armands-malejevs authored Apr 13, 2023
1 parent 4046555 commit 780371b
Show file tree
Hide file tree
Showing 12 changed files with 4,873 additions and 16 deletions.
4 changes: 4 additions & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ android {
repositories {
// Remove this repository line after google releases to google() or mavenCentral()
maven { url "https://dl.google.com/android/maven2" }
maven { url "https://s3.amazonaws.com/android.truex.com/mobile/prod/maven/" }
}

dependencies {
Expand All @@ -43,6 +44,9 @@ dependencies {
implementation 'com.google.android.exoplayer:exoplayer-core:2.18.1'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.18.1'
implementation 'com.google.android.exoplayer:extension-ima:2.18.1'
implementation 'com.truex:TruexAdRenderer-Mobile:2.1.+'

compileOnly 'org.checkerframework:checker-qual:3.13.0'

// All support libs must use the same version
implementation "androidx.annotation:annotation:1.1.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.webkit.WebView;

import com.google.common.collect.ImmutableList;
import com.google.android.exoplayer2.C;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.brentvatne.exoplayer;

public interface PlaybackHandler {
void resumeStream();
void closeStream();
void displayLinearAds();
void handlePopup(String url);
}
113 changes: 97 additions & 16 deletions android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
import android.view.Display;
import android.view.View;
import android.view.Window;
import android.view.ViewGroup;
import android.view.Gravity;
import android.view.accessibility.CaptioningManager;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.util.DisplayMetrics;
import android.content.Intent;

import com.brentvatne.react.R;
import com.brentvatne.receiver.AudioBecomingNoisyReceiver;
Expand All @@ -38,7 +40,6 @@
import com.google.ads.interactivemedia.v3.api.AdErrorEvent;
import com.google.ads.interactivemedia.v3.api.AdsLoader;
import com.google.ads.interactivemedia.v3.api.AdsManagerLoadedEvent;
import com.google.ads.interactivemedia.v3.api.AdsManager;
import com.google.ads.interactivemedia.v3.api.AdEvent;
import com.google.ads.interactivemedia.v3.api.AdEvent.AdEventListener;
import com.google.ads.interactivemedia.v3.api.ImaSdkSettings;
Expand All @@ -49,7 +50,7 @@
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.drm.MediaDrmCallbackException;
import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
import com.google.android.exoplayer2.ext.ima.ImaAdsLoader;
import com.brentvatne.exoplayer.ext.ima.ImaAdsLoader;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackException;
Expand Down Expand Up @@ -135,16 +136,21 @@
import java.lang.Double;
import java.lang.reflect.Method;

import com.facebook.react.uimanager.util.ReactFindViewUtil;


import com.brentvatne.exoplayer.PlaybackHandler;

@SuppressLint("ViewConstructor")
public class ReactExoplayerView extends FrameLayout implements
AdEventListener,
AdsLoader.AdsLoadedListener,
LifecycleEventListener,
Player.Listener,
BandwidthMeter.EventListener,
BecomingNoisyListener,
AudioManager.OnAudioFocusChangeListener,
DrmSessionEventListener {
DrmSessionEventListener,
PlaybackHandler {

public static final double DEFAULT_MAX_HEAP_ALLOCATION_PERCENT = 1;
public static final double DEFAULT_MIN_BACK_BUFFER_MEMORY_RESERVE = 0;
Expand All @@ -170,15 +176,18 @@ public class ReactExoplayerView extends FrameLayout implements
private Player.Listener eventListener;
private MediaSourceEventListener mediaSourceEventListener;

private ExoPlayerView exoPlayerView;
private FrameLayout adOverlay;
private ImaAdsLoader adsLoader;
public ExoPlayerView exoPlayerView;
public static FrameLayout truexOverlayFrameLayout;
public ImaAdsLoader adsLoader;
private AdsLoader googleAdsLoader;
private TruexAdManager truexAdManager;
private FrameLayout truexViewGroup;
private ImaSdkSettings imaSettings;
private boolean shouldPlayAdBeforeStartPosition;
private AdsManager googleAdsManager;
private Ad activeAd;
private ArrayList<Double> adMarkers;
private boolean isAdsManagerListenerAdded = false;
private Timeline playerTimeline;

private DataSource.Factory mediaDataSourceFactory;
private ExoPlayer player;
Expand Down Expand Up @@ -221,6 +230,7 @@ public class ReactExoplayerView extends FrameLayout implements
private Uri srcUri;
private String extension;
private boolean isCSAIEnabled = false;
private boolean isTruexEnabled = false;
private String adTagUrl;
private boolean repeat;
private String audioTrackType;
Expand Down Expand Up @@ -337,7 +347,6 @@ private void createViews() {
LayoutParams.MATCH_PARENT);
exoPlayerView = new ExoPlayerView(getContext());
exoPlayerView.setLayoutParams(layoutParams);

// Add Exoplayer view
addView(exoPlayerView, 0, layoutParams);

Expand Down Expand Up @@ -390,20 +399,86 @@ private WritableMap getAdInfo() {
return data;
}

/**
* TrueX Playback Handlers
*/
@Override
public void resumeStream() {
if (player == null) {
return;
}

WritableMap payload = Arguments.createMap();
eventEmitter.adEvent("ENDED_TRUEX", payload);

adsLoader.discardAdBreak();
startPlayback();
}

@Override
public void closeStream() {
releasePlayer();
}

@Override
public void onAdsManagerLoaded(AdsManagerLoadedEvent event){
if (event == null) {
public void displayLinearAds() {
if (this.player == null) {
return;
}
googleAdsManager = event.getAdsManager();

WritableMap payload = Arguments.createMap();
eventEmitter.adEvent("ENDED_TRUEX", payload);

adsLoader.skipAd();
startPlayback();
}

@Override
public void handlePopup(String url) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
getContext().startActivity(browserIntent);
}

/**
* Display TrueX interactive Ad
*/
private void displayInteractiveAd(String vastUrl) {
if (player == null) {
return;
}
WritableMap payload = Arguments.createMap();
eventEmitter.adEvent("STARTED_TRUEX", payload);

// Pause the stream and display a true[X] engagement
Long position = player.getCurrentPosition();
if (position > 0) resumePosition = position;

// Start the true[X] engagement
ViewGroup viewGroup = (ViewGroup) truexOverlayFrameLayout;
truexAdManager = new TruexAdManager(getContext(), this);
truexAdManager.startAd(viewGroup, vastUrl);
}

public void handleCheckTruex(AdEvent event) {
if (activeAd == null) {
return;
}
boolean isTrueXAd = activeAd.getAdSystem().contains("trueX");
if (isTrueXAd && isTruexEnabled) {
String vastUrl = activeAd.getDescription();
displayInteractiveAd(vastUrl);
} else if (isTrueXAd && !isTruexEnabled) {
// Don't display interactive ads if TrueX is disabled
adsLoader.skipAd();
}
reLayout(exoPlayerView);
}

@Override
public void onAdEvent(AdEvent event) {
if (event == null || !isCSAIEnabled) {
return;
}

// Get ad data
activeAd = event.getAd();
WritableMap adInfo = getAdInfo();
Expand All @@ -414,16 +489,17 @@ public void onAdEvent(AdEvent event) {
AdEvent.AdEventType eventType = event.getType();
switch(eventType) {
case STARTED:
reLayout(exoPlayerView);
eventEmitter.adEvent("STARTED", payload);
handleCheckTruex(event);
break;
case CONTENT_RESUME_REQUESTED:
activeAd = null;
eventEmitter.adEvent("CONTENT_RESUME_REQUESTED", payload);
break;
case TAPPED:
eventEmitter.videoClickEvent();
}
break;
}
}

@Override
Expand Down Expand Up @@ -1074,6 +1150,7 @@ private void releasePlayer() {
adsLoader = null;
imaSettings = null;
shouldPlayAdBeforeStartPosition = true;
truexOverlayFrameLayout = null;
}
if (player != null) {
updateResumePosition();
Expand Down Expand Up @@ -1128,7 +1205,7 @@ private void setPlayWhenReady(boolean playWhenReady) {
}
}

private void startPlayback() {
public void startPlayback() {
if (player != null) {
switch (player.getPlaybackState()) {
case Player.STATE_IDLE:
Expand Down Expand Up @@ -2232,6 +2309,10 @@ public void setEnableCSAI(boolean isEnabled) {
this.isCSAIEnabled = isEnabled;
}

public void setEnableTruex(boolean isEnabled) {
this.isTruexEnabled = isEnabled;
}

public void setAdTagUrl(String url) {
this.adTagUrl = url;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
private static final String PROP_AD_INITIAL_PLAYBACK = "playAdBeforeStart";
private static final String PROP_AD_TAG_URL = "adTagUrl";
private static final String PROP_ENABLE_CSAI = "enableCSAI";
private static final String PROP_ENABLE_TRUEX = "enableTruex";
private static final String PROP_DRM = "drm";
private static final String PROP_DRM_TYPE = "type";
private static final String PROP_DRM_LICENSESERVER = "licenseServer";
Expand Down Expand Up @@ -157,6 +158,11 @@ public void setEnableCSAI(final ReactExoplayerView videoView, final boolean isEn
videoView.setEnableCSAI(isEnabled);
}

@ReactProp(name = PROP_ENABLE_TRUEX)
public void setEnableTruex(final ReactExoplayerView videoView, final boolean isEnabled) {
videoView.setEnableTruex(isEnabled);
}

@ReactProp(name = PROP_AD_TAG_URL)
public void setAdTagUrl(final ReactExoplayerView videoView, final String url) {
videoView.setAdTagUrl(url);
Expand Down
Loading

0 comments on commit 780371b

Please sign in to comment.