Boltive Android SDK is a native Android library for intercepting malicious ad creatives.
Quick facts:
-
SDK currently supports banner and interstitial ad formats.
-
SDK has been explicitly tested against GAM, AdMob, AppLovin MAX, however the SDK is not limited to these integration scenarios, please see this section
-
The current SDK version is 1.3. See release notes.
- Add maven repository to your *.gradle file (settings.gradle for Gradle 7+)
repositories {
maven {
url "https://packagecloud.io/Boltive/Mobile-SDK/maven2"
}
}
- Add Boltive dependency
dependencies {
implementation "com.boltive:boltive-sdk:1.3.18"
}
- Download the SDK zip archive and unzip it:
curl -OL http://d29z9h4vafd34g.cloudfront.net/android/boltive-android-sdk-1.3.18.zip
unzip boltive-android-sdk-1.3.18.zip
- Create
libs
directory inside yourapp
module. - Copy
boltive-android-sdk.aar
library from archive intolibs
. - Add Boltive SDK dependency in app's
build.gradle
file and sync Gradle.
dependencies {
implementation files("libs/boltive-android-sdk.aar")
}
To connect Boltive SDK with the GAM banner you should call BoltiveMonitor.capture()
static method
within the AdListener
's onAdLoaded()
method, passing it an ad banner, clientId
and BoltiveListener
instance as parameters. BoltiveListener
is called in the event
when BoltiveMonitor
detects an ad that is supposed to be blocked.
Note: BoltiveMonitor
blocker will prevent the malicious ad creative from rendering - so the ad would become blank,
however it will not automatically remove the native banner view from the screen (so worst case the user will see a blank ad).
It will send a signal to the app native code (via the callback mechanism).
Then it is the responsibility of the app developer to take the appropriate action in the callback function: f.e. reload and refresh the
banner, render a different ad unit, remove the banner altogether etc. The most common action to
take would be to call the native method that would reload the banner.
Create Boltive monitor instance.
private final BoltiveMonitor boltiveMonitor = new BoltiveMonitor(
new BoltiveConfiguration("<your client id>")
);
Add capture
call inside AdListener's onAdLoaded
with listener.
You should pass more information about your app using BoltiveTagDetails object inside AdViewConfiguration's constructor.
AdRequest adRequest = new AdRequest.Builder().build();
gamBannerView.setAdListener(new AdListener() {
@Override
public void onAdLoaded() {
AdViewConfiguration adViewConfiguration = new AdViewConfiguration(
"<banner width>", "<banner height>", "<your ad unit id>"
);
boltiveMonitor.capture(gamBannerView, adViewConfiguration, ()-> {
gamBannerView.loadAd(adRequest);
});
}
});
gamBannerView.loadAd(adRequest);
Add terminate
call when ad view destroyed or inside onDestroy
of Activity (or Fragment).
@Override
protected void onDestroy(){
super.onDestroy();
boltiveMonitor.terminate();
}
If you don't want to show an ad unit after the ad has been blocked within it, you can remove the ad view from the view tree:
boltiveMonitor.capture(gamBannerView, adViewConfiguration, () -> {
ViewParent parent = gamBannerView.getParent();
if (parent instanceof ViewGroup){
((ViewGroup) parent).removeView(gamBannerView);
}
}
Add captureInterstitial
call before calling interstitial.show
. Also make sure you call BoltiveMonitor.stopCapturingInterstitial
inside interstitial's FullScreenContentCallback.onAdDismissedFullScreenContent
, see example below:
AdRequest adRequest = new AdRequest.Builder().build();
AdManagerInterstitialAd.load(this, "<your ad unit id>", adRequest, new InterstitialAdLoadCallback() {
@Override
public void onAdLoaded(@NonNull InterstitialAd interstitialAd){
super.onAdLoaded(interstitialAd);
AdViewConfiguration viewConfiguration = new AdViewConfiguration(
320, 480, "<your ad unit id>"
);
boltiveMonitor.captureInterstitial(getApplication(), viewConfiguration, interstitialAd, ()-> {
// Any Actions
})
interstitialAd.setFullScreenContentCallback(new FullScreenContentCallback() {
@Override
public void onAdDismissedFullScreenContent() {
super.onAdDismissedFullScreenContent();
boltiveMonitor.stopCapturingInterstitial();
}
});
interstitialAd.show(MyActivity.this);
});
};
You should pass more information about your app using BoltiveTagDetails object inside AdViewConfiguration's constructor. Don't forget to pass InterstitialAd parameter to BoltiveMonitor.captureInterstitial
.
Note: When Boltive SDK detects an offensive interstitial - it automatically blocks and dismisses it (contrary to the behavior for banners, where it is a developer responsibility), providing you with a callback (you implement it as an anonymous function passed to BoltiveMonitor.captureInterstitial
) where you can reload the interstitial and/or perform any other side effects as necessary.
Create Boltive monitor instance. IMPORTANT to set second parameter AdNetwork.APPLOVIN_MAX
. You should pass more information about your app using BoltiveTagDetails object inside AdViewConfiguration's constructor.
private final BoltiveMonitor boltiveMonitor = new BoltiveMonitor(
new BoltiveConfiguration("<your client id>", AdNetwork.APPLOVIN)
);
Add capture
call inside MaxAdViewAdListener's onAdLoaded
with listener.
private void initAd() {
adViewContainer.removeAllViews();
maxAdView = new MaxAdView(adUnitId, this);
maxAdView.setListener(new MaxAdViewAdListener() {
@Override
public void onAdLoaded(MaxAd ad) {
AdViewConfiguration adViewConfiguration = new AdViewConfiguration(
"<banner width>", "<banner height>", "<your ad unit id>"
);
boltiveMonitor.capture(maxAdView, adViewConfiguration, () -> {
maxAdView.destroy();
initAd();
});
}
...
});
adViewContainer.addView(maxAdView);
maxAdView.loadAd();
}
Add terminate
call when ad view is destroyed or inside the onDestroy
method of the Activity (or Fragment).
@Override
protected void onDestroy(){
super.onDestroy();
boltiveMonitor.terminate();
}
Add captureInterstitial
call before calling interstitial.showAd()
, and stopCapturingInterstitial
inside onAdHidden
.
You should pass more information about your app using BoltiveTagDetails object inside AdViewConfiguration's constructor.
MaxInterstitialAd interstitial = new MaxInterstitialAd("<your ad unit id>", this);
interstitial.setListener(new MaxAdListener() {
@Override
public void onAdLoaded(MaxAd ad) {
AdViewConfiguration viewConfiguration = new AdViewConfiguration(
320, 480, "<your ad unit id>"
);
boltiveMonitor.captureInterstitial(getApplication(), viewConfiguration, () -> {});
interstitial.showAd();
}
@Override
public void onAdHidden(MaxAd ad) {
boltiveMonitor.stopCapturingInterstitial();
}
...
});
Consider using WeakReference
for the ad view reference that you use
inside the BoltiveListener
callback that is passed into the capture()
call to prevent memory leaks.
private static class SafeBoltiveListener implements BoltiveListener {
private final WeakReference<AdView> adView;
public SafeBoltiveListener(AdView adView) {
this.adView = new WeakReference<>(adView);
}
@Override
public void onAdBlocked() {
AdView view = this.adView.get();
if (view != null) {
view.loadAd();
}
}
}
Usage:
boltiveMonitor.capture(adView, adViewConfiguration, new SafeBoltiveListener(adView));
As part of the AdViewConfiguration
you can pass a tagDetails
object, containing data handy for reporting and attribution of the ad blocking events.
BoltiveTagDetails tagDetails = new BoltiveTagDetails("<your ad unit id>");
tagDetails.setAppName("<you app name>");
tagDetails.setAdvertiserId("<your advertiser id>");
tagDetails.setCampaignId("<your campaign id>");
tagDetails.setCreativeId("<your creative id>");
tagDetails.setLineItemId("<your line item id>");
tagDetails.setSspRefreshCode("<your ssp refresh code>");
AdViewConfiguration viewConfig = new AdViewConfiguration(300, 250, tagDetails);
monitor.capture(adView, viewConfig, () -> { ... })
Please note that if any of the ad server details properties are not set (advertiserId
, campaignId
, creativeId
, lineItemId
) - Boltive SDK will attempt to fill them from ResponseInfo
object in case of Google Mobile Ads SDK.
Boltive SDK
has been tested against GAM, AdMob (Google Mobile Ads SDK) and AppLovin MAX integration scenarios. However BoltiveMonitor
API is designed to be SDK-agnostic. The only assumption it makes is that the ad is rendered in
the WebView
object contained somewhere within a View
-based banner view hierarchy. Most ad SDKs
use the same integration patterns as Google Mobile Ads SDK - thus the usage of BoltiveMonitor
with them would be similar.
Google Ad Manager and AdMob assume the integration of Google Mobile Ads SDK into the app.
Applovin MAX assumes integration of Applovin MAX Mobile Ads SDK into the app.