SDK 8 Mopub Mediation Native
於 2021年8月24日 (二) 01:54 由 imported>Wikiuser 所做的修訂 (→TAMediaCustomNativeAdEvent(必要))
官方教學:連結
NativeAd 需要建立4個客製化class來串接廣告,其中 TAMediaCustomNativeAdEventSetting 為非必要,其他三個都必須加入專案內。
TAMediaCustomNativeAdEventAdapter(必要)
此 class 是作為 TADNativeAd 與 MPNativeAd 的橋樑,將 TAmdia 得到的 TADNativeAd 提供給 mopub 建立 MPNativeAd
- 建立一class實做 MPNativeAdAdapter protocol,protocol 有兩必須實作 property:properties 及 defaultActionURL
- 建立初始化方法,將TADNativeAd 及 TADNativeAdView 作為參數帶入,將由 TADNativeAd 拿到的 TADNativeAdContent 與 MPNativeAdConstants.h 提供的 key 值建立相對應的 dictionary 後賦予給 proerties
- defaultActionURL 則回傳 nil,點擊的部分將交由 TADNativeAdView 處理
- 實作
displayContentForURL:rootViewController:completion:
當 user 點擊時觸發
參考以下代碼
#import <Foundation/Foundation.h>
#import <MoPub/MoPub.h>
#import <TAMediaAdsFramework/TAMediaAdsFramework.h>
@interface TAMediaCustomNativeAdEventAdapter : NSObject <MPNativeAdAdapter>
- (instancetype)initTADNativeAd:(TADNativeAd *)nativeAd withNativeView: (TADNativeAdView *)nativeAdView;
@property (nonatomic, readonly) NSDictionary *properties;
@property (nonatomic, readonly) NSURL *defaultActionURL;
@property (nonatomic, strong) TADNativeAdView *nativeAdView;
@property (nonatomic, weak) id<MPNativeAdAdapterDelegate> delegate;
@end
#import "TAMediaCustomNativeAdEventAdapter.h"
#import <MoPub/MoPub.h>
@interface TAMediaCustomNativeAdEventAdapter () <TADNativeAdDelegate>
@property (nonatomic,strong) TADNativeAd *nativeAd;
@end
@implementation TAMediaCustomNativeAdEventAdapter
- (instancetype)initTADNativeAd:(TADNativeAd *)nativeAd withNativeView: (TADNativeAdView *)nativeAdView {
self = [super init];
TADNativeAdContent *adContent = nativeAd.adContent;
nativeAd.delegate = self;
self.nativeAd = nativeAd;
self.nativeAdView = nativeAdView;
_properties = @{kAdTitleKey: adContent.longSubject,
kAdTextKey: adContent.body,
kAdCTATextKey: adContent.callToAction,
kAdIconImageKey: adContent.iconSquare.image,
kAdMainMediaViewKey: nativeAdView.mediaView};
return self;
}
#pragma mark - MPNativeAdAdapter
- (BOOL)enableThirdPartyClickTracking {
return YES;
}
- (UIView *)mainMediaView {
return self.nativeAdView.mediaView;
}
- (NSURL *)defaultActionURL {
return nil;
}
#pragma mark - TADNativeAdDelegate
- (void)nativeAdDidClick:(TADNativeAd *)ad {
[self.delegate nativeAdDidClick:self];
MPLogAdEvent([MPLogEvent adTappedForAdapter:NSStringFromClass(self.class)], nil);
[self.delegate nativeAdWillPresentModalForAdapter:self];
}
- (void)nativeAdDidImpression:(TADNativeAd *)ad {
[self.delegate nativeAdWillLogImpression:self];
MPLogAdEvent([MPLogEvent adShowSuccessForAdapter:NSStringFromClass(self.class)], nil);
MPLogAdEvent([MPLogEvent adDidAppearForAdapter:NSStringFromClass(self.class)], nil);
}
- (void)adViewWillLeaveApplication:(TADNativeAd *)adView {
if ([self.delegate respondsToSelector:@selector(nativeAdWillLeaveApplicationFromAdapter:)]) {
[self.delegate nativeAdWillLeaveApplicationFromAdapter:self];
}
MPLogAdEvent([MPLogEvent adWillLeaveApplicationForAdapter:NSStringFromClass(self.class)], nil);
}
@end
TAMediaCustomNativeAdRenderer(必要)
此 class 需實做 MPNativeAdRenderer protocol,用於提供實際所要呈現的廣告視圖的 class
- 實作
+ (MPNativeAdRendererConfiguration *)rendererConfigurationWithRendererSettings:(id<MPNativeAdRendererSettings>)rendererSettings
建立 MPNativeAdRendererConfiguration物件 - 設置 rendering class 為本身class
- 設置 rendererSettings 為參數傳入 的rendererSettings
- 設置 supportedCustomEvents 為 TAMediaCustomNativeAdEvent class
- 實作
initWithRendererSettings:
設置物件viewSizeHandler,以及任何客製化設定 - 實作
retrieveViewWithAdapter:
回傳要來呈顯在畫面上的 View
參考以下代碼
#import <Foundation/Foundation.h>
#import <MoPub/MoPub.h>
@interface TAMediaCustomNativeAdRenderer : NSObject <MPNativeAdRenderer>
@property (nonatomic, readonly) MPNativeViewSizeHandler viewSizeHandler;
@end
#import "TAMediaCustomNativeAdRenderer.h"
#import "TAMediaCustomNativeAdEventAdapter.h"
#import <MoPub/MoPub.h>
#import "MPNativeAdView.h"
@interface TAMediaCustomNativeAdRenderer()
@property (nonatomic,strong) id<MPNativeAdRendererSettings>setting;
@property (nonatomic,strong) MPNativeAdRendererImageHandler *rendererImageHandler;
@property(nonatomic, strong) Class renderingViewClass;
@end
@implementation TAMediaCustomNativeAdRenderer
+ (MPNativeAdRendererConfiguration *)rendererConfigurationWithRendererSettings:(id<MPNativeAdRendererSettings>)rendererSettings {
MPNativeAdRendererConfiguration *config = [[MPNativeAdRendererConfiguration alloc] init];
config.rendererSettings = rendererSettings;
config.supportedCustomEvents = @[@"TAMediaCustomNativeAdEvent"];//設置客製化事件處理的class
config.rendererClass = [self class];
return config;
}
- (instancetype)initWithRendererSettings:(id<MPNativeAdRendererSettings>)rendererSettings {
self = [super init];
MPStaticNativeAdRendererSettings *settings =
(MPStaticNativeAdRendererSettings *)rendererSettings;
_viewSizeHandler = [rendererSettings.viewSizeHandler copy];
self.setting = rendererSettings;
_renderingViewClass = settings.renderingViewClass;
return self;
}
- (UIView *)retrieveViewWithAdapter:(id<MPNativeAdAdapter>)adapter error:(NSError **)error {
MPLogAdEvent([MPLogEvent adShowAttemptForAdapter:NSStringFromClass(self.class)], nil);
MPLogAdEvent([MPLogEvent adWillAppearForAdapter:NSStringFromClass(self.class)], nil);
UIView<MPNativeAdRendering> *mpNativeAdView = [self.renderingViewClass new];
mpNativeAdView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
TAMediaCustomNativeAdEventAdapter *tadAdpater = (TAMediaCustomNativeAdEventAdapter *)adapter;
TADNativeAdView *tadNativeAdView = tadAdpater.nativeAdView;
tadNativeAdView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[tadNativeAdView addSubview:mpNativeAdView];
[self fillSuperview:mpNativeAdView];
if([mpNativeAdView respondsToSelector:@selector(nativeTitleTextLabel)]) {
[mpNativeAdView.nativeTitleTextLabel addSubview:tadNativeAdView.longSubjectLabel];
mpNativeAdView.nativeTitleTextLabel.text = adapter.properties[kAdTitleKey];
mpNativeAdView.nativeTitleTextLabel.userInteractionEnabled = YES;
tadNativeAdView.longSubjectLabel.userInteractionEnabled = YES;
[self fillSuperview:tadNativeAdView.longSubjectLabel];
}
if([mpNativeAdView respondsToSelector:@selector(nativeMainTextLabel)]) {
[mpNativeAdView.nativeMainTextLabel addSubview:tadNativeAdView.bodyLabel];
mpNativeAdView.nativeMainTextLabel.text = adapter.properties[kAdTextKey];
mpNativeAdView.nativeMainTextLabel.userInteractionEnabled = YES;
tadNativeAdView.bodyLabel.userInteractionEnabled = YES;
[self fillSuperview:tadNativeAdView.bodyLabel];
}
if([mpNativeAdView respondsToSelector:@selector(nativeCallToActionTextLabel)] && mpNativeAdView.nativeCallToActionTextLabel) {
[mpNativeAdView.nativeCallToActionTextLabel addSubview:tadNativeAdView.callToActionView];
mpNativeAdView.nativeCallToActionTextLabel.text = adapter.properties[kAdCTATextKey];
mpNativeAdView.nativeCallToActionTextLabel.userInteractionEnabled = YES;
tadNativeAdView.callToActionView.userInteractionEnabled = YES;
[self fillSuperview:tadNativeAdView.callToActionView];
}
if([mpNativeAdView respondsToSelector:@selector(nativeIconImageView)]) {
[mpNativeAdView.nativeIconImageView addSubview:tadNativeAdView.squareImgeView];
mpNativeAdView.nativeIconImageView.image = adapter.properties[kAdIconImageKey];
mpNativeAdView.nativeIconImageView.userInteractionEnabled = YES;
tadNativeAdView.squareImgeView.userInteractionEnabled = YES;
[self fillSuperview:tadNativeAdView.squareImgeView];
}
if([mpNativeAdView respondsToSelector:@selector((nativeMainImageView))]) {
tadNativeAdView.mediaView.frame = mpNativeAdView.nativeMainImageView.bounds;
[mpNativeAdView.nativeMainImageView addSubview:tadNativeAdView.mediaView];
mpNativeAdView.nativeMainImageView.userInteractionEnabled = YES;
[self fillSuperview:tadNativeAdView.mediaView];
}
MPLogAdEvent([MPLogEvent adShowAttemptForAdapter:NSStringFromClass(self.class)], nil);
MPLogAdEvent([MPLogEvent adWillAppearForAdapter:NSStringFromClass(self.class)], nil);
return tadNativeAdView;
}
- (void)fillSuperview:(UIView *)view {
view.frame = view.superview.bounds;
}
@end
TAMediaCustomNativeAdEvent(必要)
此 class 需繼承 MPNativeCustomEvent,由 TAmedia 取得 TADNativeAd 廣告後,建立 TADNativeAdView,並透過 adapter 取得 MPNativeAd
- 建立 class 繼承 MPNativeCustomEvent
- 複寫
- (void)requestAdWithCustomEventInfo:(NSDictionary *)info adMarkup:(NSString *)adMarkup
在此用 TADNativeAd 去取得廣告 - 取得廣告後建立 TADNativeAdView
- 透過 TADNativeAd 及 TADNativeAdView 建立 TAMediaCustomNativeAdEventAdapter,再用 adapter 建立 MPNativeAd
#import <MoPub/MoPub.h>
#import <TAMediaAdsFramework/TAMediaAdsFramework.h>
@interface TAMediaCustomNativeAdEvent : MPNativeCustomEvent <TADNativeAdDelegate>
@property (nonatomic,strong) TADNativeAd *nativeAd;
@end
#import "TAMediaCustomNativeAdEvent.h"
#import "TAMediaCustomNativeAdEventAdapter.h"
#import <MoPub/MoPub.h>
@interface TAMediaCustomNativeAdEvent()
@property (nonatomic,strong) NSString *adUnitId;
@end
@implementation TAMediaCustomNativeAdEvent
- (void)requestAdWithCustomEventInfo:(NSDictionary *)info adMarkup:(NSString *)adMarkup {
self.adUnitId = info[@"NativeListId"];
if (self.adUnitId == nil) {
MPLogAdEvent([MPLogEvent adLoadFailedForAdapter:NSStringFromClass(self.class)
error:MPNativeAdNSErrorForInvalidAdServerResponse(@"Ad unit ID cannot be nil.")], self.adUnitId);
[self.delegate nativeCustomEvent:self
didFailToLoadAdWithError:MPNativeAdNSErrorForInvalidAdServerResponse(
@"Ad unit ID cannot be nil.")];
return;
}
TADRequest *request = [TADRequest request];
request.testing = NO;
// Type: TADGender
request.gender = kTADGenderUnknown;
// NAD 物件初始化, 帶入自訂的origin
if (!self.nativeAd) {
self.nativeAd = [[TADNativeAd alloc] initWithAdUnitId: self.adUnitId];
}
// 必須要設定delegate
self.nativeAd.delegate = self;
MPLogAdEvent([MPLogEvent adLoadAttemptForAdapter:NSStringFromClass(self.class) dspCreativeId:nil dspName:nil], self.adUnitId);
// 載入廣告
[self.nativeAd loadRequest:request];
}
- (void)nativeAdDidReceiveAd:(TADNativeAd *)ad {
MPLogAdEvent([MPLogEvent adLoadSuccessForAdapter:NSStringFromClass(self.class)], self.adUnitId);
TADNativeAdView *nativeView = [TADNativeAdView new];
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
UILabel *subTitleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
UILabel *bodyLabel = [[UILabel alloc] initWithFrame:CGRectZero];
UILabel *callToActionView = [[UILabel alloc] initWithFrame: CGRectZero];
UIImageView *smallImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
UIImageView *bigImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
TADNativeMediaView *mediaView = [[TADNativeMediaView alloc] initWithFrame:CGRectZero];
mediaView.mediaContent = ad.adContent.mediaContent;
[nativeView addSubview:titleLabel];
[nativeView addSubview:subTitleLabel];
[nativeView addSubview:bodyLabel];
[nativeView addSubview:callToActionView];
[nativeView addSubview:smallImageView];
[nativeView addSubview:bigImageView];
[nativeView addSubview:mediaView];
nativeView.longSubjectLabel = titleLabel;
nativeView.shortSubjectLabel = subTitleLabel;
nativeView.bodyLabel = bodyLabel;
nativeView.callToActionView = callToActionView;
nativeView.squareImgeView = smallImageView;
nativeView.rectangleImgeView = bigImageView;
nativeView.mediaView = mediaView;
nativeView.nativeAd = ad;
// 表示本次請求收到廣告
TAMediaCustomNativeAdEventAdapter *adapter = [[TAMediaCustomNativeAdEventAdapter alloc] initTADNativeAd:ad withNativeView:nativeView];
MPNativeAd *mpNativeAd = [[MPNativeAd alloc] initWithAdAdapter:adapter];
[self.delegate nativeCustomEvent:self didLoadAd:mpNativeAd];
}
- (void)nativeAd:(TADNativeAd *)ad didFailToReceiveAdWithError:(TADRequestError *)error {
MPLogAdEvent([MPLogEvent adLoadFailedForAdapter:NSStringFromClass(self.class) error:error], self.adUnitId);
if ([self.delegate respondsToSelector:@selector(nativeCustomEvent:didFailToLoadAdWithError:)]) {
[self.delegate nativeCustomEvent:self didFailToLoadAdWithError:error];
}
@end
TAMediaCustomNativeAdEventSetting
此class需實做MPNativeAdRendererSettings protocol,用來設定 viewSize,與指定需要來呈現廣告的 View,亦可使用 MPNativeAdRendererSettings 取代
// TAMediaCustomNativeAdEventSetting.h #import <Foundation/Foundation.h> #import <MoPub/MoPub.h> @interface TAMediaCustomNativeAdEventSetting : NSObject <MPNativeAdRendererSettings> @property (nonatomic, assign) Class renderingViewClass; @property (nonatomic, readwrite, copy) MPNativeViewSizeHandler viewSizeHandler; @end
// TAMediaCustomNativeAdEventSetting.m #import "TAMediaCustomNativeAdEventSetting.h" @implementation TAMediaCustomNativeAdEventSetting @end