Skip to content

Instantly share code, notes, and snippets.

@hoanghiephui
Last active March 31, 2021 12:53
Show Gist options
  • Save hoanghiephui/eb018f7b3556fa63e688b6ece37ee568 to your computer and use it in GitHub Desktop.
Save hoanghiephui/eb018f7b3556fa63e688b6ece37ee568 to your computer and use it in GitHub Desktop.
Mediation Mopub Native
class AdLoader {
/**
* Call this method to load Native ad
* @param context : Activity Context
* @param customAdListener : Custom Ad Listener to get - ad loaded, clicked, impression, failed callback
* @param adType : Custom Class for different type of Ad Formats - Banner, Native, Interstitial
* @param adapterHelper : AdapterHelper from MoPub
* @param moPubNativeEventListener : MoPub specific class to track impression & click
*/
private var moPubNative: MoPubNative? = null
private var nativeBannerAd: NativeBannerAd? = null
var isLoad = false
private var loadFail = 0
fun loadNativeAds(
context: Context,
adUnitId: String,
customAdListener: CustomAdListener,
adType: AdType,
adapterHelper: AdapterHelper,
moPubNativeEventListener: MoPubNativeEventListener
) {
if (moPubNative == null) {
moPubNative = MoPubNative(
context,
adUnitId,
getMoPubNativeNetworkListener(
adapterHelper,
customAdListener,
moPubNativeEventListener
)
).apply {
requestAndLoadNativeAd(context, this, adType)
}
} else {
moPubNative?.apply {
requestAndLoadNativeAd(context, this, adType)
}
}
}
fun loadNativeAds(
context: Context,
adUnitId: String,
isUseMediation: Boolean,
customAdListener: CustomAdListener,
adType: AdType,
adapterHelper: AdapterHelper = AdapterHelper(context, 0, 2),
moPubNativeEventListener: MoPubNativeEventListener
) {
if (isUseMediation) {
loadNativeAds(
context,
adUnitId,
customAdListener,
adType,
adapterHelper,
moPubNativeEventListener
)
} else {
if (nativeBannerAd == null) {
nativeBannerAd =
NativeBannerAd(
context,
adUnitId
)
nativeBannerAd?.apply {
loadAdFan(context, customAdListener)
}
} else {
nativeBannerAd?.destroy()
nativeBannerAd = null
nativeBannerAd =
NativeBannerAd(
context,
adUnitId
)
nativeBannerAd?.apply {
if (!isAdLoaded) {
loadAdFan(context, customAdListener)
} else {
destroy()
CoroutineScope(Job() + Dispatchers.Main).launch {
delay(1000)
loadAdFan(context, customAdListener)
}
}
}
}
}
}
private fun NativeBannerAd.loadAdFan(
context: Context,
customAdListener: CustomAdListener
) {
loadAd(
this.buildLoadAdConfig()
.withAdListener(
nativeAdListener(
context,
mCustomAdListener = customAdListener
)
)
.withMediaCacheFlag(NativeAdBase.MediaCacheFlag.ALL)
.build()
)
}
/**
* This method integrates view binders & ad renderer for both MoPub & FAN, then request Ad to mopub
* @param moPubNative : MoPubNative object
* @param adType : Custom Class for different type of Ad Formats - Banner, Native, Interstitial
*/
private fun requestAndLoadNativeAd(context: Context, moPubNative: MoPubNative, adType: AdType) {
// mopub view binder
val moPubNativeViewBinder =
when (adType) {
AdType.NATIVE_MEDIUM -> {
ViewBinder.Builder(R.layout.native_ad_mopub_list_item)
.iconImageId(R.id.native_icon_image)
.titleId(R.id.native_title)
.textId(R.id.native_text)
.mainImageId(R.id.native_main_image)
.privacyInformationIconImageId(R.id.native_privacy_information_icon_image)
.sponsoredTextId(R.id.native_sponsored_text_view)
.callToActionId(R.id.native_cta)
.build()
}
AdType.NATIVE_SMALL -> {
ViewBinder.Builder(R.layout.native_banner_ad_mopub)
.iconImageId(R.id.native_icon_image)
.titleId(R.id.native_title)
.textId(R.id.native_text)
.privacyInformationIconImageId(R.id.native_privacy_information_icon_image)
.callToActionId(R.id.native_cta)
.build()
}
}
// mopub native ad renderer
val moPubStaticNativeAdRenderer = MoPubStaticNativeAdRenderer(moPubNativeViewBinder)
// facebook view binder
val facebookAdRenderer =
when (adType) {
AdType.NATIVE_MEDIUM -> {
val facebookViewBinder =
FacebookAdRenderer.FacebookViewBinder.Builder(R.layout.native_ad_fan_list_item)
.titleId(R.id.native_title)
.textId(R.id.native_text)
// Binding to new layouts from Facebook 4.99.0+
.mediaViewId(R.id.native_media_view)
.adIconViewId(R.id.native_icon)
.adChoicesRelativeLayoutId(R.id.native_privacy_information_icon_layout)
.advertiserNameId(R.id.textView85) // Bind either the titleId or advertiserNameId depending on the FB SDK version
// End of binding to new layouts
.callToActionId(R.id.native_cta)
.build()
FacebookAdRenderer(facebookViewBinder)
}
AdType.NATIVE_SMALL -> {
val facebookViewBinder =
FacebookAdRenderer.FacebookViewBinder.Builder(R.layout.native_banner_ad_fan)
.titleId(R.id.native_ad_title)
.textId(R.id.native_ad_text)
// Binding to new layouts from Facebook 4.99.0+
.adIconViewId(R.id.native_icon_view)
.adChoicesRelativeLayoutId(R.id.ad_choices_container)
.advertiserNameId(R.id.native_ad_social_context) // Bind either the titleId or advertiserNameId depending on the FB SDK version
// End of binding to new layouts
.callToActionId(R.id.native_ad_call_to_action)
.build()
FacebookAdRenderer(facebookViewBinder)
}
}
// this is needed for Facebook Native Ad
moPubNative.setLocalExtras(getFBLocalExtra(adType))
// register Facebook Ad Renderer
moPubNative.registerAdRenderer(facebookAdRenderer)
// register MoPub Ad Renderer - Always add this in last
moPubNative.registerAdRenderer(moPubStaticNativeAdRenderer)
// Setting desired assets on your request helps native ad networks and bidders
// provide higher-quality ads.
val desiredAssets =
when (adType) {
AdType.NATIVE_MEDIUM -> {
EnumSet.of(
NativeAdAsset.TITLE,
NativeAdAsset.TEXT,
NativeAdAsset.ICON_IMAGE,
NativeAdAsset.MAIN_IMAGE,
NativeAdAsset.CALL_TO_ACTION_TEXT,
NativeAdAsset.SPONSORED
)
}
AdType.NATIVE_SMALL -> {
EnumSet.of(
NativeAdAsset.TITLE,
NativeAdAsset.TEXT,
NativeAdAsset.ICON_IMAGE,
NativeAdAsset.CALL_TO_ACTION_TEXT,
NativeAdAsset.SPONSORED
)
}
}
val mRequestParameters = RequestParameters.Builder()
.desiredAssets(desiredAssets)
.build()
// make request to MoPub which internally talk to FAN also
moPubNative.makeRequest(mRequestParameters)
}
/**
* This provides FAN related parameters for Native Ads
* @param adType : Custom Class for different type of Ad Formats - Banner, Native, Interstitial
*/
private fun getFBLocalExtra(adType: AdType): HashMap<String, Any> {
val localExtras = HashMap<String, Any>()
return when (adType) {
AdType.NATIVE_MEDIUM -> {
localExtras["native"] = true
localExtras
}
AdType.NATIVE_SMALL -> {
localExtras["native_banner"] = true
localExtras
}
}
}
/**
* Returns MoPub Native Network Listener which gives callback when native is loaded or failed
* @param adapterHelper : AdapterHelper from MoPub
* @param mCustomAdListener : Custom Ad Listener to get - ad loaded, clicked, impression, failed callback
* @param moPubNativeEventListener : MoPub specific class to track impression & click
* @return MoPubNativeNetworkListener : Network listener for Ad Loading
*/
private fun getMoPubNativeNetworkListener(
adapterHelper: AdapterHelper,
mCustomAdListener: CustomAdListener,
moPubNativeEventListener: MoPubNativeEventListener
): MoPubNative.MoPubNativeNetworkListener {
return object : MoPubNative.MoPubNativeNetworkListener {
override fun onNativeLoad(nativeAd: com.mopub.nativeads.NativeAd?) {
// Retrieve the pre-built ad view that AdapterHelper prepared for us.
val renderedAdView =
adapterHelper.getAdView(null, null, nativeAd, ViewBinder.Builder(0).build())
// Set the native event listeners (onImpression, and onClick).
nativeAd?.setMoPubNativeEventListener(moPubNativeEventListener)
mCustomAdListener.onNativeAdLoaded(renderedAdView)
isLoad = true
}
override fun onNativeFail(errorCode: NativeErrorCode?) {
mCustomAdListener.onAdFailed(errorCode?.intCode)
if (loadFail == 1) {
isLoad = true
}
loadFail++
}
}
}
fun onDestroy() {
moPubNative?.destroy()
moPubNative = null
nativeBannerAd?.apply {
unregisterView()
destroy()
}
nativeBannerAd = null
loadFail = 0
isLoad = false
}
private fun nativeAdListener(
context: Context,
mCustomAdListener: CustomAdListener
) = object : NativeAdListener {
override fun onError(ad: Ad, error: AdError) {
Timber.e(error.errorMessage)
mCustomAdListener.onAdFailed(error.errorCode)
if (loadFail == 1) {
isLoad = true
}
loadFail++
}
override fun onAdLoaded(ad: Ad) {
if (nativeBannerAd == null || nativeBannerAd != ad) {
return
}
isLoad = true
nativeBannerAd?.let {
// Create a NativeAdViewAttributes object and set the attributes
val attributes =
NativeAdViewAttributes(context)
.setBackgroundColor(context.getColorAttr(android.R.attr.windowBackground))
.setTitleTextColor(context.getColorAttr(R.attr.colorControlNormal))
.setDescriptionTextColor(context.getColorAttr(R.attr.colorControlNormal))
.setButtonTextColor(context.getColorCompat(R.color.white))
.setButtonColor(context.getColorCompat(R.color.blue_600))
// Use NativeAdView.render to generate the ad View
val adView = NativeBannerAdView.render(
context,
it,
NativeBannerAdView.Type.HEIGHT_120,
attributes
)
mCustomAdListener.onNativeAdLoaded(adView)
}
}
override fun onAdClicked(ad: Ad) {
}
override fun onLoggingImpression(ad: Ad) {
}
override fun onMediaDownloaded(ad: Ad?) {
}
}
companion object {
fun adapterHelper(context: Context) = AdapterHelper(context, 0, 2)
}
}
enum class AdType {
NATIVE_MEDIUM, NATIVE_SMALL
}
interface CustomAdListener {
fun onNativeAdLoaded(view: View)
fun onAdFailed(errorCode: Int?)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment