Preparing Mediated Networks

When you integrate third-party SDKs into your Mobile Property, you are solely responsible for such integrations. You and the third-party SDK provider must ensure compliant data processing and treatment of any end user- or device-based privacy choices or flags.

You can download and integrate the MAX mediation adapters into your app in multiple ways:

Gradle
AppLovin recommends that you integrate adapters this way. AppLovin’s adapters’ POM files automatically integrate the mediated network’s SDK along with its dependencies.
Open Source Adapters
If you require more flexibility in the integration, you can integrate AppLovin’s open source adapters. Android SDK v11.0.0 is required in order to compile. You are responsible for integrating the mediated SDKs and any dependencies they require. You can find these adapters in the AppLovn-MAX-SDK-Android GitHub repository.
Manual Integration
Read the manual integration instructions if you want to integrate the adapter artifacts, mediated SDKs, and their dependencies manually.

Do not change the adapter’s name or package name. If you do so, the MAX SDK will not be able to recognize the adapter and ads will not load.

By , developers & publishers who use Google AdSense, AdManager, or AdMob must use a consent management platform (CMP) that is certified by Google and that integrates with IAB’s Transparency and Consent Framework when they serve ads to users in the European Economic Area (EEA) or the UK. Click here for more information.

Pangle SDK versions 5.4.0.0–5.5.0.8 cause deadlocks. These inhibit MAX from effectively carrying out core mediation capabilities, and impact revenue. For this reason, as of Pangle are filtered from auctions. AppLovin encourages you to update to the latest Pangle Android SDK (5.6.0.1 or later) as soon as you can.

Gradle

Choose which mediated ad networks you want to integrate by checking the boxes below, and this page will display instructions specific to those networks. Then copy the customized Gradle script below to your app-level build.gradle.

  • // Repos
    repositories {
        google()
        mavenCentral()
    }
    
    dependencies {
        implementation 'com.applovin:applovin-sdk:+'
    }
  • // Repos
    repositories {
        google()
        mavenCentral()
    }
    
    dependencies {
        implementation("com.applovin:applovin-sdk:+")
    }

Minimum API Level Required

Nend requires Android API 19 (KitKat 4.4–4.4.4) or higher.

Migrating to AndroidX

Integrate AndroidX libraries into your project. Refer to the Migrate to AndroidX guide for more information on how to migrate your project.

Add Your Google Bidding and Google AdMob / Google Ad Manager App ID

In your app’s AndroidManifest.xml, add a <meta-data> tag inside the <application> tag. In the example below, replace your-admob-app-id with your Google bidding and Google AdMob / Google Ad Manager App ID.

<?xml version="1.0" encoding="utf-8"?>
<manifest … >
  <application … >
    <meta-data
      android:name="com.google.android.gms.ads.APPLICATION_ID"
      android:value="your-admob-app-id"/>
    ⋮
  </application>
</manifest>

Google Mobile Ads SDK versions 20.5.0 and newer require that you set the compileSdkVersion of your app to 31 in build.gradle. Google Mobile Ads SDK version 20.4.0.1 is the most recent version that still supports setting compileSdkVersion to 30.

Use the latest Amazon Publisher Services adapter version to avoid reporting discrepancies.

Initialize the Amazon SDK

The Amazon Publisher Services SDK requires that you initialize it outside of MAX SDK:

// Amazon requires an 'Activity' instance
AdRegistration.getInstance( "AMAZON_APP_ID", this );
AdRegistration.setAdNetworkInfo( new DTBAdNetworkInfo( DTBAdNetwork.MAX ) );
AdRegistration.setMRAIDSupportedVersions( new String[] { "1.0", "2.0", "3.0" } );
AdRegistration.setMRAIDPolicy( MRAIDPolicy.CUSTOM );

Load a Banner Ad from Amazon’s SDK

Amazon leaders (tablet banners) are not supported. Only use Amazon banners when you create slot IDs in the Amazon dashboard.

To integrate Amazon ads into MAX, you must load the Amazon ad first, then pass the DTBAdResponse or AdError into the instance of MaxAdView by calling MaxAdView#setLocalExtraParameter() before you load the MAX ad.

For auto-refreshing banner ads you only need to load the ad once.

  • class ExampleActivity
            extends Activity
    {
      ⋮
    
      private void loadAd()
      {
        String amazonAdSlotId;
        MaxAdFormat adFormat;
    
        if ( AppLovinSdkUtils.isTablet( getApplicationContext() ) )
        {
          amazonAdSlotId = "Amazon-leader-slot-ID";
          adFormat = MaxAdFormat.LEADER;
        }
        else
        {
          amazonAdSlotId = "Amazon-banner-slot-ID";
          adFormat = MaxAdFormat.BANNER;
        }
    
        // Raw size will be 320x50 for BANNERs on phones, and 728x90 for LEADERs on tablets
        AppLovinSdkUtils.Size rawSize = adFormat.getSize();
        DTBAdSize size = new DTBAdSize( rawSize.getWidth(), rawSize.getHeight(), amazonAdSlotId );
    
        DTBAdRequest adLoader = new DTBAdRequest();
        adLoader.setSizes( size );
        adLoader.loadAd( new DTBAdCallback()
        {
          @Override
          public void onSuccess(@NonNull final DTBAdResponse dtbAdResponse)
          {
            // 'adView' is your instance of MaxAdView
            adView.setLocalExtraParameter( "amazon_ad_response", dtbAdResponse );
            adView.loadAd();
          }
          
          @Override
          public void onFailure(@NonNull final AdError adError)
          {
            // 'adView' is your instance of MaxAdView
            adView.setLocalExtraParameter( "amazon_ad_error", adError );
            adView.loadAd();
          }
        } );
      }
    }
  • class ExampleActivity : Activity()
    {
      private val adView: MaxAdView? = null
    
      private fun loadAd()
      {
        val amazonAdSlotId: String
        val adFormat: MaxAdFormat
    
        if (AppLovinSdkUtils.isTablet(applicationContext))
        {
          amazonAdSlotId = "Amazon-leader-slot-ID"
          adFormat = MaxAdFormat.LEADER
        }
        else
        {
          amazonAdSlotId = "Amazon-banner-slot-ID"
          adFormat = MaxAdFormat.BANNER
        }
    
        // Raw size will be 320x50 for BANNERs on phones, and 728x90 for LEADERs on tablets
        val rawSize = adFormat.size
        val size = DTBAdSize(rawSize.width, rawSize.height, amazonAdSlotId)
    
        val adLoader = DTBAdRequest()
        adLoader.setSizes(size)
        adLoader.loadAd(object : DTBAdCallback
        {
          override fun onSuccess(dtbAdResponse: DTBAdResponse)
          {
            // 'adView' is your instance of MaxAdView
            adView?.setLocalExtraParameter("amazon_ad_response", dtbAdResponse)
            adView?.loadAd()
          }
    
          override fun onFailure(adError: AdError)
          {
            // 'adView' is your instance of MaxAdView
            adView?.setLocalExtraParameter("amazon_ad_error", adError)
            adView?.loadAd()
          }
        })
      }
    }

Load an MREC Ad from Amazon’s SDK

To integrate Amazon MRECs into MAX, you must load the Amazon ad first, then pass the DTBAdResponse or AdError into the instance of MaxAdView by calling MaxAdView#setLocalExtraParameter() before you load the MAX ad.

  • class ExampleActivity
            extends Activity
    {
      ⋮
      private void loadAd()
      {
        String amazonAdSlotId;
    
        DTBAdRequest adLoader = new DTBAdRequest();
        adLoader.setSizes( new DTBAdSize( 300, 250, amazonAdSlotId ) );
        adLoader.loadAd( new DTBAdCallback()
        {
          @Override
          public void onSuccess(@NonNull final DTBAdResponse dtbAdResponse)
          {
            // 'adView' is your instance of MaxAdView
            adView.setLocalExtraParameter( "amazon_ad_response", dtbAdResponse );
            adView.loadAd();
          }
    
          @Override
          public void onFailure(@NonNull final AdError adError)
          {
            // 'adView' is your instance of MaxAdView
            adView.setLocalExtraParameter( "amazon_ad_error", adError );
            adView.loadAd();
          }
        } );
      }
    }
  • class ExampleActivity : Activity()
    {
      private val adView: MaxAdView? = null
    
      private fun loadAd()
      {
        val amazonAdSlotId: String
    
        val adLoader = DTBAdRequest()
        adLoader.setSizes(DTBAdSize(300, 250, amazonAdSlotId))
        adLoader.loadAd(object : DTBAdCallback
        {
          override fun onSuccess(dtbAdResponse: DTBAdResponse)
          {
            // 'adView' is your instance of MaxAdView
            adView!!.setLocalExtraParameter("amazon_ad_response", dtbAdResponse)
            adView.loadAd()
          }
    
          override fun onFailure(adError: AdError)
          {
            // 'adView' is your instance of MaxAdView
            adView!!.setLocalExtraParameter("amazon_ad_error", adError)
            adView.loadAd()
          }
        })
      }
    }

