Android SDK Implementation Guide

This is a free Software Development Kit for the Android application developers and publishers to monetize their digital mobile inventory in the blink of an eye. SmartyAds SDK integrates with SmartyAds SSP, creating one single source of offerings tailored to publishers’ needs.

Supported ad formats

Banner and rich media ads:

Size, DPI Type SmartyAds SDK Size Constant
320x50 Standard Banner kSmartyAdsAdSizeBanner
320x100 Large Banner kSmartyAdsAdSizeLargeBanner
300x250 IAB Medium Rectangle kSmartyAdsAdSizeIABMediumRectangle
468x60 IAB Full-Size Banner kSmartyAdsAdSizeIABFullSizeBanner
728x90 IAB Leaderboard kSmartyAdsAdSizeIABLeaderBoard

Video ads:

Orientation: Landscape or Portrait

Native ads:

Recommended to use ListView and RecylerView

Interstitial ads:

Size, DPI Type
Custom size Full screen

Getting Started

Just a few steps to start:

  1. Register your account on SmartyAds Supply Side Platform.
  2. Confirm your registration by following the confirmation link sent via email.
  3. Create your first mobile Android inventory, it should be reviewed and then approved.
  4. After that, you will be granted access to create placements for your inventory, and ‘Add Placement’ button should become clickable.
  5. Click on ‘Add Placement’, add the targeting options, floor price and size of your placement, then save your changes.
  6. Please note the Placement ID (e.g., ID#1234) below its title. It will be used later in your code to initialize the ad container.

 

Requirements

  • Android 4.0+ (Jelly Bean, API 16) and higher. MRAID ads require API 19 and higher. Older Android versions will work, but are not officially supported. Recommended API version - 26.

  • Google Play Services - for users ad tracking preferences. For more information, please see Google's Playstore support regarding Google Advertising ID (ADID).

  • Recommended Google Play Services 11.4.0

  • android-support-v4.jar, r26

  • android-support-annotations.jar, r26

  • android-support-v7-recyclerview.jar, r26

  • Android SDK:

Package
Minimum Version
Android SDK Tools
23
Android SDK Platform-tools/Build-tools 23
Android SDK For Android modules, you need to install Android SDK 6.0.x (API 23) and SDK 6.0.0+.

 

Installation

Provide Maven dependency into your Project gradle.build:

repositories {
    jcenter()
    google()
    // SmartyAds Maven dependepcies
    mavenCentral()
    mavenLocal()
    flatDir {
        dirs '../libs'
    }
    maven { url "https://jitpack.io" }
    maven { url "https://s3.amazonaws.com/moat-sdk-builds" }
    maven { url "https://dl.bintray.com/smartyads/maven/" }
}

Include sdk dependency into your Module gradle.build:

implementation('com.smartyads:ad-container:0.4.7') {
    transitive = true
}

Synchronize project with Gradle files (Gradle sync).

IMPORTANT!
Enable Multidex for your app.

Example Multidex
apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.retrolambda'
android {
    compileSdkVersion 26
    buildToolsVersion "26.0.1"
    defaultConfig {
        applicationId "com.smartyads.testapplication"
        minSdkVersion 16
        targetSdkVersion 26
        versionCode 11
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        multiDexEnabled true
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

        }
    }
    compileOptions {
        targetCompatibility JavaVersion.VERSION_1_8
        sourceCompatibility JavaVersion.VERSION_1_8
    }
    dependencies {
        compile fileTree(include: ['*.jar'], dir: 'libs')
        androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
            exclude group: 'com.android.support', module: 'support-annotations'
        })

        compile 'com.android.support:appcompat-v7:26.+'
        compile 'com.android.support:design:26.+'
        compile 'com.android.support:cardview-v7:26.+'

        testCompile 'junit:junit:4.12'
        compile 'com.android.support:multidex:1.0.1'

        compile('com.smartyads:ad-container:0.4.6') {
            transitive = true
        }
    }
}

Sample Test App

You can download the application and test your creatives in it: Test App

