-jio-start-block-type-2
-jio-style-title
Mediation is a google feature which helps to maximize publisher Ad fill rate and increase publisher Ad monetization by sending Ad requests to multiple networks to find the best available network to serve ads
There are 2 types of Mediation.
1. Mediation Feature for Google Mobile Ads
2. IMA Mediation
Complete GETTING STARTED section and INITIALIZE SDK section before starting this section.
-jio-style-title
Add Google Mobile Ads library
Step 1: Add Google Mobile Ads library using GMA mediation and add Google Mobile ads library in your project as shown below.
import GoogleMobileAds
-jio-style-title
Add App Permissions
Step 2: Add the following permission in info.plist
of Application.
1. GADApplicationIdentifier
2. SKAdNetworkItems, SKAdNetworkIdentifier: Download the sample app from Google Ads SDK , drag and drop SKAdNetworkItems from sample app's Info.plist.
- GADApplicationIdentifier: This identifier has to be publisher's app ID.
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-5897336307575085~2571722903</string>
<key>GADNativeAdValidatorEnabled</key>
<false/>. // For GMANativeAds only
<key>SKAdNetworkItems</key>
<array>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>cstr6suwn9.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>4fzdc2evr5.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>2fnua5tdw4.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>ydx93a7ass.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>5a6flpkh64.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>p78axxw29g.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>v72qych5uu.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>c6k4g5qg8m.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>s39g8k73mm.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>3qy4746246.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>3sh42y64q3.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>f38h382jlk.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>hs6bdukanm.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>prcb7njmu6.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>wzmmz9fp6w.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>yclnxrl5pm.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>4468km3ulz.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>t38b2kh725.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>7ug5zh24hu.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>9rd848q2bz.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>n6fk4nfna4.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>kbd757ywx3.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>9t245vhmpl.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>2u9pt9hc89.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>8s468mfl3y.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>av6w8kgt66.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>klf5c3l5u5.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>ppxm28t8ap.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>424m5254lk.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>uw77j35x4d.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>e5fvkxwrpn.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>zq492l623r.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>3qcr597p9d.skadnetwork</string>
</dict>
</array>
Follow below link for for more information about custom layout for mediataion
https://developers.google.com/admob/ios/native/advanced
-jio-style-title
Add “GMABannerAdapter
” file shared along JioAds to the app level project file to support banner ads / display ads.
-jio-style-title
Sample Code reference
import Foundation
import UIKit
import GoogleMobileAds
import JioAdsFramework
class GMABannerAdapter: NSObject, JioAdRenderer {
private var bannerView: GAMBannerView?
public var mediationData: JioAdsFramework.MediationModelElement?
private weak var jioAdRenderDelegate: JioAdRendererDelegate?
private var isLoadFromAppendMarkUpData: Bool = false
private var publisherContainer: UIView?
private var adSpotId: String?
required init(adSpotId: String?) {
}
func prepare<T>(delegate: JioAdRendererDelegate, adMarkup: T) {
guard let mediationData = getMediationModel(adMarkup: adMarkup) else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .badRequest), errorUrls: [])
SDKLog("GMABanner Markup Data Failed")
return
}
self.mediationData = mediationData
self.jioAdRenderDelegate = delegate
delegate.prepareSuccess()
}
func load(publisherContainer: UIView, customContainer: UIView?) {
self.bannerView = GAMBannerView.init()
guard let viewControllerToPresent = UIApplication.getTopViewController() else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .renditionError), errorUrls: [])
SDKLog("GMABanner TopViewController Failed")
return
}
self.bannerView?.delegate = self
self.bannerView?.rootViewController = viewControllerToPresent
guard let adunitid = self.mediationData?.adunitid else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .renditionError), errorUrls: [])
SDKLog("GMABanner AdunitId Failed")
return
}
self.bannerView?.frame = CGRect(x: 0, y: 0, width: publisherContainer.frame.width, height: publisherContainer.frame.height)
guard let gmaBanner = self.bannerView else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .renditionError), errorUrls: [])
SDKLog("GMABanner Rendition Failed")
return
}
if UIDevice.current.userInterfaceIdiom == .pad {
// iPad: Only allow 728x90 (Leaderboard)
self.bannerView?.validAdSizes = [
NSValueFromGADAdSize(GADAdSizeLeaderboard) // 728x90
]
} else {
// iPhone: Allow 320x50, 300x250, 320x100
self.bannerView?.validAdSizes = [
NSValueFromGADAdSize(GADAdSizeBanner), // 320x50
NSValueFromGADAdSize(GADAdSizeMediumRectangle), // 300x250
NSValueFromGADAdSize(GADAdSizeLargeBanner) // 320x100
]
}
publisherContainer.addSubview(gmaBanner)
self.publisherContainer = publisherContainer
self.bannerView?.adUnitID = adunitid
self.loadBannerAd()
}
func loadBannerAd() {
DispatchQueue.main.async {
self.bannerView?.load(GAMRequest())
}
}
func getMediationModel<T>(adMarkup: T) -> JioAdsFramework.MediationModelElement? {
guard let admarkUp = adMarkup as? JioAdMarkup, !admarkUp.body.isEmpty else {
return nil
}
guard let mediationData = try? PropertyListDecoder().decode(JioAdsFramework.MediationModelElement.self, from: admarkUp.body) else {
SDKLog("GMABanner Mediation Model Failed")
return nil
}
return mediationData
}
func addListener<T>(listener: T) {
}
func destroy() {
self.bannerView?.removeFromSuperview()
self.bannerView = nil
}
func append<T>(adMarkup: T) {
guard let mediationData = getMediationModel(adMarkup: adMarkup) else {
self.jioAdRenderDelegate?.appendFailed(error: JioAdError(requestError: .badRequest), errorUrls: [])
SDKLog("GMABanner AppendMarkup Data Failed")
return
}
guard let adunitid = mediationData.adunitid else {
self.jioAdRenderDelegate?.appendFailed(error: JioAdError(requestError: .renditionError), errorUrls: [])
SDKLog("GMABanner AppendMarkup Adunitid Failed")
return
}
self.bannerView?.adUnitID = adunitid
self.isLoadFromAppendMarkUpData = true
self.loadBannerAd()
}
/// Return RendererType
///
///
func getRendererType() -> String {
return "GMABannerAdapter"
}
}
extension GMABannerAdapter: GADBannerViewDelegate {
func bannerViewDidReceiveAd(_ bannerView: GADBannerView) {
guard isLoadFromAppendMarkUpData else {
self.jioAdRenderDelegate?.loadSuccess()
return
}
self.jioAdRenderDelegate?.appendSuccess()
}
func bannerView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: Error) {
let jioError = JioAdError.init(title: "bannerView:didFailToReceiveAdWithError", description: "\(error.localizedDescription)", code: JioAdError.RequestError.badRequest.rawValue)
self.jioAdRenderDelegate?.loadFailed(error: jioError, errorUrls: [])
}
func bannerViewDidRecordImpression(_ bannerView: GADBannerView) {
SDKLog("bannerViewDidRecordImpression")
}
func bannerViewWillPresentScreen(_ bannerView: GADBannerView) {
SDKLog("bannerViewWillPresentScreen")
}
func bannerViewWillDismissScreen(_ bannerView: GADBannerView) {
SDKLog("bannerViewWillDIsmissScreen")
}
func bannerViewDidDismissScreen(_ bannerView: GADBannerView) {
SDKLog("bannerViewDidDismissScreen")
}
}
-jio-style-title
Add “GMANativeAdapter
” file shared along JioAds to the app level project file to support native ads such as Infeed / Custom Native.
GADNativeAdValidatorEnabled: Add it in the app's Info.plist and set it true to enables it.
It is used during development to detect issues before submitting the app to production .It should be set to false or remove the key while submitting it to the App Store.
Sample Code:
<key>GADNativeAdValidatorEnabled</key>
<true/>
-jio-style-title
Sample Code reference
import Foundation
import GoogleMobileAds
import UIKit
import JioAdsFramework
class GMANativeAdapter: NSObject, JioAdRenderer {
var customContainer: UIView?
var publisherViewController: UIViewController?
var mediationData: JioAdsFramework.MediationModelElement?
var adLoader: GADAdLoader?
var adUnitID = ""
var gadNativeAdView: GADNativeAdView?
var gadMediaView: GADMediaView?
var calActionView: UIView?
weak var jioAdRenderDelegate: JioAdRendererDelegate?
var isLoadFromAppendMarkUpData: Bool = false
required init(adSpotId: String?) {
}
func prepare<T>(delegate: JioAdsFramework.JioAdRendererDelegate, adMarkup: T) {
guard let mediationData = getMediationModel(adMarkup: adMarkup) else {
SDKLog("GMANativeAd Markup Data Failed")
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .badRequest), errorUrls: [])
return
}
self.mediationData = mediationData
self.jioAdRenderDelegate = delegate
delegate.prepareSuccess()
}
func load(publisherContainer: UIView, customContainer: UIView?) {
self.gadNativeAdView = GADNativeAdView.init()
guard let adunitid = self.mediationData?.adunitid else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .renditionError), errorUrls: [])
SDKLog("GMANative AdunitId Failed")
return
}
self.adUnitID = adunitid // "ca-app-pub-3940256099942544/3986624511"
self.customContainer = customContainer
if let customContainer = customContainer {
publisherContainer.addSubview(customContainer)
}
self.customContainer?.isHidden = true
self.setAdNativeView()
self.loadNativeAd()
}
func setAdNativeView () {
gadNativeAdView = GADNativeAdView.init(frame: CGRect(x: self.customContainer?.frame.origin.x ?? 0, y: self.customContainer?.frame.origin.y ?? 0,
width: self.customContainer?.frame.width ?? 300,
height: self.customContainer?.frame.height ?? 50))
calActionView = UIView.init(frame: CGRect(x: 0,
y: 0,
width: self.customContainer?.frame.width ?? 300,
height: self.customContainer?.frame.height ?? 50))
calActionView?.backgroundColor = .clear
gadNativeAdView?.callToActionView = calActionView
guard let gmaNative = self.gadNativeAdView else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .renditionError), errorUrls: [])
SDKLog("GMANative gmaNativeView Failed")
return
}
guard let calActionView = calActionView else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .renditionError), errorUrls: [])
SDKLog("GMANative calActionView Failed")
return
}
gadMediaView = GADMediaView.init(frame: self.customContainer?.viewWithTag(NativeAdTags.mediaView.rawValue)?.frame ?? .zero)
gmaNative.addSubview(calActionView)
gmaNative.mediaView = gadMediaView
guard let mediaVaiew = gadMediaView else {
SDKLog("GMANative mediaView Failed")
return
}
gmaNative.addSubview(mediaVaiew)
self.customContainer?.viewWithTag(NativeAdTags.mediaView.rawValue)?.addSubview(mediaVaiew)
self.customContainer?.layer.borderWidth = 1.0
self.customContainer?.layer.borderColor = UIColor.lightGray.cgColor
self.customContainer?.addSubview(gmaNative)
}
func getMediationModel<T>(adMarkup: T) -> JioAdsFramework.MediationModelElement? {
guard let admarkUp = adMarkup as? JioAdMarkup, !admarkUp.body.isEmpty else {
SDKLog("GMANative AppendMarkup Data Failed")
return nil
}
guard let mediationData = try? PropertyListDecoder().decode(JioAdsFramework.MediationModelElement.self, from: admarkUp.body) else {
SDKLog("GMANative AppendMarkup Data Failed")
return nil
}
return mediationData
}
func loadNativeAd() {
DispatchQueue.main.async {
guard let viewControllerToPresent = UIApplication.getTopViewController() else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .renditionError), errorUrls: [])
SDKLog("GMANative TopViewController Failed")
return
}
self.adLoader = GADAdLoader(
adUnitID: self.adUnitID, rootViewController: viewControllerToPresent,
adTypes: [.native], options: nil)
self.adLoader?.delegate = self
self.adLoader?.load(GADRequest())
}
}
func append<T>(adMarkup: T) {
guard let mediationData = getMediationModel(adMarkup: adMarkup) else {
self.jioAdRenderDelegate?.appendFailed(error: JioAdError(requestError: .badRequest), errorUrls: [])
return
}
guard let adunitid = mediationData.adunitid else {
SDKLog("GMABanner AppendMarkup Adunitid Failed")
return
}
self.adUnitID = adunitid
self.loadNativeAd()
}
func addListener<T>(listener: T) {
}
func destroy() {
self.gadNativeAdView?.removeFromSuperview()
self.gadNativeAdView = nil
}
/// Return RendererType
///
///
func getRendererType() -> String {
return "GMANativeAdapter"
}
}
extension GMANativeAdapter: GADNativeAdLoaderDelegate, GADNativeAdDelegate, GADAdLoaderDelegate, GADVideoControllerDelegate {
func adLoader(_ adLoader: GADAdLoader, didReceive nativeAd: GADNativeAd) {
populateAdvertisement(adData: nativeAd)
self.customContainer?.isHidden = false
guard isLoadFromAppendMarkUpData else {
self.jioAdRenderDelegate?.loadSuccess()
return
}
self.jioAdRenderDelegate?.appendSuccess()
}
func adLoader(_ adLoader: GADAdLoader, didFailToReceiveAdWithError error: Error) {
let jioError = JioAdError.init(title: "JioGMANativeAdapter", description: "\(error.localizedDescription )", code: JioAdError.RequestError.badRequest.rawValue)
self.jioAdRenderDelegate?.loadFailed(error: jioError, errorUrls: [])
}
private func populateAdvertisement(adData: GADNativeAd) {
guard let customContainer = self.customContainer else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .renditionError), errorUrls: [])
return
}
if let headLine = customContainer.viewWithTag(NativeAdTags.title.rawValue) as? UILabel {
headLine.isHidden = adData.headline == nil
headLine.text = adData.headline
SDKLog("GMA Custom Native title \(headLine)")
} else {
SDKLog("Failed title:\(NativeAdTags.title.rawValue)")
}
if let body = customContainer.viewWithTag(NativeAdTags.desc.rawValue) as? UILabel {
body.isHidden = adData.body == nil
body.text = adData.body
} else {
SDKLog("Failed desc:\(NativeAdTags.desc.rawValue)")
}
if let iconImage = customContainer.viewWithTag(NativeAdTags.iconImageView.rawValue) as? UIImageView {
iconImage.isHidden = adData.icon?.image == nil
iconImage.image = adData.icon?.image
} else {
SDKLog("Failed IconImage:\(NativeAdTags.iconImageView.rawValue)")
}
if let mainImageView = customContainer.viewWithTag(NativeAdTags.mainImageView.rawValue) as? UIImageView {
if let images = adData.images, !images.isEmpty,
let firstImage = images.first?.image {
mainImageView.image = firstImage
mainImageView.isHidden = false
SDKLog("GMA Native image \(firstImage)")
} else {
mainImageView.isHidden = true
}
} else {
SDKLog("Failed mainImage:\(NativeAdTags.mainImageView.rawValue)")
}
if let ctaButton = customContainer.viewWithTag(NativeAdTags.ctaButton.rawValue) as? UIButton {
ctaButton.isHidden = adData.callToAction == nil
ctaButton.setTitle(adData.callToAction, for: .normal)
SDKLog("GMA Custom CTA Text \(String(describing: adData.callToAction))")
ctaButton.isUserInteractionEnabled = false
} else {
SDKLog("Failed mainImage:\(NativeAdTags.ctaButton.rawValue)")
}
if let mediatView = customContainer.viewWithTag(NativeAdTags.mediaView.rawValue) {
mediatView.isHidden = false
self.gadNativeAdView?.mediaView?.mediaContent = adData.mediaContent
} else {
SDKLog("Failed mainImage:\(NativeAdTags.mediaView.rawValue)")
}
self.gadNativeAdView?.nativeAd = adData
}
}
-jio-style-title
Add “GMAInterstitial
” file shared along JioAds to the app level project file to support ads such as Interstitial/Rewarded Interstitial /Rewarded Video Ads.
-jio-style-title
Sample Code reference
import Foundation
import UIKit
import GoogleMobileAds
import JioAdsFramework
class GMAInterstitial: NSObject, JioAdRenderer {
private let TAG = "GMAInterstitial"
private var interstitial: GADInterstitialAd?
private var interstitialReward: GADRewardedInterstitialAd?
private var rewardedAd: GADRewardedAd?
weak private var jioAdRenderDelegate: JioAdRendererDelegate?
private var request: GADRequest?
public var mediationData: JioAdsFramework.MediationModelElement?
private var isRewardAvailable = false
required init(adSpotId: String?) {
SDKLog("\(TAG) init")
}
func prepare<T>(delegate: JioAdsFramework.JioAdRendererDelegate, adMarkup: T) {
SDKLog("\(TAG) prepare")
self.jioAdRenderDelegate = delegate
guard let admarkUp = adMarkup as? JioAdsFramework.JioAdMarkup, !admarkUp.body.isEmpty else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .badRequest), errorUrls: [])
return
}
guard let mediationData = try? PropertyListDecoder().decode(JioAdsFramework.MediationModelElement.self, from: admarkUp.body) else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .badRequest), errorUrls: [])
return
}
self.mediationData = mediationData
delegate.prepareSuccess()
}
func load(publisherContainer: UIView, customContainer: UIView?) {
SDKLog("\(TAG) load")
self.request = GADRequest()
DispatchQueue.main.async {
if self.mediationData?.code == .rewardedInterstitial {
self.loadRewardedInterstitial()
} else if self.mediationData?.code == .rewarded {
self.loadRewarded()
} else {
self.loadInterstitial()
}
}
}
fileprivate func loadInterstitial() {
guard let adunitid = self.mediationData?.adunitid else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .renditionError), errorUrls: [])
SDKLog("\(TAG) AdunitId Failed")
return
}
self.interstitial = GADInterstitialAd.init()
GADInterstitialAd.load( withAdUnitID: adunitid, request: self.request) { (adValue, error) in
guard error == nil else {
let jioError = JioAdError.init(title: "Failed to load interstitial ad with error",
description: "\(error?.localizedDescription ?? "")",
code: JioAdError.RequestError.badRequest.rawValue)
self.jioAdRenderDelegate?.loadFailed(error: jioError, errorUrls: [])
return
}
guard let adObject = adValue else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .badRequest), errorUrls: [])
return
}
self.interstitial = adObject
self.interstitial?.fullScreenContentDelegate = self
guard let viewControllerToPresent = UIApplication.getTopViewController() else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .renditionError), errorUrls: [])
return
}
adObject.present(fromRootViewController: viewControllerToPresent)
}
}
fileprivate func loadRewardedInterstitial() {
guard let adunitid = self.mediationData?.adunitid else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .renditionError), errorUrls: [])
SDKLog("\(TAG) AdunitId Failed")
return
}
self.interstitialReward = GADRewardedInterstitialAd.init()
GADRewardedInterstitialAd.load( withAdUnitID: adunitid, request: self.request) { (adValue, error) in
guard error == nil else {
let jioError = JioAdError.init(title: "Failed to load interstitial ad with error",
description: "\(error?.localizedDescription ?? "")",
code: JioAdError.RequestError.badRequest.rawValue)
self.jioAdRenderDelegate?.loadFailed(error: jioError, errorUrls: [])
return
}
guard let adObject = adValue else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .badRequest), errorUrls: [])
return
}
self.interstitialReward = adObject
self.interstitialReward?.fullScreenContentDelegate = self
guard let viewControllerToPresent = UIApplication.getTopViewController() else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .renditionError), errorUrls: [])
return
}
adObject.present(fromRootViewController: viewControllerToPresent) {
let reward = adObject.adReward
SDKLog("\(self.TAG) | Reward received with currency \(reward.amount), amount \(reward.amount.doubleValue)")
self.isRewardAvailable = true
}
}
}
fileprivate func loadRewarded() {
guard let adunitid = self.mediationData?.adunitid else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .renditionError), errorUrls: [])
SDKLog("\(TAG) RewardAdunitId Failed")
return
}
self.rewardedAd = GADRewardedAd.init()
GADRewardedAd.load( withAdUnitID: adunitid, request: self.request) { (adValue, error) in
guard error == nil else {
let jioError = JioAdError.init(title: "Failed to load interstitial ad with error",
description: "\(error?.localizedDescription ?? "")",
code: JioAdError.RequestError.badRequest.rawValue)
self.jioAdRenderDelegate?.loadFailed(error: jioError, errorUrls: [])
return
}
guard let adObject = adValue else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .badRequest), errorUrls: [])
return
}
self.rewardedAd = adObject
self.rewardedAd?.fullScreenContentDelegate = self
guard let viewControllerToPresent = UIApplication.getTopViewController() else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .renditionError), errorUrls: [])
return
}
adObject.present(fromRootViewController: viewControllerToPresent) {
let reward = adObject.adReward
SDKLog("\(self.TAG) | Reward received with currency \(reward.amount), amount \(reward.amount.doubleValue)")
self.isRewardAvailable = true
}
}
}
func append<T>(adMarkup: T) { }
func addListener<T>(listener: T) { }
func destroy() {
self.isRewardAvailable = false
}
func getRendererType() -> String {
return TAG
}
}
extension GMAInterstitial: GADFullScreenContentDelegate {
func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
SDKLog("\(TAG) Ad failed to present full screen content with error \(error.localizedDescription).")
let jioError = JioAdError.init(title: "Ad failed to present full screen content with error", description: "\(error.localizedDescription)", code: JioAdError.RequestError.badRequest.rawValue)
self.jioAdRenderDelegate?.loadFailed(error: jioError, errorUrls: [])
}
func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
SDKLog("\(TAG) | dismiss full screeen")
// self.adView?.delegate?.onAdClosed(adView: self.adView ?? JioAdView(), isVideoCompleted: true, isEligibleForReward: isRewardAvailable)
jioAdRenderDelegate?.renditionComplete()
}
}
-jio-style-title
Add SDK Packages & Files in App
Step 1: Add the required Google IMA Adapter in the code.
-jio-style-title
Add SDK Dependencies in App
Step 2: Add JioAds Adapter IMAAdapter.swift
shared along with JioAds library.
Step 3: Include the below dependency in your app level project file
import GoogleInteractiveMediaAds
-jio-style-title
import Foundation
import UIKit
import GoogleInteractiveMediaAds
import JioAdsFramework
class IMAAdapter: NSObject, JioAdRenderer, AVPictureInPictureControllerDelegate {
private let TAG = "IMAAdapter"
private var mediationData: JioAdsFramework.MediationModelElement?
private var adsLoader: IMAAdsLoader?
private var adsManager: IMAAdsManager?
private var refreshTimer: Timer?
private var isTapped = false
private var isStopViewport = false
private var playButton: UIButton?
weak private var jioAdRenderDelegate: JioAdRendererDelegate?
private var customContainer: UIView?
private var durationRenderered = 0
private var mediaRenderer: JioMediaRenderer?
private var jioViewPortObserverManager: JioViewPortObserverManager?
private var viewPortStatus: ViewPortStatus?
required override init() {
SDKLog("\(TAG) init")
}
func prepare<T>(delegate: JioAdRendererDelegate, adMarkup: T) {
SDKLog("\(TAG) prepare")
guard let admarkUp = adMarkup as? JioAdMarkup, !admarkUp.body.isEmpty else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .badRequest), errorUrls: [])
return
}
guard let mediationData = try? PropertyListDecoder().decode(JioAdsFramework.MediationModelElement.self, from: admarkUp.body) else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .badRequest), errorUrls: [])
return
}
self.mediationData = mediationData
self.jioAdRenderDelegate = delegate
delegate.prepareSuccess()
}
func load(publisherContainer: UIView, customContainer: UIView?) {
SDKLog("\(TAG) load")
let iamSetting = IMASettings()
iamSetting.enableBackgroundPlayback = true
adsLoader = IMAAdsLoader(settings: iamSetting)
adsLoader?.delegate = self
self.customContainer = publisherContainer
self.loadImaVideoAd(customContainer: publisherContainer)
}
func loadImaVideoAd(customContainer: UIView?) {
SDKLog("\(TAG) loadImaVideoAd")
guard let viewControllerToPresent = UIApplication.getTopViewController() else {
self.jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .renditionError), errorUrls: [])
return
}
let adDisplayContainer = IMAAdDisplayContainer(
adContainer: customContainer ?? UIView(), viewController: viewControllerToPresent, companionSlots: nil)
let adRequest = IMAAdsRequest(adTagUrl: self.mediationData?.adtagcode ?? "", adDisplayContainer: adDisplayContainer, contentPlayhead: nil, userContext: nil)
self.adsLoader?.requestAds(with: adRequest)
self.adsManager?.start()
}
func append<T>(adMarkup: T) { }
func addListener<T>(listener: T) {
if let mediaRenderer = listener as? JioMediaRenderer {
self.mediaRenderer = mediaRenderer
}
if let jioViewPortObserverManager = listener as? JioViewPortObserverManager {
self.jioViewPortObserverManager = jioViewPortObserverManager
jioViewPortObserverManager.add(delegate: self)
}
}
func getRendererType() -> String {
return TAG
}
func destroy() {
SDKLog("\(TAG) destroy")
adsManager?.destroy()
adsManager = nil
mediationData = nil
adsLoader = nil
adsManager = nil
refreshTimer = nil
jioAdRenderDelegate = nil
mediaRenderer = nil
jioViewPortObserverManager = nil
viewPortStatus = nil
}
fileprivate func completeIma() {
self.mediaRenderer?.mediaRenditionComplete(duration: durationRenderered, count: 1)
self.jioAdRenderDelegate?.renditionComplete()
}
@objc func viewPortVisibliltyCheck() {
guard self.adsManager != nil else {
return
}
}
}
extension IMAAdapter: IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
func adsLoader(_ loader: IMAAdsLoader, adsLoadedWith adsLoadedData: IMAAdsLoadedData) {
SDKLog("\(TAG) adsLoader adsLoadedWith ")
self.adsManager = adsLoadedData.adsManager
self.adsManager?.delegate = self
let adsRenderingSettings = IMAAdsRenderingSettings()
self.adsManager?.initialize(with: adsRenderingSettings)
}
func adsLoader(_ loader: IMAAdsLoader, failedWith adErrorData: IMAAdLoadingErrorData) {
SDKLog("\(TAG) Error loading IMA Ad: \(adErrorData.adError.message ?? "nil") \(adErrorData.adError.code) ")
jioAdRenderDelegate?.loadFailed(error: JioAdError(requestError: .mediationError), errorUrls: [])
}
func adsManager(_ adsManager: IMAAdsManager, didReceive event: IMAAdEvent) {
SDKLog("\(TAG) : adsManager didReceive \(event.typeString) ")
if event.type == IMAAdEventType.LOADED {
self.jioViewPortObserverManager?.startObserver()
SDKLog("\(TAG) onPlayStarted | SelectedAdId | videoAdplayed ima mediation")
} else if event.type == IMAAdEventType.STARTED {
let duration = adsManager.adPlaybackInfo.totalMediaTime
durationRenderered += Int(duration.rounded())
DispatchQueue.main.async {
self.playButton = UIButton.init(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
self.playButton?.addTarget(self, action: #selector(self.playButtonTapped(_:)), for: .touchUpInside)
self.playButton?.isUserInteractionEnabled = true
self.customContainer?.addSubview(self.playButton ?? UIButton())
self.playButton?.center = self.customContainer?.center ?? .zero
}
} else if event.type == IMAAdEventType.SKIPPED {
completeIma()
} else if event.type == IMAAdEventType.CLICKED {
adsManager.pause()
isStopViewport = true
} else if event.type == IMAAdEventType.TAPPED {
isTapped.toggle()
isStopViewport = isTapped
if isTapped {
adsManager.pause()
} else {
adsManager.resume()
}
} else if event.type == IMAAdEventType.COMPLETE {
completeIma()
}
}
func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager) {
SDKLog("\(TAG) adsManagerDidRequestContentPause")
}
func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager) {
SDKLog("\(TAG) adsManagerDidRequestContentResume")
}
func adsManager(_ adsManager: IMAAdsManager, adDidProgressToTime mediaTime: TimeInterval, totalTime: TimeInterval) { }
func adsManager(_ adsManager: IMAAdsManager, didReceive error: IMAAdError) {
SDKLog("\(TAG) didReceive \(error)")
}
@objc func playButtonTapped(_ sender: UIButton? = nil) {
isTapped.toggle()
isStopViewport = isTapped
if isTapped {
adsManager?.pause()
} else {
adsManager?.resume()
}
}
}
extension IMAAdapter: JioViewPortObserverDelegate {
func viewPortStatusUpdate(status: JioAdsFramework.ViewPortStatus?, percentage: CGFloat?) {
guard let status = status else {
return
}
guard let _ = self.viewPortStatus else {
// This block should execute once initially when viewPortStatus is nil
if status == .inPort {
self.adsManager?.start()
jioAdRenderDelegate?.loadSuccess()
self.viewPortStatus = .inPort
}
return
}
// This block of code should trigger whenever there is a viewPortStatus update
self.viewPortStatus = status
switch status {
case .inPort:
adsManager?.resume()
case .outOfPort:
adsManager?.pause()
}
}
}
-jio-end-block-type-2