Load an Interstitial Ad from Amazon’s SDK

To integrate Amazon interstitial ads into MAX, you must load the Amazon ad first, then pass the DTBAdResponse or AdError into the instance of MaxInterstitialAd by calling MaxInterstitialAd#setLocalExtraParameter() before you load the MAX ad.

You must load and pass the Amazon DTBAdResponse or DTBAdErrorInfo into the MaxInterstitialAd instance only once per session.

  • class ExampleActivity
           extends Activity
    {
      private static MaxInterstitialAd interstitialAd; // static to ensure only one instance exists
      private static boolean           isFirstLoad = true;
    
      private void loadAd()
      {
        if ( isFirstLoad )
        {
          isFirstLoad = false;
    
          if ( interstitialAd == null )
          {
            interstitialAd = new MaxInterstitialAd( "MAX-inter-ad-unit-ID", this );
          }
    
          DTBAdRequest adLoader = new DTBAdRequest();
          adLoader.setSizes( new DTBAdSize.DTBInterstitialAdSize( "Amazon-inter-slot-ID" ) );
          adLoader.loadAd( new DTBAdCallback()
          {
            @Override
            public void onSuccess(@NonNull final DTBAdResponse dtbAdResponse)
            {
              // 'interstitialAd' is your instance of MaxInterstitialAd
              interstitialAd.setLocalExtraParameter( "amazon_ad_response", dtbAdResponse );
              interstitialAd.loadAd();
            }
            
            @Override
            public void onFailure(@NonNull final AdError adError)
            {
              // 'interstitialAd' is your instance of MaxInterstitialAd
              interstitialAd.setLocalExtraParameter( "amazon_ad_error", adError );
              interstitialAd.loadAd();
            }
          } );
        }
        else
        {
          interstitialAd.loadAd();
        }
      }
    }
  • class ExampleActivity : Activity()
    {
      private var interstitialAd: MaxInterstitialAd? = null // static to ensure only one instance exists
      private var isFirstLoad = true
    
      private fun loadAd()
      {
        if (isFirstLoad)
        {
          isFirstLoad = false
    
          if (interstitialAd == null)
          {
            interstitialAd = MaxInterstitialAd("MAX-inter-ad-unit-ID", this)
          }
    
          val adLoader = DTBAdRequest()
          adLoader.setSizes(DTBAdSize.DTBInterstitialAdSize("Amazon-inter-slot-ID"))
          adLoader.loadAd(object : DTBAdCallback
          {
            override fun onSuccess(dtbAdResponse: DTBAdResponse)
            {
              // 'interstitialAd' is your instance of MaxInterstitialAd
              interstitialAd!!.setLocalExtraParameter("amazon_ad_response", dtbAdResponse)
              interstitialAd!!.loadAd()
            }
    
            override fun onFailure(adError: AdError)
            {
              // 'interstitialAd' is your instance of MaxInterstitialAd
              interstitialAd!!.setLocalExtraParameter("amazon_ad_error", adError)
              interstitialAd!!.loadAd()
            }
          })
        }
        else
        {
          interstitialAd!!.loadAd()
        }
      }
    }

Load a Video Interstitial Ad from Amazon’s SDK

To integrate Amazon video interstitial ads into MAX, you must load the Amazon ad first, then pass the DTBAdResponse or AdError into the instance of MaxInterstitialAd by calling MaxInterstitialAd#setLocalExtraParameter() before you load the MAX ad.

