draw广告

简介

draw广告分为自渲染广告和模板广告,类型取决于三方SDK的支持情况。SDK 提供draw广告的数据绑定、点击事件的上报

自渲染广告:聚合SDK返回物料,由开发者在返回的CloooudDrawAdView类型的view上进行子视图的自行渲染和展示。

模板广告:聚合SDK直接返回渲染好的广告view:CloooudDrawAdView,开发者直接展示即可。

draw广告管理类CloooudDrawAdsManager

在SDK里只需要使用 CloooudDrawAdsManager 就可以获取draw广告。CloooudDrawAdsManager支持多广告加载,可以一次加载返回多个广告。 注:一定要设置rootViewController,即跳转落地页需要的viewController。

@interface CloooudDrawAdsManager : CloooudBaseAd

/// 快速广告构建方法
/// @param unitID 广告位ID
/// @param adSize 广告视图大小
- (instancetype)initWithAdUnitID:(NSString *)unitID adSize:(CGSize)adSize;

/// 广告视图的尺寸,请勿设置为0
@property (nonatomic, assign) CGSize adSize;

/// 广告代理对象
@property (nonatomic, weak) id<CloooudDrawAdsManagerDelegate> delegate;

/// 必要,设置广告详情跳转控制器
@property (nonatomic, weak) UIViewController *rootViewController;

/// 加载广告方法
/// @param count 加载广告的数量,建议单次不超过3个
- (void)loadAdDataWithCount:(NSUInteger)count;

@end

draw广告类CloooudDrawAdView

CloooudDrawAdView为请求原生广告返回的广告类,它的使用方法有两种。

自渲染广告(hasExpressAdGot=NO) 开发者根据CloooudDrawAdView.data的物料信息对CloooudDrawAdView提供的UI类型进行赋值和布局。

模板广告(hasExpressAdGot=YES) 开发者可直接将CloooudDrawAdView添加到父视图上进行展示。

注意:目前仅支持frame布局方式,不支持自动布局

@interface CloooudDrawAdView : CloooudCanvasView
/// 广告管理者
@property (nonatomic, weak, readonly) CloooudDrawAdsManager *adManager;
​
/// 代理协议对象
@property (nonatomic, weak, readwrite, nullable) id<CloooudDrawAdViewDelegate> delegate;
​
/// 视频播放代理协议对象
@property (nonatomic, weak, readwrite, nullable) id<CloooudDrawAdVideoDelegate> videoDelegate;
​
/// 是否是模板广告,由adapter开发者实现
@property (nonatomic, assign, readonly) BOOL isExpressAd;
​
/// 是否是模板广告,由adapter开发者实现,同isExpressAd
@property (nonatomic, assign, readonly) BOOL hasExpressAdGot;
​
/// [必传]跳转控制器
@property (nonatomic, weak, readwrite) UIViewController *_Nullable rootViewController;
​
- (NSString *)getAdNetworkPlatformName Cloooud_DEPRECATED_MSG_ATTRIBUTE("接口即将废弃,请使用`getShowEcpmInfo`代替");
​
/// 返回显示广告对应的披露信息,当没有权限访问时Ecpm会返回'-3'
- (nullable CloooudRitInfo *)getShowEcpmInfo;
​
/// 填充后可调用,但推荐展示后调用,返回竞价广告的ecpm;当为server bidding ad时访问需要白名单权限;
- (NSArray<CloooudRitInfo *> *)multiBiddingEcpmInfos;
​
/// 填充后可调用, 返回广告缓存池内所有信息;nil为无权限
- (NSArray<CloooudRitInfo *> *)cacheRitList;
​
/// 填充后可调用,返回当前最佳广告的ecpm;当为server bidding ad时访问需要白名单权限
- (CloooudRitInfo *)getCurrentBestEcpmInfo;
​
/// 填充后可调用,获取广告中的extra信息。目前只支持穿山甲,并且只支持获取coupon, live_room, product信息。
- (nullable NSDictionary *)getMediaExtraInfo;
​
/// 广告视图的唯一标识
@property (nonatomic, copy, readonly) NSString *adViewID;
@end
/// draw广告视图类,模板部分
@interface CloooudDrawAdView (Express)
​
/// 是否已经准备广告展示,理论上在广告加载回调后即为YES,但受一些因素的影响(例如广告失效),可能为NO。建议在广告展示前调用该方法进行是否可以展示
@property (nonatomic, assign, readonly) BOOL isReady;
​
/// 返回显示广告对应的Adn名称
/// [必要]渲染模板广告,开发者调用前无需区分是否为模板广告,Cloooud会自行处理
- (void)render;
​
/// [保留方法]更新模板媒体视图大小
- (void)reSizeMediaView;
​
@end

