TAMedia Wiki

SDK 8 Mopub Mediation Native

官方教學:連結
NativeAd 需要建立4個客製化class來串接廣告,其中 TAMediaCustomNativeAdEventSetting 為非必要,其他三個都必須加入專案內。

回MoPub教學

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 處理
#將由 TADNativeAd delegate 接收到的事件 nativeAdDidClick、nativeAdDidImpression、adViewWillLeaveApplication 透過 MPNativeAdAdapterDelegate 傳回給 Mopub 參考以下代碼

#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。
取得 TADNativeAd 廣告可以參考 TADNativeAd 介紹,對 TADRequest 設定參數或帶入 TADNativeAdOptions。
#建立 class 繼承 MPNativeCustomEvent
#複寫- (void)requestAdWithCustomEventInfo:(NSDictionary *)info adMarkup:(NSString *)adMarkup 在此用 TADNativeAd 去取得廣告
#取得廣告後建立 TADNativeAdView

  1. 透過 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