You must load and pass the Amazon DTBAdResponse or DTBAdErrorInfo into the MaxInterstitialAd instance only once per session.

  • class ExampleActivity
           extends Activity
    {
      private static MaxInterstitialAd interstitialAd; // static to ensure only one instance exists
      private static boolean           isFirstLoad = true;
    
      private void loadAd()
      {
        if ( isFirstLoad )
        {
          isFirstLoad = false;
    
          if ( interstitialAd == null )
          {
            interstitialAd = new MaxInterstitialAd( "MAX-inter-ad-unit-ID", this );
          }
    
          DTBAdRequest adLoader = new DTBAdRequest();
    
          // Switch video player width and height values(320, 480) depending on device orientation
          adLoader.setSizes( new DTBAdSize.DTBVideo(320, 480, "Amazon-video-inter-slot-ID") );
          adLoader.loadAd( new DTBAdCallback()
          {
            @Override
            public void onSuccess(@NonNull final DTBAdResponse dtbAdResponse)
            {
              // 'interstitialAd' is your instance of MaxInterstitialAd
              interstitialAd.setLocalExtraParameter( "amazon_ad_response", dtbAdResponse );
              interstitialAd.loadAd();
            }
    
            @Override
            public void onFailure(@NonNull final AdError adError)
            {
              // 'interstitialAd' is your instance of MaxInterstitialAd
              interstitialAd.setLocalExtraParameter( "amazon_ad_error", adError );
              interstitialAd.loadAd();
            }
          } );
        }
        else
        {
          interstitialAd.loadAd();
        }
      }
    }
  • class ExampleActivity : Activity()
    {
      private var interstitialAd: MaxInterstitialAd? = null // static to ensure only one instance exists
      private var isFirstLoad = true
    
      private fun loadAd()
      {
        if (isFirstLoad)
        {
          isFirstLoad = false
    
          if (interstitialAd == null)
          {
            interstitialAd = MaxInterstitialAd("MAX-inter-ad-unit-iD", this)
          }
    
          val adLoader = DTBAdRequest()
    
          // Switch video player width and height values(320, 480) depending on device orientation
          adLoader.setSizes(DTBAdSize.DTBVideo(320, 480, "Amazon-video-inter-slot-ID"))
          adLoader.loadAd(object : DTBAdCallback
          {
            override fun onSuccess(dtbAdResponse: DTBAdResponse)
            {
              // 'interstitialAd' is your instance of MaxInterstitialAd
              interstitialAd!!.setLocalExtraParameter("amazon_ad_response", dtbAdResponse)
              interstitialAd!!.loadAd()
            }
    
            override fun onFailure(adError: AdError)
            {
              // 'interstitialAd' is your instance of MaxInterstitialAd
              interstitialAd!!.setLocalExtraParameter("amazon_ad_error", adError)
              interstitialAd!!.loadAd()
            }
          })
        }
        else
        {
          interstitialAd!!.loadAd()
        }
      }
    }

Load a Rewarded Video Ad from Amazon’s SDK

To integrate Amazon rewarded videos into MAX, first load the Amazon ad, then pass the DTBAdResponse or AdError into the instance of MaxRewardedAd by calling MaxRewardedAd#setLocalExtraParameter() before you load the MAX ad.

You must load and pass the Amazon DTBAdResponse or AdError into the MaxRewardedAd instance only once per session.

  • class ExampleActivity
            extends Activity
    {
      private static MaxRewardedAd rewardedAd; // static to ensure only one instance exists
      private static boolean       isFirstLoad = true;
    
      private void loadAd()
      {
        if ( isFirstLoad )
        {
          isFirstLoad = false;
    
          if ( rewardedAd == null )
          {
            rewardedAd = MaxRewardedAd.getInstance( "MAX-rewarded-ad-unit-ID", this );
          }
    
          DTBAdRequest adLoader = new DTBAdRequest();
    
          // Switch video player width and height values(320, 480) depending on device orientation
          adLoader.setSizes( new DTBAdSize.DTBVideo( 320, 480, "Amazon-video-rewarded-slot-ID" ) );
          adLoader.loadAd( new DTBAdCallback()
          {
            @Override
            public void onSuccess(@NonNull final DTBAdResponse dtbAdResponse)
            {
              // 'rewardedAd' is your instance of MaxRewardedAd
              rewardedAd.setLocalExtraParameter( "amazon_ad_response", dtbAdResponse );
              rewardedAd.loadAd();
            }
    
            @Override
            public void onFailure(@NonNull final AdError adError)
            {
              // 'rewardedAd' is your instance of MaxRewardedAd
              rewardedAd.setLocalExtraParameter( "amazon_ad_error", adError );
              rewardedAd.loadAd();
            }
          } );
        }
        else
        {
          rewardedAd.loadAd();
        }
      }
    }
  • class ExampleActivity
            extends Activity
    {
      private static MaxRewardedAd rewardedAd; // static to ensure only one instance exists
      private static boolean       isFirstLoad = true;
    
      private void loadAd()
      {
        if ( isFirstLoad )
        {
          isFirstLoad = false;
    
          if ( rewardedAd == null )
          {
            rewardedAd = MaxRewardedAd.getInstance( "MAX-rewarded-ad-unit-ID", this );
          }
    
          DTBAdRequest adLoader = new DTBAdRequest();
    
          // Switch video player width and height values(320, 480) depending on device orientation
          adLoader.setSizes( new DTBAdSize.DTBVideo( 320, 480, "Amazon-video-rewarded-slot-ID" ) );
          adLoader.loadAd( new DTBAdCallback()
          {
            @Override
            public void onSuccess(@NonNull final DTBAdResponse dtbAdResponse)
            {
              // 'rewardedAd' is your instance of MaxRewardedAd
              rewardedAd.setLocalExtraParameter( "amazon_ad_response", dtbAdResponse );
              rewardedAd.loadAd();
            }
    
            @Override
            public void onFailure(@NonNull final AdError adError)
            {
              // 'rewardedAd' is your instance of MaxRewardedAd
              rewardedAd.setLocalExtraParameter( "amazon_ad_error", adError );
              rewardedAd.loadAd();
            }
          } );
        }
        else
        {
          rewardedAd.loadAd();
        }
      }
    }

