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