Setup App Permissions (optional)

Edit your Android manifest to include the following (optional but recommended) permissions:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.smartyads.sampleapp">

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />  <!-- Grants the SDK permission to access a more accurate location based on GPS -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- Grants the SDK permission to access approximate location based on cell tower -->

    <!-- your app description -->
</manifest>

SmartyAds SDK already has the following normal permissions required by the SDK:

  • <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>;
  • <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
  • <uses-permission android:name="android.permission.INTERNET" />

 

Example AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.smartyads.testapplication">

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <!-- required for video ads -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android:name="android.support.multidex.MultiDexApplication" // for MultiDex
        android:allowBackup="true"
        android:icon="@mipmap/pw_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".AdActivity"></activity>
    </application>
</manifest/>

Working with Android 6.0 Runtime Permissions:

If your app's target SDK is 23 or higher and the user's device is running Android 6.0 or higher, you are responsible for supporting runtime permissions, one of the changes introduced in Android 6.0 (API level 23). In addition to listing any dangerous permissions your app needs in the manifest, your app also has to explicitly request the dangerous permission(s) during runtime by calling method requestPermissions() in the ActivityCompat class.

  • Dangerous permission ACCESS_COARSE_LOCATION is needed to pass network location data to MoPub.
  • Dangerous permission ACCESS_FINE_LOCATION is needed to pass GPS location data to MoPub. Granting ACCESS_FINE_LOCATION also allows network location data to be passed to PW without the need to also grant ACCESS_COARSE_LOCATION.
  • Dangerous permission  WRITE_EXTERNAL_STORAGE is optional and only required for MRAID 2.0 storePicture ads.
  • Note: The user can deny granting any dangerous permissions during runtime, so please make sure your app can handle this properly.
  • Note: The user can revoke any permissions granted previously by going to your app's Settings screen, so please make sure your app can handle this properly.

Setting up required parameters in strings.xml

Set the app distribution type (required by SDK) in your strings.xml file:

<integer name="distribution_type">{0|1}</integer>

Where:

  • 0 - app is free
  • 1 - the app is a paid version

Now, add the banner_placement_id to strings.xml:

<string name="banner_placement_id">{your_banner_placement_id_here}</string>

Important!

Do not forget to replace the your_banner_placement_id_here with the placement ID from the Platform:

<string name="banner_placement_id">{1234}</string>

Initializing SmartyAds SDK

Call com.smartyads.Ads#init(Context) method as shown below:

Recommend to invoke this initialization routine at least 10-15 seconds before you intend to load your first ad.

JAVA:

Ads.init(getApplicationContext());

KOTLIN:

Ads.init(baseContext)

Setting GDPR (Requirement)

To make your Android SDK GDPR compliant please set one of the following options:

- SdkConfig.GDPRconsentflag(boolean flag) - set a new value for GDPR user consent. GDPR user consent is a boolean value, where true = user consent given & false = user consent denied or no information provided.

- SdkConfig.getGdprConsentFlag() - get current GDPR value.

JAVA:

SdkConfig.GDPRconsentflag(true);
boolean currentGdprFlag = SdkConfig.getGdprConsentFlag();

KOTLIN:

SdkConfig.GDPRconsentflag(true)
val currentGdprFlag  = SdkConfig.getGdprConsentFlag();

Show Banners

You can configure your banner ad view using XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:smartyads="http://schemas.android.com/apk/res-auto">

   <com.smartyads.adcontainer.BannerContainer
        android:id="@+id/banner_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        smartyads:adContainerId="@string/banner_id"
        smartyads:banner_width="300dp"
        smartyads:banner_height="250dp"
        smartyads:refreshTime="20"
        />

</LinearLayout>

Where

  • smartyads:adContainerId="@string/banner_id" - the placement ID you received
  • smartyads:banner_width="300dp" - placement width
  • smartyads:banner_height="250dp" - placement height
  • smartyads:refreshTime="20" - Optional. Time in seconds after which the banner will expire and will be reloaded automatically. By default 20 sec.