自渲染广告物料信息同信息流广告

当返回广告是自渲染类型时,开发者需要使用CloooudNativeAdView.data的数据进行自渲染布局.该类型数据结构如下

typedef NS_ENUM (NSInteger, CloooudMediatedNativeAdCallToType) {
    CloooudMediatedNativeAdCallToTypeUnknown        = 0,
    CloooudMediatedNativeAdCallToTypeNone           = 1,  // pure ad display
    CloooudMediatedNativeAdCallToTypeURL            = 2,  // open the webpage using a browser
    CloooudMediatedNativeAdCallToTypePage           = 3,  // open the webpage within the app
    CloooudMediatedNativeAdCallToTypeDownload       = 4,  // download the app
    CloooudMediatedNativeAdCallToTypePhone          = 5,  // make a call
    CloooudMediatedNativeAdCallToTypeMessage        = 6,  // send messages
    CloooudMediatedNativeAdCallToTypeEmail          = 7,  // send email
    CloooudMediatedNativeAdCallToTypeVideoAdDetail  = 8,   // video ad details page
    CloooudMediatedNativeAdCallToTypeOthers         = 100 //其他广告sdk返回的类型
};

typedef NS_ENUM (NSInteger, CloooudMediatedNativeAdMode) {
    CloooudMediatedNativeAdModeUnknown          = 00, // 未知
    CloooudMediatedNativeAdModeSmallImage       = 02, // 水平小图样式
    CloooudMediatedNativeAdModeLargeImage       = 03, // 水平大图样式
    CloooudMediatedNativeAdModeGroupImage       = 04, // 水平组图样式
    CloooudMediatedNativeAdModeLandscapeVideo   = 05, // 水平视频样式
    CloooudMediatedNativeAdModePortraitVideo    = 15, // 垂直视频样式
    CloooudMediatedNativeAdModePortraitImage    = 16, // 垂直图片样式
    // 兼容
    CloooudFeedADModeSmallImage                 = 02, // CloooudMediatedNativeAdModeSmallImage,
    CloooudFeedADModeLargeImage                 = 03, // CloooudMediatedNativeAdModeLargeImage,
    CloooudFeedADModeGroupImage                 = 04, // CloooudMediatedNativeAdModeGroupImage,
    CloooudFeedVideoAdModeImage                 = 05, // CloooudMediatedNativeAdModeLandscapeVideo,
    CloooudFeedVideoAdModePortrait              = 15, // CloooudMediatedNativeAdModePortraitVideo,
    CloooudFeedADModeImagePortrait              = 16, // CloooudMediatedNativeAdModePortraitImage,
};

typedef CloooudMediatedNativeAdMode CloooudFeedADMode;

@protocol CloooudMediatedNativeAdData;

typedef NSObject<CloooudMediatedNativeAdData> CloooudMaterialMeta;

// 媒体native ad数据协议,配合CloooudMediatedNativeAdViewCreator使用
@protocol CloooudMediatedNativeAdData <NSObject>

// 广告支持的跳转类型
@property (nonatomic, assign, readonly) CloooudMediatedNativeAdCallToType callToType;

// 物料图片集,如果图片有宽高,请尽量配置width和height
@property (nonatomic, copy, readonly, nullable) NSArray<CloooudImage *> *imageList;

// 物料图片集,如果图片有宽高,请尽量配置width和height
@property (nonatomic, copy, readonly, nullable) NSArray<CloooudImage *> *imageAry Cloooud_DEPRECATED_MSG_ATTRIBUTE("接口即将废弃,请使用 'imageList' 代替");

// app图标,如果图标有宽高,请尽量配置width和height
@property (nonatomic, strong, readonly, nullable) CloooudImage *icon;

// 广告logo,如果logo有宽高,请尽量配置width和height
@property (nonatomic, strong, readonly, nullable) CloooudImage *adLogo;

// 聚合广告SDKlogo
@property (nonatomic, strong, readonly, nullable) CloooudImage *sdkLogo;

// 广告标题
@property (nonatomic, copy, readonly, nullable) NSString *AdTitle;

// 广告详情描述
@property (nonatomic, copy, readonly, nullable) NSString *AdDescription;

