diff --git a/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/AppLovinIncentivizedAdListener.java b/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/AppLovinIncentivizedAdListener.java index d4e64c3d8..3583ca8d4 100644 --- a/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/AppLovinIncentivizedAdListener.java +++ b/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/AppLovinIncentivizedAdListener.java @@ -116,28 +116,4 @@ public void userRewardVerified(AppLovinAd ad, Map response) { ApplovinAdapter.log(DEBUG, "Rewarded " + amount + " " + currency); mRewardItem = new AppLovinRewardItem(amount, currency); } - - /** - * Reward item wrapper class. - */ - private static final class AppLovinRewardItem - implements RewardItem { - private final int mAmount; - private final String mType; - - private AppLovinRewardItem(int amount, final String type) { - mAmount = amount; - mType = type; - } - - @Override - public String getType() { - return mType; - } - - @Override - public int getAmount() { - return mAmount; - } - } } diff --git a/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/AppLovinRewardItem.java b/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/AppLovinRewardItem.java new file mode 100644 index 000000000..58176e445 --- /dev/null +++ b/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/AppLovinRewardItem.java @@ -0,0 +1,31 @@ +package com.applovin.mediation; + +import com.google.android.gms.ads.reward.RewardItem; + +/** + * Created by Thomas So on July 17 2018 + */ +public final class AppLovinRewardItem + implements RewardItem +{ + private final int mAmount; + private final String mType; + + public AppLovinRewardItem(int amount, String type) + { + mAmount = amount; + mType = type; + } + + @Override + public String getType() + { + return mType; + } + + @Override + public int getAmount() + { + return mAmount; + } +} diff --git a/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/AppLovinUtils.java b/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/AppLovinUtils.java index efb3d3b09..cf77728d7 100644 --- a/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/AppLovinUtils.java +++ b/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/AppLovinUtils.java @@ -4,18 +4,25 @@ import android.os.Bundle; import android.text.TextUtils; +import com.applovin.sdk.AppLovinAdSize; import com.applovin.sdk.AppLovinErrorCodes; import com.applovin.sdk.AppLovinMediationProvider; import com.applovin.sdk.AppLovinSdk; import com.applovin.sdk.AppLovinSdkSettings; +import com.applovin.sdk.BuildConfig; import com.google.android.gms.ads.AdRequest; +import com.google.android.gms.ads.AdSize; /* * A helper class used by {@link AppLovinAdapter}. */ -class AppLovinUtils { +public class AppLovinUtils +{ private static final String DEFAULT_ZONE = ""; + private static final int BANNER_STANDARD_HEIGHT = 50; + private static final int BANNER_HEIGHT_OFFSET_TOLERANCE = 10; + /** * Keys for retrieving values from the server parameters. */ @@ -29,8 +36,9 @@ private static class ServerParameterKeys { * Retrieves the appropriate instance of AppLovin's SDK from the SDK key given in the server * parameters, or Android Manifest. */ - static AppLovinSdk retrieveSdk(Bundle serverParameters, Context context) { - final String sdkKey = serverParameters.getString(ServerParameterKeys.SDK_KEY); + public static AppLovinSdk retrieveSdk(Bundle serverParameters, Context context) + { + final String sdkKey = (serverParameters != null) ? serverParameters.getString( ServerParameterKeys.SDK_KEY ) : null; final AppLovinSdk sdk; if (!TextUtils.isEmpty(sdkKey)) { @@ -73,14 +81,16 @@ static String retrieveZoneId(Bundle serverParameters) { /** * Retrieves whether or not to mute the ad that is about to be rendered. */ - static boolean shouldMuteAudio(Bundle networkExtras) { - return networkExtras != null && networkExtras.getBoolean(AppLovinExtras.Keys.MUTE_AUDIO); + public static boolean shouldMuteAudio(Bundle networkExtras) + { + return networkExtras != null && networkExtras.getBoolean( AppLovinExtras.Keys.MUTE_AUDIO ); } /** * Convert the given AppLovin SDK error code into the appropriate AdMob error code. */ - static int toAdMobErrorCode(int applovinErrorCode) { + public static int toAdMobErrorCode(int applovinErrorCode) + { // // TODO: Be more exhaustive // @@ -93,4 +103,35 @@ static int toAdMobErrorCode(int applovinErrorCode) { return AdRequest.ERROR_CODE_INTERNAL_ERROR; } } + + /** + * Get the {@link AppLovinAdSize} from a given {@link AdSize} from AdMob. + */ + public static AppLovinAdSize appLovinAdSizeFromAdMobAdSize(AdSize adSize) + { + final boolean isSmartBanner = ( adSize.getWidth() == AdSize.FULL_WIDTH ) && + ( adSize.getHeight() == AdSize.AUTO_HEIGHT ); + + if ( AdSize.BANNER.equals( adSize ) || AdSize.LARGE_BANNER.equals( adSize ) || isSmartBanner ) + { + return AppLovinAdSize.BANNER; + } + else if ( AdSize.MEDIUM_RECTANGLE.equals( adSize ) ) + { + return AppLovinAdSize.MREC; + } + else if ( AdSize.LEADERBOARD.equals( adSize ) ) + { + return AppLovinAdSize.LEADER; + } + + // Assume fluid width, and check for height with offset tolerance + final int offset = Math.abs( BANNER_STANDARD_HEIGHT - adSize.getHeight() ); + if ( offset <= BANNER_HEIGHT_OFFSET_TOLERANCE ) + { + return AppLovinAdSize.BANNER; + } + + return null; + } } diff --git a/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/ApplovinAdapter.java b/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/ApplovinAdapter.java index 9518c8dcb..7ec43fcab 100644 --- a/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/ApplovinAdapter.java +++ b/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/ApplovinAdapter.java @@ -43,10 +43,7 @@ public class ApplovinAdapter implements MediationBannerAdapter, MediationInterstitialAdapter, MediationRewardedVideoAdAdapter, OnContextChangedListener { private static final boolean LOGGING_ENABLED = true; - private static final String DEFAULT_ZONE = ""; - - private static final int BANNER_STANDARD_HEIGHT = 50; - private static final int BANNER_HEIGHT_OFFSET_TOLERANCE = 10; + private static final String DEFAULT_ZONE = ""; // Interstitial globals. private static final HashMap> INTERSTITIAL_AD_QUEUES = @@ -338,9 +335,10 @@ public void requestBannerAd(Context context, + mZoneId + " and placement: " + mPlacement); // Convert requested size to AppLovin Ad Size. - final AppLovinAdSize appLovinAdSize = appLovinAdSizeFromAdMobAdSize(adSize); - if (appLovinAdSize != null) { - mAdView = new AppLovinAdView(mSdk, appLovinAdSize, context); + final AppLovinAdSize appLovinAdSize = AppLovinUtils.appLovinAdSizeFromAdMobAdSize( adSize ); + if ( appLovinAdSize != null ) + { + mAdView = new AppLovinAdView( mSdk, appLovinAdSize, context ); final AppLovinBannerAdListener listener = new AppLovinBannerAdListener( mZoneId, mPlacement, mAdView, this, mediationBannerListener); @@ -372,27 +370,6 @@ public View getBannerView() { } //endregion - private AppLovinAdSize appLovinAdSizeFromAdMobAdSize(AdSize adSize) { - final boolean isSmartBanner = (adSize.getWidth() == AdSize.FULL_WIDTH) && - (adSize.getHeight() == AdSize.AUTO_HEIGHT); - - if (AdSize.BANNER.equals(adSize) || AdSize.LARGE_BANNER.equals(adSize) || isSmartBanner) { - return AppLovinAdSize.BANNER; - } else if (AdSize.MEDIUM_RECTANGLE.equals(adSize)) { - return AppLovinAdSize.MREC; - } else if (AdSize.LEADERBOARD.equals(adSize)) { - return AppLovinAdSize.LEADER; - } - - // Assume fluid width, and check for height with offset tolerance - final int offset = Math.abs( BANNER_STANDARD_HEIGHT - adSize.getHeight() ); - if (offset <= BANNER_HEIGHT_OFFSET_TOLERANCE) { - return AppLovinAdSize.BANNER; - } - - return null; - } - //region MediationAdapter. @Override public void onPause() { diff --git a/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/rtb/AppLovinRtbAdapter.java b/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/rtb/AppLovinRtbAdapter.java new file mode 100644 index 000000000..c74bf5873 --- /dev/null +++ b/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/rtb/AppLovinRtbAdapter.java @@ -0,0 +1,125 @@ +package com.applovin.mediation.rtb; + +import android.app.Application; +import android.text.TextUtils; +import android.util.Log; + +import com.applovin.mediation.AppLovinUtils; +import com.applovin.sdk.AppLovinSdk; +import com.google.ads.mediation.sample.adapter.BuildConfig; +import com.google.android.gms.ads.AdSize; +import com.google.android.gms.ads.mediation.rtb.AdRenderingCallback; +import com.google.android.gms.ads.mediation.rtb.BannerAd; +import com.google.android.gms.ads.mediation.rtb.BannerEventListener; +import com.google.android.gms.ads.mediation.rtb.InterstitialAd; +import com.google.android.gms.ads.mediation.rtb.InterstitialEventListener; +import com.google.android.gms.ads.mediation.rtb.RewardedAd; +import com.google.android.gms.ads.mediation.rtb.RewardedEventListener; +import com.google.android.gms.ads.mediation.rtb.RtbAdConfiguration; +import com.google.android.gms.ads.mediation.rtb.RtbAdapter; +import com.google.android.gms.ads.mediation.rtb.RtbConfiguration; +import com.google.android.gms.ads.mediation.rtb.RtbSignalData; +import com.google.android.gms.ads.mediation.rtb.SignalCallbacks; +import com.google.android.gms.ads.mediation.rtb.VersionInfo; + +import java.util.List; + +/** + * Created by Thomas So on July 17 2018 + */ +public class AppLovinRtbAdapter + extends RtbAdapter +{ + private static final String TAG = "AppLovinRtbAdapter"; + + // TODO: Why is this not in the base adapter?! + // @Override + // public void setUp() + // { + // AppLovinSdk.getInstance( new Application() ).initializeSdk(); + // } + + @Override + public void initialize() + { + AppLovinSdk.getInstance( new Application() ).initializeSdk(); + } + + @Override + public void updateConfiguration(final List list) + { + super.updateConfiguration( list ); + } + + @Override + public VersionInfo getSdkVersion() + { + String versionString = AppLovinSdk.VERSION; + String splits[] = versionString.split( "\\." ); + int major = Integer.parseInt( splits[0] ); + int minor = Integer.parseInt( splits[1] ); + int patch = Integer.parseInt( splits[2] ); + + return new VersionInfo( major, minor, patch ); + } + + @Override + public VersionInfo getAdapterVersion() + { + String versionString = BuildConfig.VERSION_NAME; + String splits[] = versionString.split( "\\." ); + int major = Integer.parseInt( splits[0] ); + int minor = Integer.parseInt( splits[1] ); + // Adapter versions have 2 patch versions. Multiply the first patch by 100. + int micro = Integer.parseInt( splits[2] ) * 100 + Integer.parseInt( splits[3] ); + + return new VersionInfo( major, minor, micro ); + } + + @Override + public void collectSignals(RtbSignalData rtbSignalData, SignalCallbacks signalCallbacks) + { + // TODO: I hope that we do not use the SDK Key and Context from here to initialize SDK / get bid token with... + // Check if the publisher provided extra parameters + if ( rtbSignalData.extras != null ) + { + Log.i( TAG, "Extras for signal collection: " + rtbSignalData.extras ); + } + + AppLovinSdk sdk = AppLovinUtils.retrieveSdk( rtbSignalData.extras, rtbSignalData.context ); + String bidToken = sdk.getAdService().getBidToken(); + + if ( !TextUtils.isEmpty( bidToken ) ) + { + Log.i( TAG, "Generated bid token: " + bidToken ); + signalCallbacks.onSuccess( bidToken ); + } + else + { + String errorMessage = "Failed to generate bid token"; + Log.e( TAG, errorMessage ); + signalCallbacks.onFailure( errorMessage ); + } + } + + @Override + public void renderBannerAd(RtbAdConfiguration adConfiguration, AdSize adSize, AdRenderingCallback callback) + { + AppLovinRtbBannerRenderer bannerRenderer = new AppLovinRtbBannerRenderer( adConfiguration, adSize, callback ); + bannerRenderer.loadAd(); + } + + @Override + public void renderInterstitialAd(RtbAdConfiguration adConfiguration, AdRenderingCallback callback) + { + AppLovinRtbInterstitialRenderer interstitialRenderer = new AppLovinRtbInterstitialRenderer( adConfiguration, callback ); + interstitialRenderer.loadAd(); + } + + @Override + public void renderRewardedAd(RtbAdConfiguration adConfiguration, AdRenderingCallback callback) + { + AppLovinRtbRewardedRenderer rewardedRenderer = new AppLovinRtbRewardedRenderer( adConfiguration, callback ); + rewardedRenderer.loadAd(); + } +} diff --git a/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/rtb/AppLovinRtbBannerRenderer.java b/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/rtb/AppLovinRtbBannerRenderer.java new file mode 100644 index 000000000..1d06e471f --- /dev/null +++ b/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/rtb/AppLovinRtbBannerRenderer.java @@ -0,0 +1,155 @@ +package com.applovin.mediation.rtb; + +import android.support.annotation.NonNull; +import android.util.Log; +import android.view.View; + +import com.applovin.adview.AppLovinAdView; +import com.applovin.adview.AppLovinAdViewDisplayErrorCode; +import com.applovin.adview.AppLovinAdViewEventListener; +import com.applovin.mediation.AppLovinUtils; +import com.applovin.sdk.AppLovinAd; +import com.applovin.sdk.AppLovinAdClickListener; +import com.applovin.sdk.AppLovinAdDisplayListener; +import com.applovin.sdk.AppLovinAdLoadListener; +import com.applovin.sdk.AppLovinAdSize; +import com.applovin.sdk.AppLovinSdk; +import com.google.android.gms.ads.AdSize; +import com.google.android.gms.ads.mediation.rtb.AdRenderingCallback; +import com.google.android.gms.ads.mediation.rtb.BannerAd; +import com.google.android.gms.ads.mediation.rtb.BannerEventListener; +import com.google.android.gms.ads.mediation.rtb.RtbAdConfiguration; + +/** + * Created by Thomas So on July 17 2018 + */ +public final class AppLovinRtbBannerRenderer + implements BannerAd, AppLovinAdLoadListener, AppLovinAdDisplayListener, AppLovinAdClickListener, AppLovinAdViewEventListener +{ + private static final String TAG = "AppLovinRtbBannerRenderer"; + + /** + * Data used to render an RTB banner ad. + */ + private final RtbAdConfiguration adConfiguration; + + /** + * Callback object to notify the Google Mobile Ads SDK if ad rendering succeeded or failed. + */ + private final AdRenderingCallback callback; + + /** + * Listener object to notify the Google Mobile Ads SDK of banner presentation events. + */ + private BannerEventListener listener; + + private final AppLovinSdk sdk; + private final AppLovinAdSize adSize; + private AppLovinAdView adView; + + public AppLovinRtbBannerRenderer(RtbAdConfiguration adConfiguration, + AdSize adSize, + AdRenderingCallback callback) + { + this.adConfiguration = adConfiguration; + this.callback = callback; + + // Convert requested size to AppLovin Ad Size. + this.adSize = AppLovinUtils.appLovinAdSizeFromAdMobAdSize( adSize ); + this.sdk = AppLovinUtils.retrieveSdk( adConfiguration.serverParameters, adConfiguration.context ); + } + + public void loadAd() + { + if ( adSize != null ) + { + // Create adview object + adView = new AppLovinAdView( sdk, adSize, adConfiguration.context ); + adView.setAdDisplayListener( this ); + adView.setAdClickListener( this ); + adView.setAdViewEventListener( this ); + + // Load ad! + sdk.getAdService().loadNextAdForAdToken( adConfiguration.bidResponse, this ); + } + else + { + callback.onFailure( "Failed to request banner with unsupported size" ); + } + } + + @NonNull + @Override + public View getView() + { + return adView; + } + + //region AppLovin Listeners + @Override + public void adReceived(AppLovinAd ad) + { + Log.d( TAG, "Banner did load ad: " + ad.getAdIdNumber() ); + + listener = callback.onSuccess( AppLovinRtbBannerRenderer.this ); + + adView.renderAd( ad ); + } + + @Override + public void failedToReceiveAd(int code) + { + Log.e( TAG, "Failed to load banner ad with error: " + code ); + + int admobErrorCode = AppLovinUtils.toAdMobErrorCode( code ); + callback.onFailure( Integer.toString( admobErrorCode ) ); + } + + @Override + public void adDisplayed(AppLovinAd ad) + { + Log.d( TAG, "Banner displayed" ); + listener.reportAdImpression(); + } + + @Override + public void adHidden(AppLovinAd ad) + { + Log.d( TAG, "Banner hidden" ); + } + + @Override + public void adClicked(AppLovinAd ad) + { + Log.d( TAG, "Banner clicked" ); + listener.reportAdClicked(); + } + + @Override + public void adOpenedFullscreen(AppLovinAd ad, AppLovinAdView adView) + { + Log.d( TAG, "Banner opened fullscreen" ); + listener.onAdOpened(); + } + + @Override + public void adClosedFullscreen(AppLovinAd ad, AppLovinAdView adView) + { + Log.d( TAG, "Banner closed fullscreen" ); + listener.onAdClosed(); + } + + @Override + public void adLeftApplication(AppLovinAd ad, AppLovinAdView adView) + { + Log.d( TAG, "Banner left application" ); + listener.onAdLeftApplication(); + } + + @Override + public void adFailedToDisplay(AppLovinAd ad, AppLovinAdView adView, AppLovinAdViewDisplayErrorCode code) + { + Log.e( TAG, "Banner failed to display: " + code ); + } + //endregion +} diff --git a/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/rtb/AppLovinRtbInterstitialRenderer.java b/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/rtb/AppLovinRtbInterstitialRenderer.java new file mode 100644 index 000000000..7096e4518 --- /dev/null +++ b/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/rtb/AppLovinRtbInterstitialRenderer.java @@ -0,0 +1,130 @@ +package com.applovin.mediation.rtb; + +import android.util.Log; + +import com.applovin.adview.AppLovinInterstitialAd; +import com.applovin.adview.AppLovinInterstitialAdDialog; +import com.applovin.mediation.AppLovinUtils; +import com.applovin.sdk.AppLovinAd; +import com.applovin.sdk.AppLovinAdClickListener; +import com.applovin.sdk.AppLovinAdDisplayListener; +import com.applovin.sdk.AppLovinAdLoadListener; +import com.applovin.sdk.AppLovinAdVideoPlaybackListener; +import com.applovin.sdk.AppLovinSdk; +import com.google.android.gms.ads.mediation.rtb.AdRenderingCallback; +import com.google.android.gms.ads.mediation.rtb.InterstitialAd; +import com.google.android.gms.ads.mediation.rtb.InterstitialEventListener; +import com.google.android.gms.ads.mediation.rtb.RtbAdConfiguration; + +/** + * Created by Thomas So on July 17 2018 + */ +public final class AppLovinRtbInterstitialRenderer + implements InterstitialAd, AppLovinAdLoadListener, AppLovinAdDisplayListener, AppLovinAdClickListener, AppLovinAdVideoPlaybackListener +{ + private static final String TAG = "AppLovinRtbInterstitialRenderer"; + + /** + * Data used to render an RTB interstitial ad. + */ + private final RtbAdConfiguration adConfiguration; + + /** + * Callback object to notify the Google Mobile Ads SDK if ad rendering succeeded or failed. + */ + private final AdRenderingCallback callback; + + /** + * Listener object to notify the Google Mobile Ads SDK of interstitial presentation events. + */ + private InterstitialEventListener listener; + + private final AppLovinSdk sdk; + private AppLovinInterstitialAdDialog interstitialAd; + private AppLovinAd ad; + + public AppLovinRtbInterstitialRenderer(RtbAdConfiguration adConfiguration, AdRenderingCallback callback) + { + this.adConfiguration = adConfiguration; + this.callback = callback; + + this.sdk = AppLovinUtils.retrieveSdk( adConfiguration.serverParameters, adConfiguration.context ); + } + + public void loadAd() + { + // Create interstitial object + interstitialAd = AppLovinInterstitialAd.create( sdk, adConfiguration.context ); + interstitialAd.setAdDisplayListener( this ); + interstitialAd.setAdClickListener( this ); + interstitialAd.setAdVideoPlaybackListener( this ); + + // Load ad! + sdk.getAdService().loadNextAdForAdToken( adConfiguration.bidResponse, this ); + } + + @Override + public void showAd() + { + // Update mute state + boolean muted = AppLovinUtils.shouldMuteAudio( adConfiguration.mediationExtras ); + sdk.getSettings().setMuted( muted ); + + interstitialAd.showAndRender( ad ); + } + + //region AppLovin Listeners + @Override + public void adReceived(AppLovinAd ad) + { + Log.d( TAG, "Interstitial did load ad: " + ad.getAdIdNumber() ); + + this.ad = ad; + + listener = callback.onSuccess( AppLovinRtbInterstitialRenderer.this ); + } + + @Override + public void failedToReceiveAd(int code) + { + Log.e( TAG, "Failed to load interstitial ad with error: " + code ); + + int admobErrorCode = AppLovinUtils.toAdMobErrorCode( code ); + callback.onFailure( Integer.toString( admobErrorCode ) ); + } + + @Override + public void adDisplayed(AppLovinAd ad) + { + Log.d( TAG, "Interstitial displayed" ); + listener.reportAdImpression(); + } + + @Override + public void adHidden(AppLovinAd ad) + { + Log.d( TAG, "Interstitial hidden" ); + listener.onAdClosed(); + } + + @Override + public void adClicked(AppLovinAd ad) + { + Log.d( TAG, "Interstitial clicked" ); + listener.reportAdClicked(); + listener.onAdLeftApplication(); + } + + @Override + public void videoPlaybackBegan(AppLovinAd ad) + { + Log.d( TAG, "Interstitial video playback began" ); + } + + @Override + public void videoPlaybackEnded(AppLovinAd ad, double percentViewed, boolean fullyWatched) + { + Log.d( TAG, "Interstitial video playback ended at playback percent: " + percentViewed + "%" ); + } + //endregion +} diff --git a/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/rtb/AppLovinRtbRewardedRenderer.java b/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/rtb/AppLovinRtbRewardedRenderer.java new file mode 100644 index 000000000..38e85f455 --- /dev/null +++ b/ThirdPartyAdapters/applovin/applovin/src/main/java/com/applovin/mediation/rtb/AppLovinRtbRewardedRenderer.java @@ -0,0 +1,183 @@ +package com.applovin.mediation.rtb; + +import android.util.Log; + +import com.applovin.adview.AppLovinIncentivizedInterstitial; +import com.applovin.mediation.AppLovinRewardItem; +import com.applovin.mediation.AppLovinUtils; +import com.applovin.sdk.AppLovinAd; +import com.applovin.sdk.AppLovinAdClickListener; +import com.applovin.sdk.AppLovinAdDisplayListener; +import com.applovin.sdk.AppLovinAdLoadListener; +import com.applovin.sdk.AppLovinAdRewardListener; +import com.applovin.sdk.AppLovinAdVideoPlaybackListener; +import com.applovin.sdk.AppLovinSdk; +import com.google.android.gms.ads.mediation.rtb.AdRenderingCallback; +import com.google.android.gms.ads.mediation.rtb.RewardedAd; +import com.google.android.gms.ads.mediation.rtb.RewardedEventListener; +import com.google.android.gms.ads.mediation.rtb.RtbAdConfiguration; + +import java.util.Map; + +/** + * Created by Thomas So on July 17 2018 + */ +public final class AppLovinRtbRewardedRenderer + implements RewardedAd, AppLovinAdLoadListener, AppLovinAdDisplayListener, AppLovinAdClickListener, AppLovinAdVideoPlaybackListener, AppLovinAdRewardListener +{ + private static final String TAG = "AppLovinRtbRewardedRenderer"; + + /** + * Data used to render an RTB rewarded ad. + */ + private RtbAdConfiguration adConfiguration; + + /** + * Callback object to notify the Google Mobile Ads SDK if ad rendering succeeded or failed. + */ + private final AdRenderingCallback callback; + + /** + * Listener object to notify the Google Mobile Ads SDK of rewarded presentation events. + */ + private RewardedEventListener listener; + + private final AppLovinSdk sdk; + private AppLovinIncentivizedInterstitial incentivizedInterstitial; + private AppLovinAd ad; + private boolean fullyWatched; + private AppLovinRewardItem rewardItem; + + public AppLovinRtbRewardedRenderer(RtbAdConfiguration adConfiguration, AdRenderingCallback callback) + { + this.adConfiguration = adConfiguration; + this.callback = callback; + + this.sdk = AppLovinUtils.retrieveSdk( adConfiguration.serverParameters, adConfiguration.context ); + } + + public void loadAd() + { + // Create rewarded video object + incentivizedInterstitial = AppLovinIncentivizedInterstitial.create( sdk ); + + // Load ad! + sdk.getAdService().loadNextAdForAdToken( adConfiguration.bidResponse, this ); + } + + @Override + public void showAd() + { + // Update mute state + boolean muted = AppLovinUtils.shouldMuteAudio( adConfiguration.mediationExtras ); + sdk.getSettings().setMuted( muted ); + + incentivizedInterstitial.show( ad, adConfiguration.context, this, this, this, this ); + } + + //region AppLovin Listeners + @Override + public void adReceived(AppLovinAd ad) + { + Log.d( TAG, "Rewarded video did load ad: " + ad.getAdIdNumber() ); + + this.ad = ad; + + listener = callback.onSuccess( AppLovinRtbRewardedRenderer.this ); + } + + @Override + public void failedToReceiveAd(int code) + { + Log.e( TAG, "Failed to load rewarded video with error: " + code ); + + int admobErrorCode = AppLovinUtils.toAdMobErrorCode( code ); + callback.onFailure( Integer.toString( admobErrorCode ) ); + } + + @Override + public void adDisplayed(AppLovinAd ad) + { + Log.d( TAG, "Rewarded video displayed" ); + listener.reportAdImpression(); + } + + @Override + public void adHidden(AppLovinAd ad) + { + Log.d( TAG, "Rewarded video hidden" ); + + if ( fullyWatched && rewardItem != null ) + { + listener.onRewarded( rewardItem ); + } + + listener.onAdClosed(); + + // Clear states in the case this listener gets re-used in the future. + fullyWatched = false; + rewardItem = null; + } + + @Override + public void adClicked(AppLovinAd ad) + { + Log.d( TAG, "Rewarded video clicked" ); + listener.reportAdClicked(); + listener.onAdLeftApplication(); + } + + @Override + public void videoPlaybackBegan(AppLovinAd ad) + { + Log.d( TAG, "Rewarded video playback began" ); + listener.onVideoStarted(); + } + + @Override + public void videoPlaybackEnded(AppLovinAd ad, double percentViewed, boolean fullyWatched) + { + Log.d( TAG, "Rewarded video playback ended at playback percent: " + percentViewed + "%" ); + listener.onVideoCompleted(); + } + //endregion + + //region AppLovin Reward Listener + @Override + public void userOverQuota(AppLovinAd ad, Map response) + { + Log.e( TAG, "Rewarded video validation request for ad did exceed quota with response: " + response ); + } + + @Override + public void validationRequestFailed(AppLovinAd ad, int code) + { + Log.e( TAG, "Rewarded video validation request for ad failed with error code: " + code ); + } + + @Override + public void userRewardRejected(AppLovinAd ad, Map response) + { + Log.e( TAG, "Rewarded video validation request was rejected with response: " + response ); + } + + @Override + public void userDeclinedToViewAd(AppLovinAd ad) + { + Log.e( TAG, "User declined to view rewarded video" ); + } + + @Override + public void userRewardVerified(AppLovinAd ad, Map response) + { + final String currency = response.get( "currency" ); + final String amountStr = response.get( "amount" ); + + // AppLovin returns amount as double. + final int amount = (int) Double.parseDouble( amountStr ); + + Log.d( TAG, "Rewarded " + amount + " " + currency ); + rewardItem = new AppLovinRewardItem( amount, currency ); + } + //endregion +}