This page describes how to integrate our Android SDK with your project.
Follow the instructions in this section to set up our SDK to show ads in your app.
Requirements
This SDK requires Android 4 or later, and Android SDK version 14 or higher.
In order to show ads, you must have a valid Xandr placement ID. This is a numeric ID that represents a context in an application where ads can be shown
Tip: Google Play
In order to enable the Android Advertising ID (AAID) for frequency capping and mobile app targeting, you must include Google Play Services as a dependency of your app. Xandr's SDK will still function without Google Play Services, but you won't have access to those features.
Tip: Android Studio and Gradle
These instructions assume you are using Android Studio and Gradle. Most of the required AndroidManifest.xml
entries (except the Location permissions) and ProGuard changes are automatically added to your app. If you are using other build systems, the steps may vary.
Installation
Get the SDK
Clone the repo
Run this command in your terminal:
git clone https://github.com/e-planning/mobile-sdk-android.git
Note: The SDK is a standalone library
Add the source to your project
Click File -> New -> Import Module (or your IDE's equivalent) and enter the location of the SDK sources you just cloned. Make sure the sources are actually copied into your project so you can edit the code.
Configure build settings
Include the SDK at the top of your settings.gradle
file:
include ':app', ':sdk'
Add a new line in the dependencies
block of your app's build.gradle
file:
dependencies { compile project(":sdk") }
At this point you should be able to build your app with the SDK included as a library.
Edit App Permissions
Edit your Android manifest to include the following (optional but recommended) permissions:
<!-- Android: XML to include recommended permissions --> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Add the permissions here... --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
ACCESS_COARSE_LOCATION
(recommended) - Grants the SDK permission to access approximate location based on cell tower.ACCESS_FINE_LOCATION
(recommended) - Grants the SDK permission to access a more accurate location based on GPS.
Tip: Location Permissions Must Prompt the User
In API Level 23 (Marshmallow) and above, you must prompt the user with a dialog at app runtime for either of the location permissions listed above. The SDK can only access location permissions with the user's consent.
For more information, see Request Permissions from the Android documentation.
Although not technically required, the location permissions make it possible for the SDK to send location-based data to advertisers. Sending better location data generally leads to better monetization.
Note: The SDK will never wake up the phone to request the location to be updated; this would take time and battery. Instead, it will use these permissions to access the last known location of the device.
Edit Proguard Settings
If your app uses Proguard, you must edit your Proguard settings to avoid stripping Google Play out of your app. The SDK doesn't require Google Play to function, but you will lose access to the Android Advertiser ID (AAID), which is used for app targeting and frequency capping. Edit your project's proguard-project.txt
file to add the following:
### Proguard settings to support Android Advertiser ID -keep class com.google.android.gms.ads.identifier.AdvertisingIdClient { com.google.android.gms.ads.identifier.AdvertisingIdClient$Info getAdvertisingIdInfo(android.content.Context); } -keep class com.google.android.gms.ads.identifier.AdvertisingIdClient$Info { java.lang.String getId(); boolean isLimitAdTrackingEnabled(); }
Show Banners on Android
You can configure your banner ad view using XML, Java, or a mixture of the two. The XML and Java equivalents are listed below.
opensdk:publisher_id
oradview.setPublisherId(Int publisherID)
: The publisherID ID associated with your app's inventory. You must include a publisher ID or an error will be thrown. Example:"123456"
. You can get this value from our UI or from your Account Manager.opensdk:auto_refresh_interval
oradview.setAutoRefreshInterval(long interval)
: The interval, in milliseconds, at which the ad view will request new ads, if autorefresh is enabled. The minimum period is 15 seconds. The default period is 30 seconds. Set this to 0 to disable autorefresh. Example:"60000"
.opensdk:ad_width
oradview.setAdSize(int width, int height)
: The width of the advertisement to request from the server. If this is not set, the SDK requests an ad of at leastandroid:layout_width
. Note that the Java methodsetAdSize
sets the width and height at the same time. Example:"320"
.opensdk:ad_height
oradview.setAdSize(int width, int height)
: The height of the view. Note that the Java methodsetAdSize
sets the width and height at the same time. Example:"50dp"
.
If you're using XML, you must add the xmlns:opensdk
namespace attribute describing your application to your layout tag; for example this might be a RelativeLayout
, LinearLayout
, or FrameLayout
.
// Android: XML to configure the banner ad view (optional) xmlns:opensdk="https://schemas.android.com/apk/res/com.example.SimpleBanner"
Here's how to declare a banner in XML. Note that you must replace YOUR PUBLISHER ID and "YOUR PLACEMENT ID" below with an active publisher ID and placement ID.
Note: If you're using both XML and Java (loadAd
) to define BannerAdView
, define auto_refresh_interval
in either XML or Java. Do not define auto_refresh_interval
in both.
// Android: XML to declare banner ad view (optional) <net.eplanning.opensdk.BannerAdView android:id="@+id/banner" android:layout_width="wrap_content" android:layout_height="wrap_content" opensdk:publisher_id=YOUR PUBLISHER ID opensdk:placement_id="YOUR PLACEMENT ID" opensdk:auto_refresh_interval="60000" opensdk:adWidth="320" opensdk:adHeight="50" opensdk:should_reload_on_resume="true" opensdk:opens_native_browser="true" android:expands_to_fit_screen_width="false" />
To show ads, you must set up a BannerAdView
. Note that the height and width you specify here must match the size of the ad placement. The code below shows a banner ad (and assumes that your placement ID points at a 300x50 placement).
This simple example doesn't take advantage of all of the capabilities provided by the SDK - for example, you can also pass in the user's age and gender, as well as whether an ad click should open the device's native browser.
Note: As best practices :
All SDK methods must be called on the main thread.
activityOnDestroy()
must be called for the BannerAdView that is expected to be destroyed.
// Android: Java to show a banner ad package eplanning.example.kotlinsample import android.os.Bundle import android.util.Log import android.widget.LinearLayout import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import net.eplanning.opensdk.AdListener import net.eplanning.opensdk.AdView import net.eplanning.opensdk.BannerAdView import net.eplanning.opensdk.NativeAdResponse import net.eplanning.opensdk.ResultCode class BannerActivity : AppCompatActivity(), AdListener { private lateinit var banner: BannerAdView private lateinit var layout: LinearLayout override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_banner) layout = findViewById(R.id.linearLayout) banner = BannerAdView(this) banner.setPublisherId(123456) // PublisherID banner.placementID = "17058950" // PlacementID banner.setAdSize(300, 250) // Size banner.adListener = this // AdListener banner.loadAd() layout.addView(banner) } override fun onAdLoaded(ad: AdView?) { log("Banner Ad Loaded") } override fun onAdLoaded(nativeAdResponse: NativeAdResponse?) { log("Native Ad Loaded") } override fun onAdClicked(adView: AdView?) { log("Ad Clicked") } override fun onAdClicked(adView: AdView?, clickUrl: String?) { log("Ad Clicked with URL: $clickUrl") } override fun onAdExpanded(adView: AdView?) { log("Ad Expanded") } override fun onAdCollapsed(adView: AdView?) { log("Ad Collapsed") } override fun onAdRequestFailed(adView: AdView?, resultCode: ResultCode?) { log("Ad Failed: " + resultCode?.message) } override fun onLazyAdLoaded(adView: AdView?) { log("Ad onLazyAdLoaded") } override fun onAdImpression(adView: AdView?) { log("Ad onAdImpression") } private fun log(msg: String){ Log.d("BannerActivity",msg) Toast.makeText(this.applicationContext, msg, Toast.LENGTH_LONG).show() } override fun onDestroy() { if (banner != null) { banner.activityOnDestroy() } super.onDestroy() } }
Show Interstitials on Android
Showing interstitial ads is a little more work. In addition to setting up an InterstitialAdView
with your placement ID, you must implement the AdListener
interface, which includes methods that tell you when an interstitial ad has successfully finished loading, or when the request has failed.
Furthermore, actually showing interstitial ads to users is a two-step process:
Call
InterstitialAdView.loadAd()
to fetch the ad contents from our server and cache them locally. Note that any ad content is rendered in a WebView at the time it is fetched from the ad server and cached. This means that any third-party tracking pixels that are part of the ad content will be fired at the time of the call toloadAd()
, not when the call toshow()
is made at a later time.When you're ready to show the interstitial ad to the user, call
show()
. This needs to happen within approximately 4 minutes of the call toloadAd()
in order for the impression to be counted by Xandr. (For the exact timing in milliseconds, see the value ofInterstitialAdView.MAX_AGE
in the source code.)
Note that the close button appears after ten seconds by default. You can set the delay using InterstitialAdView.setCloseButtonDelay(int closeButtonDelay)
.
For more information, see the code sample below.
Note: As best practices :
All SDK methods must be called on the main thread.
activityOnDestroy()
must be called for the Interstitial that is expected to be destroyed.
// Android: Java code to show an interstitial ad package com.example.simpleinterstitial; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.util.Log; import net.eplanning.opensdk.AdListener import net.eplanning.opensdk.AdView import net.eplanning.opensdk.BannerAdView import net.eplanning.opensdk.NativeAdResponse import net.eplanning.opensdk.ResultCode public class MainActivity extends Activity implements AdListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); InterstitialAdView iav = new InterstitialAdView(this); iav.setPublisherID(123456); iav.setPlacementID("1326299"); iav.setAdListener(this); // Fetch an ad from the server. If this works, `onAdLoaded' will // be called, and we can show the ad. iav.loadAd(); } @Override protected void onDestroy() { if (iav != null) { iav.activityOnDestroy(); } super.onDestroy(); } @Override public void onAdLoaded(AdView av) { Log.d("onAdLoaded", "The ad has loaded, now we can show it..."); // Now that the ad has loaded, we can show it to the user. InterstitialAdView iav = (InterstitialAdView) av; iav.show(); } @Override public void onAdLoaded(NativeAdResponse nativeAdResponse) { // JUST ignore it. This callback is for Native in Banner. } @Override public void onAdRequestFailed(AdView av, ResultCode rc) { Log.d("onAdRequestFailed", "Not sure why the ad request failed; try again? Return code ==> " + rc); } @Override public void onAdClicked(AdView av) { Log.d("onAdClicked", "The user clicked your ad. Congrats!"); } @Override public void onAdClicked(AdView adView, String clickUrl) { // This will be getting called if you have set setClickThroughAction(ANClickThroughAction.RETURN_URL); // Handle the URL appropriately } @Override public void onAdCollapsed(AdView av) { // Do something here. } @Override public void onAdExpanded(AdView av) { // Do something here as well. } }
Using Custom Interstitial Sizes
By default, if you don't specify an ad size, the SDK will fetch ads in any of the sizes below that are less than or equal to the size of the device's screen.
1x1 (always sent)
The detected size of the screen (always sent)
300x250
320x480
900x500
1024x1024
If you want to show interstitial ads in sizes other than the defaults, use the setAllowedSizes
method on the interstitial ad view as shown below. Note that the detected size of the screen will still be passed as the primary size. The sizes set using setAllowedSizes
will be passed in as additional size on the interstitial ad view and will replace the defaults of 300x250, 320x480, 900x500, and 1024x1024.
// Android: Java code to show interstitial ads in sizes other than the defaults (optional) InterstitialAdView iav = new InterstitialAdView(this); iav.setPublisherId(123456); iav.setPlacementID("1326299"); AdSize test_size1 = new AdSize(320,480); AdSize test_size2 = new AdSize(768,1024); ArrayList test_array_list = new ArrayList() {}; test_array_list.add(test_size1); test_array_list.add(test_size2); iav.setAllowedSizes(test_array_list);
Auto-Close an Interstitial
If you want to auto-close an interstitial ad after a specific timeout period, do not call show()
as described in the above sections. Instead, call showWithAutoDismissDelay(delayinseconds)
, where delayinseconds
is the number of seconds the ad will be displayed before it closes.
// This will show an interstitial ad, wait for 10 seconds, then auto close it. interstitialAdView.showWithAutoDismissDelay(10);
Show Instream Video Ads on Android
Cache the Video Ad
To cache a video ad, set up a request object and supply it with a Publisher ID and Placement ID.
Then register a VideoAdLoadListener
which will signal whether the ad load succeeded or failed. This is optional but strongly recommended. If you don't set the VideoAdLoadListener,
you can use the VideoAd.isReady()
method to check whether the ad is available.
After that, call VideoAd.loadAd()
to start caching the ad.
// Create a VideoAd instance VideoAd videoAd = new VideoAd(this); videoAd.setPublisherID(123456); videoAd.setPlacementID("1326299"); // Set the (optional) VideoAdLoadListener. videoAd.setAdLoadListener( new VideoAdLoadListener() { @Override public void onAdLoaded(VideoAd videoAd) { Log.d(TAG, "onAdLoaded" ); } @Override public void onAdRequestFailed(VideoAd videoAd, ResultCode errorCode) { Log.d(TAG, "onAdRequestFailed" ); } }); // At this point you can set targeting parameters, the ad landing // page, and many other options before calling `loadAd()`. For // details, see the SDK documentation. // Load the VideoAd. videoAd.loadAd();
Set up the Video Playback Listener
Before showing the video ad, you'll need to set up the mandatory VideoPlaybackListener
. The onAdCompleted()
notification is required to show your content video after the ad finishes playing.
/ Set the (mandatory) PlayBack Listener. videoAd.setVideoPlaybackListener( new VideoAdPlaybackListener() { @Override public void onAdPlaying( final VideoAd videoAd) { Log.d(TAG, "onAdPlaying::" ); } @Override public void onQuartile(VideoAd view, Quartile quartile) { Log.d(TAG, "onQuartile::" + quartile); } // Resume your VideoPlayer with the 'onAddCompleted' notification. @Override public void onAdCompleted(VideoAd view, PlaybackCompletionState playbackState) { Log.d(TAG, "onAdCompleted::playbackState" + playbackState); videoPlayer.start(); // The 'videoPlayer' here is your Application Content Video Player. } @Override public void onAdMuted(VideoAd view, boolean isMute) { Log.d(TAG, "isAudioMute::" + isMute); } @Override public void onAdClicked(VideoAd adView) { Log.d(TAG, "onAdClicked" ); } @Override public void onAdClicked(VideoAd videoAd, String clickUrl) { Log.d(TAG, "onAdClicked" ); } });
Pass Activity Lifecycle Events to the Ad
// This is important because it's used to resume the ad after an interruption by user activity. @Override public void onResume() { super .onResume(); videoAd.activityOnResume(); } @Override public void onPause() { super .onPause(); videoAd.activityOnPause(); } // Used to clear the memory footprint of the VideoAd instance. @Override public void onDestroy() { super .onDestroy(); videoAd.activityOnDestroy(); }
Show the Video Ad
You are now all set to show the Video Ad by calling playAd()
as shown below. Remember to pause your content video player before calling VideoAd.playAd()
:
if (videoAd.isReady()) { // Pause your app's video player. videoPlayer.pause(); // Play the Ad by passing the container. The container here is a // FrameLayout/RelativeLayout, on top of which the ad will be // displayed. videoAd.playAd(baseContainer); }
Pause and Resume the Video Ad
To pause or resume playing the video ad use the following method calls.
public void resumeAd(); public void pauseAd();
Fetch the Attributes of a Loaded Video Creative
Once the video is loaded, you may retrieve various creative attributes:
public String getVastURL() //Provide the VAST content URL public int getVideoAdDuration() //Provide the duration of the video public String getVastXML() //Provide the VAST content as an XML string public String getCreativeURL() //Provide the actual creative loaded public VideoOrientation getVideoOrientation() //Provide the Orientation of the Video rendered. Possible video orientations can be square, portrait, landscape or none
Determine Ad Play Progress
You can determine how far the adPlay has progressed by retrieving the amount of time that has elapsed since the ad began playing:
public void getAdPlayElapsedTime(ResultCallback<String> resultCallback)