// 应用来源、市场,例如'App Store'
@property (nonatomic, copy, readonly, nullable) NSString *source;

// 按钮文案,例如'下载/安装'
@property (nonatomic, copy, readonly, nullable) NSString *buttonText;

// 图片/视频模式
@property (nonatomic, assign, readonly) CloooudMediatedNativeAdMode imageMode;

// app评分,区间为1-5,如果没有值返回-1
@property (nonatomic, assign, readonly) NSInteger score;

// 评论数量,如果没有值返回-1
@property (nonatomic, assign, readonly) NSInteger commentNum;

// 广告安装包体大小,单位KB,如果没有值返回-1
@property (nonatomic, assign, readonly) NSInteger appSize;

// 视频时长,单位秒,如果没有值返回0
@property (nonatomic, assign, readonly) NSInteger videoDuration;

// 媒体扩展数据
@property (nonatomic, copy, readonly, nullable) NSDictionary *mediaExt;

// app购买价格,例如'免费',没有则为nil
@property (nonatomic, strong, readonly, nullable) NSString *appPrice;

// 广告商标识,广告商的名称或者链接
@property (nonatomic, copy, readonly, nullable) NSString *advertiser;

// 品牌名称,若广告返回中无品牌名称则为空
@property (copy, nonatomic, readonly, nullable) NSString *brandName;

@end

回调监听

CloooudDrawAdsManagerDelegate

// Draw 广告回调协议
@protocol CloooudDrawAdsManagerDelegate <NSObject>

@optional

// Draw 广告加载成功回调
// @param adsManager 广告管理对象
// @param drawAds 广告视图,Cloooud包装视图对象组,包括模板广告和自渲染广告
- (void)drawAdsManagerSuccessToLoad:(CloooudDrawAdsManager *_Nonnull)adsManager drawVideoAds:(NSArray<CloooudDrawAdView *> *_Nullable)drawAds;

// Draw 广告加载失败回调
// @param adsManager 广告管理对象
// @param error  加载出错信息
- (void)drawAdsManager:(CloooudDrawAdsManager *_Nonnull)adsManager didFailWithError:(NSError *_Nullable)error;

@end

CloooudDrawAdViewDelegate

@protocol CloooudDrawAdViewDelegate <NSObject>

@optional

// 模板广告渲染成功回调,非模板广告不会回调,模板广告可能不会回调
// @param drawAdView 模板广告对象
- (void)drawAdExpressViewRenderSuccess:(CloooudDrawAdView *_Nonnull)drawAdView;

// 模板广告渲染成功回调,非模板广告不会回调,模板广告可能不会回调
// @param drawAdView 模板广告对象
// @param error 渲染出错原因
- (void)drawAdExpressViewRenderFail:(CloooudDrawAdView *_Nonnull)drawAdView error:(NSError *_Nullable)error;

// 模板广告点击关闭时触发
// @param drawAdView 广告视图
// @param filterWords 广告关闭原因,adapter开发者透传数据
- (void)drawAdExpressViewDidClosed:(CloooudDrawAdView *_Nullable)drawAdView closeReason:(NSArray<NSDictionary *> *_Nullable)filterWords;

// 非模板广告点击关闭时触发
// @param drawAdView 广告视图
// @param filterWords 广告关闭原因,adapter开发者透传数据
- (void)drawAdDidClosed:(CloooudDrawAdView *_Nullable)drawAdView closeReason:(NSArray<NSDictionary *> *_Nullable)filterWords;

// 广告展示回调,不区分模板与非模板
// @param drawAdView 广告对象
- (void)drawAdDidBecomeVisible:(CloooudDrawAdView *_Nonnull)drawAdView;

// 广告视频播放状态变更回调,是否回调与adapter实现有关
// @param drawAdView 广告对象
// @param playerState 播放状态
- (void)drawAdView:(CloooudDrawAdView *_Nonnull)drawAdView stateDidChanged:(CloooudPlayerPlayState)playerState;

// 广告点击事件回调
// @param drawAdView 广告对象
// @param view 广告展示视图
- (void)drawAdDidClick:(CloooudDrawAdView *_Nonnull)drawAdView withView:(UIView *_Nullable)view;

// 广告即将展示全屏页面/商店时触发
// @param drawAdView 广告视图
- (void)drawAdViewWillPresentFullScreenModal:(CloooudDrawAdView *_Nonnull)drawAdView;