Make sure that xmlns:smartyads="http://schemas.android.com/apk/res-auto" was added to your root layout

Finally, call BannerContainer#loadAd():

JAVA:

BannerContainer bannerContainer = (BannerContainer) findViewById(R.id.banner_container);
bannerContainer.loadAd(new BannerOnLoadListener() {
    @Override
    public void onSuccess() {
        Log.d("YOUR_TAG","Banner succesfully loaded");
    }

    @Override
    public void onFailure(Exception e) {
        Log.e("YOUR_TAG","Cannot load ad: " + e.getMessage());
    }
});

KOTLIN:

banner_container.loadAd(object : BannerOnLoadListener {
    override fun onSuccess() {
        Log.d("TAG", "BannerOnLoadListener : onSuccess")
        banner.showAd(object : OnCacheListener{
        	override fun noAdCache(){
        	    Log.d("TAG", "BannerOnLoadListener : noAdCache")
        	}
        })
    }
    override fun onFailure(p0: Exception?) {
        Log.d("TAG", "BannerOnLoadListener : onFailure: " + p0)
    }
})

There is an alternative method BannerContainer#loadAd(BannerOnLoadListener) that would be useful if you want to create request parameters programmatically.

JAVA:

private FrameLayout mAdContainer;
private BannerContainer bannerContainer;

private int bannerWidth  = 300; // dp
private int bannerHeight = 250; // dp
private int refreshTime  =  20; // sec
private String placementId = getString(R.string.banner_placement_id);
    
mAdContainer = (FrameLayout) findViewById(R.id.ad_container);
bannerContainer = new BannerContainer(this, bannerWidth, bannerHeight, refreshTime, placementId);
mAdContainer.addView(bannerContainer);
bannerContainer.loadAd(new BannerOnLoadListener() {
    @Override
    public void onSuccess() {
        Log.d("YOUR_TAG","Banner succesfully loaded");
        bannerAdContainer.showAd(new OnCacheListener() {
             @Override
             public void noAdCache() {
                Log.d("YOUR_TAG","No any ad in cache");
             }
        });
    }

    @Override
    public void onFailure(Exception e) {
        Log.e("YOUR_TAG","Cannot load ad: " + e.getMessage());
    }
});

KOTLIN:

private lateinit var bannerContainer : BannerContainer
private lateinit var mAdContainer : FrameLayout

private val bannerWidth = 300
private val bannerHeight = 250
private val refreshTime = 20
private val placementId = getString(R.string.banner_id)

mAdContainer = findViewById(R.id.ad_cntainer)
bannerContainer = BannerContainer(this, bannerWidth, bannerHeight, refreshTime, placementId)
mAdContainer.addView(bannerContainer)

banner.loadAd(object : BannerOnLoadListener {
    override fun onSuccess() {
        Log.d("TAG", "BannerOnLoadListener : onSuccess")
        banner.showAd(object : OnCacheListener{
            override fun noAdCache(){
                Log.d("TAG", "BannerOnLoadListener : noAdCache")
            }
        })
    }
    override fun onFailure(p0: Exception?) {
        Log.d("TAG", "BannerOnLoadListener : onFailure: " + p0)
    }
})

Show Interstitial

To show interstitial you just need to initialize ad container and call InterstitialAdContainer#loadAd(BannerOnLoadListener) method as shown in example below:

JAVA:

private InterstitialAdContainer interstitial;

interstitial = new InterstitialAdContainer(this, getString(R.string.interstitial_placement_id));
interstitial.loadAd(new InterstitialListener() {
    @Override
    public void onSuccess() {
        Log.e("YOUR_TAG", "Ad loaded");
        interstitial.showAd(new OnCacheListener() {
             @Override
             public void noAdCache() {
                Log.d("YOUR_TAG","No any ad in cache");
             }
        });
    }

    @Override
    public void onFailure(Exception e) {
        Log.e("YOUR_TAG", "Cannot load interstitial, reason: " + e.getMessage());
    }

    @Override
    public void onClosed() {
        Log.d("YOUR_TAG", "Interstitial closed");
    }
});