Testing Amazon Publisher Services

AppLovin recommends that you enable test mode for Amazon’s SDK to receive test ads. You can do this with the following calls:

AdRegistration.enableTesting( true );
AdRegistration.enableLogging( true );

To filter your waterfalls to contain only Amazon ads, navigate to Select Live Network in the Mediation Debugger and select the Amazon network.

Enable Google Ad Manager

In your app’s AndroidManifest.xml, add a <meta-data> tag inside the <application> tag, as in the example below:

<?xml version="1.0" encoding="utf-8"?>
<manifest … >
  <application … >
    <meta-data
        android:name="com.google.android.gms.ads.AD_MANAGER_APP"
        android:value="true"/>
    ⋮
  </application>
</manifest>

Meta Audience Network Data Processing Options

If you do not want to enable Limited Data Use (LDU) mode, pass SetDataProcessingOptions() an empty string array:

  • import com.facebook.ads.AdSettings;
    ⋮
    AdSettings.setDataProcessingOptions( new String[] {} );
    ⋮
    // Initialize MAX SDK
  • import com.facebook.ads.AdSettings
    ⋮
    AdSettings.setDataProcessingOptions( arrayOf<String>() )
    ⋮
    // Initialize MAX SDK

To enable LDU for users and specify user geography, call SetDataProcessingOptions() in a form like this:

  • import com.facebook.ads.AdSettings;
    ⋮
    AdSettings.setDataProcessingOptions( new String[] {"LDU"}, 1, 1000 );
    ⋮
    // Initialize MAX SDK
  • import com.facebook.ads.AdSettings
    ⋮
    AdSettings.setDataProcessingOptions( arrayOf("LDU"), 1, 1000 )
    ⋮
    // Initialize MAX SDK

Using Google UMP

If you use Google UMP as your CMP, you can parse whether the user has consented to Meta or not by using the following code:

  • Boolean hasMetaConsent = AppLovinSdkUtils.getAdditionalConsentStatus( 89, context );
    if ( hasMetaConsent != null )
    {
      // Set Meta Data Processing Options accordingly. 
    }
    else
    {
      // AC String is not available on disk. Please check for consent status after the user completes the CMP flow.
    }
  • val hasMetaConsent = AppLovinSdkUtils.getAdditionalConsentStatus(89, context)
    if ( hasMetaConsent != null )
    {
      // Set Meta Data Processing Options accordingly.
    }
    else
    {
      // AC String is not available on disk. Please check for consent status after the user completes the CMP flow.
    }
    

Meta Audience Network Data Processing Options for Users in California

For information about how to implement Meta Audience Network’s “Limited Data Use” flag in California, visit the Meta for Developers documentation.

Obfuscation

If you use code obfuscation or resource shrinking, follow Pangle’s Obfuscation guidelines.

Android Manifest Merging Errors

Several network SDKs use the <queries> element in their bundled Android Manifest files. If you are on an incompatible version of the Android Gradle plugin, this will cause one of the following build errors:

  • com.android.builder.internal.aapt.v2.Aapt2Exception: Android resource linking failed
    error: unexpected element <queries> found in <manifest>.
  • Missing 'package' key attribute on element package at [:com.my.target.mytarget-sdk-5.11.3:]
    AndroidManifest Validation failed

To fix this error, upgrade to one of the following versions of the Android Gradle plugin that supports the <queries> element:

Upgrade the Android Gradle Plugin, not the Gradle Build Tools.

Current Android Gradle Plugin Version Version that Supports <queries> Element
4.1.* All
4.0.* 4.0.1+
3.6.* 3.6.4+
3.5.* 3.5.4+
3.4.* 3.4.3+
3.3.* 3.3.3+