// 广告即将关闭全屏页面/商店时触发
// @param drawAdView 广告视图
- (void)drawAdViewWillDismissFullScreenModal:(CloooudDrawAdView *_Nonnull)drawAdView;

@end

CloooudDrawAdVideoDelegate

当返回广告为视频广告,开发者注册该监听后可以收到相应的回调。当且仅当CloooudDrawAdView.data.imageMode = CloooudFeedVideoAdModeImage生效。

@protocol CloooudDrawAdVideoDelegate <NSObject>
@optional

// 当videoadview回放状态改变时,调用此方法
// @param drawAdView draw ad view
// @param playerState 改变后播放状态
- (void)drawAdVideo:(CloooudDrawAdView *_Nullable)drawAdView stateDidChanged:(CloooudPlayerPlayState)playerState;


//  videoadview被点击时,调用此方法
// @param drawAdView draw ad view
- (void)drawAdVideoDidClick:(CloooudDrawAdView *_Nullable)drawAdView;


// 当videoadview结束播放时调用此方法。
// @param drawAdView draw ad view
- (void)drawAdVideoDidPlayFinish:(CloooudDrawAdView *_Nullable)drawAdView;

@end

draw广告示例

draw广告加载示例

// 广告加载
- (void)loadDrawVideoAdsWithAdUnitID:(NSString *)adUnitID {

    // 广告加载
    self.drawAdsManager = [[CloooudDrawAdsManager alloc] initWithAdUnitID:adUnitID adSize:CGSizeZero];
    // 如果需要场景,请设置该属性
    self.drawAdsManager.scenarioID = @"xxx";
    self.drawAdsManager.delegate = self;

    if ([CloooudAdSDKManager configDidLoad]) {
        //当前配置拉取成功,直接loadAdData
        [self.drawAdsManager loadAdDataWithCount:3];
    } else {
        //当前配置未拉取成功,在成功之后会调用该callback
        [CloooudAdSDKManager addConfigLoadSuccessObserver:self withAction:^(id  _Nonnull observer) {
            [observer.drawAdsManager loadAdDataWithCount:3];
        }];
    }
}

draw自渲染广告展示示例