KOTLIN:

lateinit var interstitialAdContainer: InterstitialAdContainer	

interstitialAdContainer = InterstitialAdContainer(this,  getString(R.string.interstitial_placement_id))

interstitialAdContainer.loadAd(object : InterstitialListener {
    override fun onClosed() {
        Log.d("TAG", "interstitialAdContainer : Closed")
    }
    
    override fun onSuccess() {
        interstitialAdContainer.showAd(object : OnCacheListener{
    	override fun noAdCache(){
    	    Log.d("TAG", "interstitialAdContainer : noAdCache")
    	}
        })
        Log.d("TAG", "interstitialAdContainer : onSuccess")
    }
    
    override fun onFailure(p0: Exception?) {
        p0?.printStackTrace()
        Log.d("TAG", "interstitialAdContainer : onFailure " + p0)
    }
})

 

Show Vast (Video ad)

Update your AndroidManifest.xml with new permission WRITE_EXTERNAL_STORAGE

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.smartyads.sampleapp">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Required. Allows an application to write to external storage. -->

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />  <!-- Optional. Grants the SDK permission to access a more accurate location based on GPS -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- Optional. Grants the SDK permission to access approximate location based on cell tower -->

    <!-- your app description -->
</manifest>

The usage of VideoContainer exactly the same as the usage of InterstitialAdContainer:

JAVA:

private VideoContainer videoContainer;
videoContainer = new VideoContainer(this, getString(R.string.video_placement_id));
videoContainer.loadAd(new InterstitialListener() {
    @Override
    public void onSuccess() {
        Log.e("YOUR_TAG", "Ad loaded");
        videoContainer.showAd(new OnCacheListener() {
            @Override
            public void noAdCache() {
                Log.d("YOUR_TAG","No any ad in cache");
            }
        });
    }

    @Override
    public void onFailure(Exception e) {
        Log.e("YOUR_TAG", "Cannot load video, reason: " + e.getMessage());
    }

    @Override
    public void onClosed() {
        Log.d("YOUR_TAG", "Video closed");
    }
});

KOTLIN:

lateinit var videoContainer: VideoContainer

videoContainer = VideoContainer(this, getString(R.string.video_placement_id))

videoContainer.loadAd(object : InterstitialListener {
    override fun onClosed() {
	Log.d("TAG", "videoContainer : Closed")
    }

    override fun onSuccess() {
	videoContainer.showAd(object : OnCacheListener{
	    override fun noAdCache(){
		Log.d("TAG", "videoContainer : noAdCache")
	    }
	})
	Log.d("TAG", "videoContainer : onSuccess")
    }

    override fun onFailure(p0: Exception?) {
	p0?.printStackTrace()
	Log.d("TAG", "videoContainer : onFailure " + p0)
    }
})

 

Show Rewarded video ad

Update your AndroidManifest.xml with new permission WRITE_EXTERNAL_STORAGE

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.deema.sampleapp">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Required. Allows an application to write to external storage. -->

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />  <!-- Optional. Grants the SDK permission to access a more accurate location based on GPS -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- Optional. Grants the SDK permission to access approximate location based on cell tower -->

    <!-- your app description -->
</manifest>

The usage of RewardedVvideoContainer exactly the same as the usage of InterstitialAdContainer:

You could give REWARD and AMOUNT fields to RewardedVideoContainer. They will be changed to macros, if those were indicated in the links when creating rewarded video placement on Deema Supply Side Platform

JAVA:

private RewardedVideoContainer rewardedVideoContainer;

