Android
Including the AppLovin MAX Adapter for Android into your app
Ensure that Maven Central is included in your repositories:
repositories {
// [... other project repos]
mavenCentral()
}
Update your dependencies to include the latest MobileFuse AppLovin Adapter:
dependencies {
// [... other project dependencies]
implementation 'com.mobilefuse.sdk:mobilefuse-adapter-applovin:<<adapterVersionAppLovinAndroid>>'
}
Adapter source code
For reference purposes, the MobileFuse MAX adapter source code is below:
package com.applovin.mediation.adapters;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.Nullable;
import com.applovin.mediation.MaxAdFormat;
import com.applovin.mediation.MaxReward;
import com.applovin.mediation.adapter.MaxAdViewAdapter;
import com.applovin.mediation.adapter.MaxAdapterError;
import com.applovin.mediation.adapter.MaxInterstitialAdapter;
import com.applovin.mediation.adapter.MaxRewardedAdapter;
import com.applovin.mediation.adapter.MaxSignalProvider;
import com.applovin.mediation.adapter.listeners.MaxAdViewAdapterListener;
import com.applovin.mediation.adapter.listeners.MaxInterstitialAdapterListener;
import com.applovin.mediation.adapter.listeners.MaxRewardedAdapterListener;
import com.applovin.mediation.adapter.listeners.MaxSignalCollectionListener;
import com.applovin.mediation.adapter.parameters.MaxAdapterInitializationParameters;
import com.applovin.mediation.adapter.parameters.MaxAdapterParameters;
import com.applovin.mediation.adapter.parameters.MaxAdapterResponseParameters;
import com.applovin.mediation.adapter.parameters.MaxAdapterSignalCollectionParameters;
import com.applovin.sdk.AppLovinSdk;
import com.applovin.sdk.AppLovinSdkConfiguration;
import com.applovin.sdk.AppLovinSdkUtils;
import com.mobilefuse.adapter.applovin.BuildConfig;
import com.mobilefuse.sdk.AdError;
import com.mobilefuse.sdk.MobileFuse;
import com.mobilefuse.sdk.MobileFuseBannerAd;
import com.mobilefuse.sdk.MobileFuseInterstitialAd;
import com.mobilefuse.sdk.MobileFuseRewardedAd;
import com.mobilefuse.sdk.SdkInitListener;
import com.mobilefuse.sdk.internal.MobileFuseBiddingTokenProvider;
import com.mobilefuse.sdk.internal.MobileFuseBiddingTokenRequest;
import com.mobilefuse.sdk.internal.TokenGeneratorListener;
import com.mobilefuse.sdk.privacy.MobileFusePrivacyPreferences;
import java.lang.reflect.Method;
import java.util.concurrent.atomic.AtomicBoolean;
public class MobileFuseMediationAdapter
extends MediationAdapterBase
implements MaxAdViewAdapter, MaxInterstitialAdapter, MaxRewardedAdapter, MaxSignalProvider
{
// Server parameters
private static final String PARAM_NAME_APP_KEY = "app_id";
private static final String PARAM_NAME_CUSTOM_PARAMS_JSON = "custom_parameters";
private static final String PARAM_NAME_BG_COLOR = "background_color";
private static final String PARAM_NAME_INITIALLY_MUTED = "initially_muted";
// State
private static final AtomicBoolean initialized = new AtomicBoolean();
// Ad objects
private MobileFuseBannerAd bannerAd;
private MobileFuseInterstitialAd interstitialAd;
private MobileFuseRewardedAd rewardedAd;
public MobileFuseMediationAdapter(AppLovinSdk appLovinSdk)
{
super( appLovinSdk );
log( "Create MobileFuse MAX adapter." );
}
@Override
public void initialize(MaxAdapterInitializationParameters parameters, Activity activity, OnCompletionListener onCompletionListener)
{
log( "Initializing SDK..." );
if ( initialized.get() )
{
log( "SDK is already initialized" );
onCompletionListener.onCompletion( InitializationStatus.INITIALIZED_SUCCESS, null );
return;
}
Bundle serverParameters = parameters.getServerParameters();
final String appKey = serverParameters.getString( PARAM_NAME_APP_KEY, null );
if ( appKey == null || appKey.isEmpty() )
{
log( "No app key is set for initialization, running with bidding support only" );
onCompletionListener.onCompletion( InitializationStatus.INITIALIZED_SUCCESS, null );
return;
}
SdkInitListener listener = new SdkInitListener()
{
@Override
public void onInitSuccess()
{
log( "MobileFuse SDK initialized" );
initialized.set( true );
onCompletionListener.onCompletion( InitializationStatus.INITIALIZED_SUCCESS, null );
}
@Override
public void onInitError()
{
log( "MobileFuse SDK failed to initialize" );
onCompletionListener.onCompletion( InitializationStatus.INITIALIZED_FAILURE, "failed to initialize MobileFuse sdk" );
}
};
log( "Initializing MobileFuse SDK with App Key: '" + appKey + "'..." );
MobileFuse.init( obtainApplicationContext( activity ), appKey, listener );
}
@Override
public String getSdkVersion()
{
return MobileFuse.getSdkVersion();
}
@Override
public String getAdapterVersion()
{
return BuildConfig.VERSION_NAME;
}
@Override
public void onDestroy()
{
log( "Destroying adapter" );
if ( bannerAd != null )
{
bannerAd.destroy();
bannerAd = null;
}
interstitialAd = null;
rewardedAd = null;
}
//region MAX Signal Provider Methods
@Override
public void collectSignal(MaxAdapterSignalCollectionParameters parameters, Activity activity, MaxSignalCollectionListener callback)
{
try
{
Context context = getContext( activity );
MobileFuseBiddingTokenRequest tokenRequest = getBiddingTokenRequest( parameters );
MobileFuseBiddingTokenProvider.getToken(
tokenRequest,
context,
new TokenGeneratorListener()
{
@Override
public void onTokenGenerated(String token)
{
callback.onSignalCollected( token );
}
@Override
public void onTokenGenerationFailed(String error)
{
callback.onSignalCollectionFailed( error );
}
}
);
}
catch ( Throwable e )
{
callback.onSignalCollectionFailed( "Failed to generate bidding token with internal error " + e );
}
}
//endregion
//region MAX Interstitial Adapter Methods
@Override
public void loadInterstitialAd(MaxAdapterResponseParameters parameters, Activity activity, MaxInterstitialAdapterListener listener)
{
String bidResponse = parameters.getBidResponse();
boolean isBidding = AppLovinSdkUtils.isValidString( bidResponse );
String placementId = parameters.getThirdPartyAdPlacementId();
log( "Loading " + (isBidding ? "bidding " : "") + "interstitial ad for placement: '" + placementId + "'..." );
interstitialAd = new MobileFuseInterstitialAd( activity, placementId );
interstitialAd.setListener( createMobileFuseAdListener( listener ) );
if ( isBidding )
{
interstitialAd.loadAdFromBiddingToken( bidResponse );
}
else
{
interstitialAd.loadAd();
}
}
@Override
public void showInterstitialAd(MaxAdapterResponseParameters parameters, Activity activity, MaxInterstitialAdapterListener listener)
{
log( "Showing interstitial ad: '" + parameters.getThirdPartyAdPlacementId() + "'..." );
if ( interstitialAd == null || !interstitialAd.isLoaded() )
{
log( "Unable to show interstitial - no ad loaded" );
listener.onInterstitialAdDisplayFailed( MaxAdapterError.AD_NOT_READY );
return;
}
interstitialAd.showAd();
}
//endregion
//region MAX Rewarded Adapter Methods
@Override
public void loadRewardedAd(MaxAdapterResponseParameters parameters, Activity activity, MaxRewardedAdapterListener listener)
{
String bidResponse = parameters.getBidResponse();
boolean isBidding = AppLovinSdkUtils.isValidString( bidResponse );
String placementId = parameters.getThirdPartyAdPlacementId();
log( "Loading " + (isBidding ? "bidding " : "") + "interstitial ad for placement: '" + placementId + "'..." );
rewardedAd = new MobileFuseRewardedAd( activity, placementId );
rewardedAd.setListener( createMobileFuseAdListener( listener ) );
if ( isBidding )
{
rewardedAd.loadAdFromBiddingToken( bidResponse );
}
else
{
rewardedAd.loadAd();
}
}
@Override
public void showRewardedAd(MaxAdapterResponseParameters parameters, Activity activity, MaxRewardedAdapterListener listener)
{
log( "Showing rewarded ad: '" + parameters.getThirdPartyAdPlacementId() + "'..." );
if ( rewardedAd == null || !rewardedAd.isLoaded() )
{
log( "Unable to show rewarded ad - no ad loaded" );
listener.onRewardedAdDisplayFailed( MaxAdapterError.AD_NOT_READY );
return;
}
rewardedAd.showAd();
}
//endregion
//region MAX Ad View Adapter Methods
@Override
public void loadAdViewAd(MaxAdapterResponseParameters parameters, MaxAdFormat adFormat, Activity activity, MaxAdViewAdapterListener listener)
{
String bidResponse = parameters.getBidResponse();
boolean isBidding = AppLovinSdkUtils.isValidString( bidResponse );
String placementId = parameters.getThirdPartyAdPlacementId();
log( "Loading " + (AppLovinSdkUtils.isValidString( bidResponse ) ? "bidding " : "") + adFormat.getLabel() + " for placement: '" + placementId + "'..." );
Context context = getContext( activity );
bannerAd = new MobileFuseBannerAd( context, placementId, convertMaxFormatToAdSize( adFormat ) );
bannerAd.setListener( createMobileFuseAdListener( listener ) );
Bundle serverParameters = parameters.getServerParameters();
if ( serverParameters != null )
{
Boolean initiallyMuted = getCustomParamBooleanValue( serverParameters, PARAM_NAME_INITIALLY_MUTED );
if ( initiallyMuted != null )
{
bannerAd.setMuted( initiallyMuted );
}
ColorDrawable customBackground = parseColor( getCustomParamStringValue( serverParameters, PARAM_NAME_BG_COLOR ) );
if ( customBackground != null )
{
bannerAd.setBackground( customBackground );
}
}
if ( isBidding )
{
bannerAd.loadAdFromBiddingToken( bidResponse );
}
else
{
bannerAd.loadAd();
}
}
//endregion
//region MAX Parameter Parsing
private MobileFuseBiddingTokenRequest getBiddingTokenRequest(MaxAdapterParameters parameters)
{
MobileFusePrivacyPreferences.Builder builder = new MobileFusePrivacyPreferences.Builder();
builder.setSubjectToGdpr( getWrappingSdk().getConfiguration().getConsentDialogState() == AppLovinSdkConfiguration.ConsentDialogState.APPLIES );
if ( AppLovinSdk.VERSION_CODE >= 91100 )
{
Boolean isDoNotSell = getPrivacySetting( "isDoNotSell", parameters );
if ( isDoNotSell != null )
{
builder.setUsPrivacyConsentString( isDoNotSell ? "1YY-" : "1YN-" );
}
else
{
builder.setUsPrivacyConsentString( "1---" );
}
}
if ( AppLovinSdk.VERSION_CODE >= 11_04_03_99 )
{
if ( parameters.getConsentString() != null )
{
builder.setIabConsentString( parameters.getConsentString() );
}
}
Boolean isAgeRestrictedUser = getPrivacySetting( "isAgeRestrictedUser", parameters );
if ( isAgeRestrictedUser != null )
{
builder.setSubjectToCoppa( isAgeRestrictedUser );
}
boolean isTesting = parameters.isTesting();
return new MobileFuseBiddingTokenRequest( builder.build(), isTesting );
}
private Boolean getPrivacySetting(final String privacySetting, final MaxAdapterParameters parameters)
{
try
{
// Use reflection because compiled adapters have trouble fetching `boolean` from old SDKs and `Boolean` from new SDKs (above 9.14.0)
Class<?> parametersClass = parameters.getClass();
Method privacyMethod = parametersClass.getMethod( privacySetting );
return (Boolean) privacyMethod.invoke( parameters );
}
catch ( Exception exception )
{
log( "Error getting privacy setting " + privacySetting + " with exception: ", exception );
return (AppLovinSdk.VERSION_CODE >= 9140000) ? null : false;
}
}
private Bundle getServerCustomParams(Bundle serverParameters)
{
if ( !serverParameters.containsKey( PARAM_NAME_CUSTOM_PARAMS_JSON ) )
{
return null;
}
return serverParameters.getBundle( PARAM_NAME_CUSTOM_PARAMS_JSON );
}
private String getCustomParamStringValue(Bundle serverParameters, String customParamName)
{
try
{
Bundle customParams = getServerCustomParams( serverParameters );
if ( customParams == null )
{
return null;
}
if ( !customParams.containsKey( customParamName ) )
{
return null;
}
return customParams.getString( customParamName ).trim();
}
catch ( Exception ex )
{
ex.printStackTrace();
}
return null;
}
private Boolean getCustomParamBooleanValue(Bundle serverParameters, String customParamName)
{
try
{
Bundle customParams = getServerCustomParams( serverParameters );
if ( customParams == null )
{
return null;
}
if ( !customParams.containsKey( customParamName ) )
{
return null;
}
return customParams.getBoolean( customParamName );
}
catch ( Exception ex )
{
ex.printStackTrace();
}
return null;
}
//endregion
//region Data conversion helpers
private MobileFuseBannerAd.AdSize convertMaxFormatToAdSize(MaxAdFormat adFormat)
{
if ( adFormat == MaxAdFormat.LEADER )
{
return MobileFuseBannerAd.AdSize.BANNER_728x90;
}
else if ( adFormat == MaxAdFormat.MREC )
{
return MobileFuseBannerAd.AdSize.BANNER_300x250;
}
else
{
return MobileFuseBannerAd.AdSize.BANNER_320x50;
}
}
//endregion
//region Helper methods
private Context obtainApplicationContext(Activity activity)
{
return (activity != null)
? activity.getApplicationContext()
: getApplicationContext();
}
private ColorDrawable parseColor(String backgroundColorValue)
{
if ( backgroundColorValue == null )
{
return null;
}
if ( backgroundColorValue.startsWith( "#" ) )
{
backgroundColorValue = backgroundColorValue.substring( 1 );
}
else if ( backgroundColorValue.startsWith( "0x" ) )
{
backgroundColorValue = backgroundColorValue.substring( 2 );
}
if ( backgroundColorValue.length() <= 6 )
{
backgroundColorValue = "ff" + backgroundColorValue;
}
try
{
return new ColorDrawable((int) Long.parseLong( backgroundColorValue, 16 ));
}
catch ( NumberFormatException ex )
{
return null;
}
}
private Context getContext(@Nullable Activity activity)
{
// NOTE: `activity` can only be null in 11.1.0+, and `getApplicationContext()` is introduced in 11.1.0
return ( activity != null ) ? activity.getApplicationContext() : getApplicationContext();
}
//endregion
//region Listener creation methods
private MobileFuseInterstitialAd.Listener createMobileFuseAdListener(MaxInterstitialAdapterListener maxListener)
{
return new MobileFuseInterstitialAd.Listener()
{
@Override
public void onAdClosed()
{
log( "InterstitialAd::onAdClosed" );
maxListener.onInterstitialAdHidden();
}
@Override
public void onAdLoaded()
{
log( "InterstitialAd::onAdLoaded" );
maxListener.onInterstitialAdLoaded();
}
@Override
public void onAdNotFilled()
{
log( "InterstitialAd::onAdNotFilled" );
maxListener.onInterstitialAdLoadFailed( MaxAdapterError.NO_FILL );
}
@Override
public void onAdRendered()
{
log( "InterstitialAd::onAdRendered" );
maxListener.onInterstitialAdDisplayed();
}
@Override
public void onAdClicked()
{
log( "InterstitialAd::onAdClicked" );
maxListener.onInterstitialAdClicked();
}
@Override
public void onAdExpired()
{
log( "InterstitialAd::onAdExpired" );
maxListener.onInterstitialAdLoadFailed( MaxAdapterError.AD_EXPIRED );
}
@Override
public void onAdError(AdError adError)
{
if ( adError != null )
{
log( "InterstitialAd::onAdError [adErrorCode" + adError.getErrorCode() + ", adErrorMsg: " + adError.getErrorMessage() + "]" );
}
else
{
log( "InterstitialAd::onAdError" );
}
}
};
}
private MobileFuseRewardedAd.Listener createMobileFuseAdListener(MaxRewardedAdapterListener maxListener)
{
return new MobileFuseRewardedAd.Listener()
{
@Override
public void onAdClosed()
{
log( "RewardedAd::onAdClosed" );
maxListener.onRewardedAdHidden();
}
@Override
public void onUserEarnedReward()
{
log( "RewardedAd::onUserEarnedReward" );
maxListener.onUserRewarded( new MaxReward()
{
@Override
public String getLabel()
{
return "";
}
@Override
public int getAmount()
{
return 0;
}
} );
}
@Override
public void onAdLoaded()
{
log( "RewardedAd::onAdLoaded" );
maxListener.onRewardedAdLoaded();
}
@Override
public void onAdNotFilled()
{
log( "RewardedAd::onAdNotFilled" );
maxListener.onRewardedAdLoadFailed( MaxAdapterError.NO_FILL );
}
@Override
public void onAdRendered()
{
log( "RewardedAd::onAdRendered" );
maxListener.onRewardedAdDisplayed();
}
@Override
public void onAdClicked()
{
log( "RewardedAd::onAdClicked" );
maxListener.onRewardedAdClicked();
}
@Override
public void onAdExpired()
{
log( "RewardedAd::onAdExpired" );
maxListener.onRewardedAdLoadFailed( MaxAdapterError.AD_EXPIRED );
}
@Override
public void onAdError(AdError adError)
{
if ( adError != null )
{
log( "RewardedAd::onAdError [adErrorCode" + adError.getErrorCode() + ", adErrorMsg: " + adError.getErrorMessage() + "]" );
}
else
{
log( "RewardedAd::onAdError" );
}
}
};
}
private MobileFuseBannerAd.Listener createMobileFuseAdListener(MaxAdViewAdapterListener listener)
{
return new MobileFuseBannerAd.Listener()
{
@Override
public void onAdExpanded()
{
log( "BannerAd::onAdExpanded" );
listener.onAdViewAdExpanded();
}
@Override
public void onAdCollapsed()
{
log( "BannerAd::onAdCollapsed" );
listener.onAdViewAdCollapsed();
}
@Override
public void onAdLoaded()
{
log( "BannerAd::onAdLoaded" );
listener.onAdViewAdLoaded( bannerAd );
}
@Override
public void onAdNotFilled()
{
log( "BannerAd::onAdNotFilled" );
listener.onAdViewAdLoadFailed( MaxAdapterError.NO_FILL );
}
@Override
public void onAdRendered()
{
log( "BannerAd::onAdRendered" );
listener.onAdViewAdDisplayed();
}
@Override
public void onAdClicked()
{
log( "BannerAd::onAdClicked" );
listener.onAdViewAdClicked();
}
@Override
public void onAdExpired()
{
log( "BannerAd::onAdExpired" );
listener.onAdViewAdLoadFailed( MaxAdapterError.AD_EXPIRED );
}
@Override
public void onAdError(AdError adError)
{
if ( adError != null )
{
log( "BannerAd::onAdError [adErrorCode" + adError.getErrorCode() + ", adErrorMsg: " + adError.getErrorMessage() + "]" );
}
else
{
log( "BannerAd::onAdError" );
}
listener.onAdViewAdDisplayFailed( MaxAdapterError.INTERNAL_ERROR );
}
};
}
//endregion
}
Updated almost 2 years ago