- (void)refreshUIWithModel:(CloooudDrawAdView *)model {
    [super refreshUIWithModel:model];

    self.drawAdView.frame = self.bounds;//CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame));

    CGFloat width = CGRectGetWidth(self.bounds);
    CGFloat contentWidth = (width - 2 * margin);
    CGFloat y = padding.top;

    NSAttributedString *attributedText = [CloooudDFeedStyleHelper titleAttributeText:model.data.AdTitle];
    CGSize titleSize = [attributedText boundingRectWithSize:CGSizeMake(contentWidth, 0) options:NSStringDrawingUsesFontLeading context:0].size;
    self.drawAdView.titleLabel.frame = CGRectMake(padding.left, y, contentWidth, titleSize.height);
    self.drawAdView.titleLabel.attributedText = attributedText;

    // 广告标识
    if (model.data.adLogo.imageURL) {
        UIImageView *adLogoV = [[UIImageView alloc] initWithFrame:CGRectMake(width-20, y, 20, 20)];
        [adLogoV setImageWithURL:model.data.adLogo.imageURL];
        [self.drawAdView addSubview:adLogoV];
    }

    y += titleSize.height;
    y += 5;

    // 广告占位图
    CloooudImage *image = model.data.imageList.firstObject;

    CGFloat imageHeight = CGRectGetHeight(self.drawAdView.frame);
    if (image.width > 0) {
        imageHeight = contentWidth * (image.height / image.width);
        if (!self.drawAdView.mediaView) {
            [self.drawAdView.imageView setImageWithURL:image.imageURL placeholderImage:image.image];
            self.drawAdView.imageView.frame = CGRectMake(padding.left, y, contentWidth, imageHeight);
        }
    }

    self.drawAdView.mediaView.frame = CGRectMake(padding.left, y, contentWidth, imageHeight);
    // !!!mediaView布局后h必须调用该方法
    [self.drawAdView reSizeMediaView];

    y += imageHeight;

    if (self.drawAdView.hasSupportActionBtn) {
        // creativeButton
        NSString *btnTxt = @"Click";
        if (self.drawAdView.data.buttonText.length > 0) {
            btnTxt = self.drawAdView.data.buttonText;
        }
        [self.drawAdView.callToActionBtn setTitle:btnTxt forState:UIControlStateNormal];
        [self.drawAdView.callToActionBtn sizeToFit];
    }

    CGSize buttonSize = self.drawAdView.callToActionBtn.frame.size;

    // source
    CGFloat maxInfoWidth = width - 2 * margin - buttonSize.width - 10 - 15;

    // sdk标识
    UIImageView *sdkLogoV;
    if (model.data.adLogo) {
        sdkLogoV = [[UIImageView alloc] initWithFrame:CGRectMake(padding.left, y, 30, 20)];
        // 优先使用image
        if (model.data.adLogo.image) {
            [sdkLogoV setImage:model.data.adLogo.image];
        } else if (model.data.adLogo.imageURL) {
            // image不存在使用url
            [sdkLogoV setImageWithURL:model.data.adLogo.imageURL];
        }
        if (sdkLogoV.image) {
            CGFloat width = 20;
            CGFloat height = 20;
            if (model.data.adLogo.width && model.data.adLogo.height) {
                height = width * model.data.adLogo.height/model.data.adLogo.width;
            }
            sdkLogoV.frame = CGRectMake(CGRectGetMinX(sdkLogoV.frame), CGRectGetMinY(sdkLogoV.frame),width, height);
            [self.drawAdView addSubview:sdkLogoV];
        }
    }

    CGFloat originY = y;
    if (sdkLogoV) {
        originY = CGRectGetMinY(sdkLogoV.frame);
    }
    self.drawAdView.descLabel.frame = CGRectMake(padding.left + 5 + CGRectGetWidth(sdkLogoV.frame), originY, maxInfoWidth, 20);
    self.drawAdView.descLabel.attributedText = [CloooudDFeedStyleHelper subtitleAttributeText:model.data.AdDescription];
    self.drawAdView.descLabel.text = model.data.AdDescription;

    //物料里的price,score,source等信息;开发者可根据原始信息自定义表现形式
    CGRect frame = CGRectMake(padding.left, CGRectGetMaxY(self.drawAdView.descLabel.frame)-5, 260, 20);
    UILabel *otherInfoLbl = [self otherInfoLblWithFrame:frame data:self.drawAdView.data];
    [self.drawAdView addSubview:otherInfoLbl];

    CGFloat dislikeX = width - 24 - padding.right;

    // 物料信息不包含关闭按钮需要自己实现
    if (!self.drawAdView.dislikeBtn) {
        [self.drawAdView.dislikeBtn setImage:[UIImage imageNamed:@"feedClose"] forState:UIControlStateNormal];
    }

    if (y >= CGRectGetHeight(self.drawAdView.frame)) {
        y -= (y-CGRectGetHeight(self.drawAdView.frame)+20);
    }
    self.drawAdView.dislikeBtn.frame = CGRectMake(dislikeX, y, 24, 24);

    if (self.drawAdView.hasSupportActionBtn) {
        self.drawAdView.callToActionBtn.frame = CGRectMake(CGRectGetMinX(self.drawAdView.dislikeBtn.frame) - buttonSize.width - 10, y + 50, buttonSize.width, buttonSize.height);
        self.drawAdView.callToActionBtn.backgroundColor = [UIColor redColor];
    }

    NSMutableArray *viewArray = [NSMutableArray array];
    [viewArray addObject:self];
    if (self.drawAdView.titleLabel) {
        [viewArray addObject:self.drawAdView.titleLabel];
    }
    if (self.drawAdView.descLabel) {
        [viewArray addObject:self.drawAdView.descLabel];
    }
    if (self.drawAdView.imageView) {
        [viewArray addObject:self.drawAdView.imageView];
    }
    if (self.drawAdView.mediaView) {
        [viewArray addObject:self.drawAdView.mediaView];
    }
    if (self.drawAdView.callToActionBtn) {
        [viewArray addObject:self.drawAdView.callToActionBtn];
    }
    if (otherInfoLbl) {
        [viewArray addObject:otherInfoLbl];
    }
    // 注册点击事件
    [self.drawAdView registerClickableViews:viewArray];
    [self addSubview:self.drawAdView];
}

详细示例请参见Demo

draw模板广告展示示例

// 获取到hasExpressAdGot参数为YES时,通过返回对象调用render方法,即可渲染模板广告。

if (model.hasExpressAdGot) { model.frame = CGRectMake(x, CGRectGetMaxY(self.showAndRefreshAd.frame) + 20, width, height); [self.view addSubview:model]; [model render]; } 详细示例请参见Demo