rewardedVideoContainer = new RewardedVideoContainer(this, getString(R.string.rewarded_video_placement_id));
rewardedVideoContainer.loadAd(new InterstitialListener() {
    @Override
    public void closed() {
        // Rewarded video closed. Nothing to do here in example case
    }

    @Override
    public void onSuccess() {
        Toast.makeText(AdActivity.this, R.string.success_load, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onFailure(Exception e) {
        showResult(e.getMessage());
    }
});

KOTLIN:

lateinit var rewardedVideoContainer : RewardedVideoContainer
    
rewardedVideoContainer = RewardedVideoContainer(this, getString(R.string.rewarded_video_placement_id))
rewardedVideoContainer.loadAd(object : InterstitialListener {
    override fun onClosed() {
        Log.d("TAG", "interstitialAdContainer : Closed")
    }
    
    override fun onSuccess() {
        interstitialAdContainer.showAd(object : OnCacheListener{
    	override fun noAdCache(){
    	    Log.d("TAG", "interstitialAdContainer : noAdCache")
    	}
        })
        Log.d("TAG", "interstitialAdContainer : onSuccess")
    }
    
    override fun onFailure(p0: Exception?) {
        p0?.printStackTrace()
        Log.d("TAG", "interstitialAdContainer : onFailure " + p0)
    }
})

Show Native

To show native you just need to initialize ad container through Builder and call NativeAdContainer#loadAd(loadListener) method as shown in example below. You should give to a Builder all fields that you specified while creating native placement on SmartyAds Supply Side Platform.

JAVA:

NativeAdContainer native = NativeAdContainer.Builder(getContext(),
  getContext().getString(R.string.native_placement_id))
  .setTitleView(myTitleView)
  .setDescriptionView(myDescriptionView)
  .setSponsoredTextView(mySponsoredTextView)
  .setPriceView(myPriceView)
  .setImageView(myImageView)
  .setCtaView(myActionButton)
  // Another specified fields
  .build();
  
native.loadAd(new NativeOnLoadListener() {
  @Override public void onSuccess() {
    switchLoadingState(false);
    showResult("success");
  }

  @Override public void onFailure(Exception e) {
    switchLoadingState(false);
    showResult("Failure: " + e.getMessage());
  }
});

KOTLIN:

lateinit var nativeAdContainer: NativeAdContainer
nativeAdContainer = NativeAdContainer.Builder(nativeAdContainer)
  .setTitleView(myTitleView)
  .setDescriptionView(myDescriptionView)
  .setSponsoredTextView(mySponsoredTextView)
  .setPriceView(myPriceView)
  .setImageView(myImageView)
  .setCtaView(myActionButton)
  // Another specified fields
  .build();

nativeAdContainer.loadAd(object : NativeOnLoadListener{
    override fun onSuccess() {
        Log.d("TAG", "nativeAdContainer : onSuccess")
    }

    override fun onFailure(p0: Exception?) {
        Log.d("TAG", "nativeAdContainer : onFailure: " + p0)
    }
})

Where R.string.native_placement_id - your native placement id(see #important).

Adding targeting params

Targeting params are data that are provided for the SDK that will improve ad targeting. The params are not required and can be provided if your application has such data. There are three targeting parameters types:

  • Gender: male, female, other - user gender
  • Year of birth - year of a user birthday
  • Keywords - user interests or intents

Usage:

JAVA:

UserKeywords userKeywords = new UserKeywords()
                .addKeywords("interest 1", "interest 2")
                .addKeywords(Collections.singletonList("interest 3"));

interstitialAdContainer.addTargetingData(Gender.MALE)
        .addTargetingData(new YearOfBirth(1990))
        .addTargetingData(userKeywords);

KOTLIN:

val userKeywords = UserKeywords()
        .addKeywords("interest 1", "interest 2")
        .addKeywords(Collections.singletonList("interest 3"))

interstitialAdContainer.addTargetingData(Gender.MALE)
        .addTargetingData(YearOfBirth(1990))
        .addTargetingData(userKeywords);

Rendering Problems in Android Studio

In case you got rendering problems (VerifyError) in Preview mode, add -noverify VM option to Android Studio:

  • Menu Help -> Edit Custom VM Options...
  • Add -noverify key
  • Restart Android Studio

Contact Us

Repo maintainer: support@smartyads.com

Partnership, legal issues, other inquiries: publishers@smartyads.com

https://smartyads.com