iOS 集成手册
iOS SDK 版本更新记录
| 版本号 | 更新日期 | 更新内容 |
|---|---|---|
| 1.1.0 | 2025-01-12 | iOS 初始版本发布 |
目录
SDK 接入准备及初始化文档
SDK接入准备
- 在Advista平台注册账号后,创建应用、代码位。 a. 开发联调阶段建议创建测试应用/代码位,测试代码位几乎满填,方便验证广告加载和展示效果。
- 下载 SDK 并集成到应用内。集成完毕后,首先需要先初始化SDK,并填写平台创建的AppID(应用ID)。然后根据您的需求接入不同的广告功能,按照规范调用各个广告类型方法。
- 每一次广告加载时都需要填写sposId(代码位ID)。
SDK 集成
系统要求
- iOS 13.0 及以上版本
- Xcode 12.0 及以上版本
CocoaPods 集成
- 在
Podfile中添加源:
source 'https://cdn.cocoapods.org/'- 在
Podfile中添加依赖,并执行pod install:
pod 'advista', '~> 1.1.0'
pod 'OpenSSL-Universal', '~> 1.1'- 执行安装:
pod install手动集成
下载 SDK 文件
- 从 Advista 平台下载最新版本的 SDK Framework
- 支持
.framework
集成 Framework
- 将
advista.framework拖拽到 Xcode 项目中 - 在项目设置中,确保 Framework 已添加到 "Embedded Binaries" 和 "Linked Frameworks and Libraries"
- 将
添加系统依赖
- 在项目设置中,确保已链接以下系统框架:
UIKit.frameworkFoundation.frameworkAVFoundation.framework(用于视频广告)WebKit.framework(用于广告展示)CoreMotion.framework(用于摇一摇功能)
- 在项目设置中,确保已链接以下系统框架:
配置 Info.plist
- 添加网络权限(如果需要):
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <false/> </dict> - 添加定位权限(如果使用定位功能):
<key>NSLocationWhenInUseUsageDescription</key> <string>用于提供更精准的广告推荐</string>
- 添加网络权限(如果需要):
导入头文件
#import <advista/advista.h> // 或者 #import "advista/advista.h"
SDK 初始化示例
#import "ViewController.h"
#import "advista/advista.h"
#import "UIView+Toast.h"
@interface ViewController () <AdvistaInitListener>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
AdvistaSDKConfig *config = [[AdvistaSDKConfig alloc]init];
config.appId = @"000000";
config.bundleId = @"bundleId"; // 可选,不设置会自动获取
config.debugMode = NO; // 生产环境必须设置为 NO
[[AdvistaSDK sharedInstance]setupWithConf:config listener:self];
}
- (void)onInitFailed:(NSInteger)code errorMsg:(nonnull NSString *)errorMsg {
[self.view makeToast:errorMsg];
}
- (void)onInitSuccess {
[self.view makeToast:@"初始化成功"];
}
@endAdvistaSDKConfig 配置说明
| 属性 | 类型 | 含义 | 是否必选 | 默认值 |
|---|---|---|---|---|
| appId | NSString | 应用ID,从 Advista 平台获取 | 必选 | - |
| bundleId | NSString | 应用的 Bundle Identifier | 可选 | 自动获取 |
| debugMode | BOOL | 开发阶段控制台日志开关,开启后输出详细日志,上线前必须设置为 NO | 可选 | NO |
| location | BOOL | 是否开启定位,当 app 获取到定位授权后,SDK 会读取定位信息;设置为 NO 后,SDK 不会再获取定位信息 | 可选 | YES |
| carrier | BOOL | 是否允许 SDK 获取运营商信息;设置为 NO 后,SDK 不会再获取运营商信息 | 可选 | YES |
| enablePersonalized | BOOL | 个性化推荐开关;设置为 NO 后,SDK 将不再根据个性化能力推荐广告 | 可选 | YES |
| IDFV | BOOL | 是否允许 SDK 获取 IDFV;设置为 NO 后,SDK 不会再获取 IDFV 信息 | 可选 | YES |
| IDFA | BOOL | 是否收集 IDFA,当 app 获取到 IDFA 授权后,SDK 会读取 IDFA 信息;设置为 NO 后,SDK 不会再获取 IDFA 信息 | 可选 | YES |
| customIDFA | NSString | 自定义 IDFA,开发者可自行获取传入。传入非空的字符串后,SDK 将不再主动获取。注意:要传入正确的 IDFA,不要随意填写内容 | 可选 | nil |
| customIDFV | NSString | 自定义 IDFV,开发者可以自行获取 IDFV 传入 | 可选 | nil |
| customCarrier | NSString | 自定义运营商信息,开发者可以自行获取运营商信息传入,格式为 mcc 拼接 mnc,如 46000 | 可选 | nil |
| customLocation | NSString | 自定义位置信息,开发者可以自行获取传入 | 可选 | nil |
注意事项:
appId是必填项,必须从 Advista 平台获取bundleId如果不设置,SDK 会自动从[NSBundle mainBundle] bundleIdentifier]获取- 生产环境必须将
debugMode设置为NO,避免泄露敏感信息 - 自定义设备信息(customIDFA、customIDFV 等)一旦设置,SDK 将使用自定义值,不再主动获取
开屏广告
概述
开屏广告是应用程序启动时呈现的全屏广告,开发者只需遵循标准接入流程即可展示广告视图。开屏广告在应用启动时显示,持续5秒后自动关闭。用户也可以点击“跳过”快速进入主界面,或点击广告了解更多信息。
广告加载参数AdLoadParams.Builder方法说明
| 方法 | 说明 | 是否必填 |
|---|---|---|
| setSposId:(NSString *)sposId | 设置代码位id,sposId不能为空 | 必填 |
| setLoadTimeOut:(NSInteger)loadTimeOut | 加载超时时间,默认5s(单位:毫秒) | 可选 |
| setMute:(BOOL)isMute | 设置视频素材是否默认静音 | 可选 |
| setShake:(BOOL)isShake | 是否允许摇一摇广告,默认YES | 可选 |
AdvistaTemplateAd方法说明
| 方法/属性 | 含义 |
|---|---|
| isReady | 对于已经加载成功,但未及时展示的广告,在展示前用此方法判断广告是否还可用 |
| showAdInWindow | 用于调用已经加载成功的广告的展示 |
| getECPM | 获取当前广告的价格 单位 分(人民币) |
AdvistaSplashAd的代理方法
@protocol AdvistaAdDelegate <NSObject>
@required
/// 广告加载成功
- (void)onAdLoaded:(AdvistaTemplateAd *)ad;
/// 广告的加载的各种错误信息
- (void)onAdFailedToLoad:(NSInteger)code errorMsg:(NSString *)errorMsg;
/// 广告展示的错误信息
- (void)onShowError:(NSInteger)code errorMsg:(NSString *)errorMsg;
/// 点击了广告
- (void)onAdClicked;
/// 关闭了广告
- (void)onAdClosed;
/// 广告曝光了
- (void)onAdExposure;
/// 广告资源加载成功
- (void)onResourceReady;
@end开屏广告的使用
#import "advista/advista.h"
#import "UIView+Toast.h"
@implementation SplashViewController
- (IBAction)loadAndShow:(UIButton *)sender {
// 创建自定义底部视图
AdLoadParamsBuilder* builder = [[AdLoadParamsBuilder alloc]init];
[builder setSposId:@"111111"];
[builder setShake:YES];
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
//设置开屏底部bottomView 可选
UIView *customBottomView;
if (_bottomSwitch.on) {
customBottomView = [[UIView alloc] init];
customBottomView.backgroundColor = [UIColor blackColor];
// 设置 bottomView 的高度
customBottomView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 100);
[builder setAdSize:CGSizeMake(screenWidth, 700)];
}
AdLoadParams *params = builder.build;
[[AdvistaSDK sharedInstance]loadSplashAdWithParams:params customBottomView:customBottomView listener:self];
}
- (void)onAdClicked {
[self.view makeToast:@"广告被点击了"];
}
- (void)onAdClosed {
[self.view makeToast:@"广告被关闭了"];
}
- (void)onAdExposure {
[self.view makeToast:@"广告曝光了"];
}
- (void)onAdFailedToLoad:(NSInteger)code errorMsg:(nonnull NSString *)errorMsg {
[self.view makeToast:@"广告加载失败"];
}
- (void)onAdLoaded:(nonnull AdvistaTemplateAd *)ad {
[self.view makeToast:@"广告加载成功"];
_splashAd = ad;
[self showAd];
}
- (void)onResourceReady {
[self.view makeToast:@"广告isReady"];
[self showAd];
}
- (void)showAd{
if (_splashAd && _splashAd.isReady) {
[_splashAd showAdInWindow:self.view.window];
}
}
- (void)onShowError:(NSInteger)code errorMsg:(nonnull NSString *)errorMsg {
}
@end插屏广告
概述
插屏广告是移动广告的一种常见形式,一般在应用使用过程中弹出,用户可以选择点击广告以访问目标网址,或者关闭广告以返回应用。 插屏广告有两种形式:半屏和全屏。两者都覆盖整个屏幕,区别在于广告内容的展示区域大小。半屏广告在展示区域之外,背景为半透明。
广告加载参数AdLoadParams.Builder方法说明
| 方法 | 说明 | 是否必填 |
|---|---|---|
| setSposId:(NSString *)sposId | 设置代码位id,sposId不能为空 | 必填 |
| setLoadTimeOut:(NSInteger)loadTimeOut | 加载超时时间,默认5s(单位:毫秒) | 可选 |
| setMute:(BOOL)isMute | 设置视频素材是否默认静音 | 可选 |
| setShake:(BOOL)isShake | 是否允许摇一摇广告,默认YES | 可选 |
AdvistaTemplateAd方法说明
| 方法/属性 | 含义 |
|---|---|
| isReady | 对于已经加载成功,但未及时展示的广告,在展示前用此方法判断广告是否还可用 |
| showAdInWindow | 用于调用已经加载成功的广告的展示 |
| getECPM | 获取当前广告的价格 单位 分(人民币) |
AdvistaSplashAd的代理方法
@protocol AdvistaAdDelegate <NSObject>
@required
/// 广告加载成功
- (void)onAdLoaded:(AdvistaTemplateAd *)ad;
/// 广告的加载的各种错误信息
- (void)onAdFailedToLoad:(NSInteger)code errorMsg:(NSString *)errorMsg;
/// 广告展示的错误信息
- (void)onShowError:(NSInteger)code errorMsg:(NSString *)errorMsg;
/// 点击了广告
- (void)onAdClicked;
/// 关闭了广告
- (void)onAdClosed;
/// 广告曝光了
- (void)onAdExposure;
/// 广告资源加载成功
- (void)onResourceReady;
@end插屏广告的使用
#import "PopupViewController.h"
#import "UIView+Toast.h"
@implementation PopupViewController
- (IBAction)loadAndShow:(id)sender {
AdLoadParamsBuilder *builder = [[AdLoadParamsBuilder alloc]init];
[builder setSposId:@"30272174"];
[builder setLoadTimeOut:5000];
[builder setShake:YES];
AdLoadParams *params = [builder build];
[[AdvistaSDK sharedInstance] loadInterstitialWithParams:params listener:self];
}
- (void)onAdClicked {
[self.view makeToast:@"广告被点击了"];
}
- (void)onAdClosed {
[self.view makeToast:@"广告被关闭了"];
}
- (void)onAdExposure {
[self.view makeToast:@"广告曝光了"];
}
- (void)onAdFailedToLoad:(NSInteger)code errorMsg:(nonnull NSString *)errorMsg {
[self.view makeToast:@"广告加载失败"];
}
- (void)onAdLoaded:(nonnull AdvistaTemplateAd *)ad {
if (ad) {
_interstitialAd = ad;
[self.view makeToast:@"广告加载成功"];
}
}
- (void)onResourceReady {
if (_interstitialAd && _interstitialAd.isReady) {
[_interstitialAd showAdInWindow:self.view.window];
}
}
- (void)onShowError:(NSInteger)code errorMsg:(nonnull NSString *)errorMsg {
}
@end原生广告
概述
原生广告是一种与应用内容和设计自然融合的广告形式,开发者只需按照标准集成步骤即可在应用中无缝展示广告内容。原生广告能够与应用的界面和用户体验协调一致,不会干扰用户的正常使用。用户可以在浏览应用内容时自然地接触到这些广告,从而提高广告的接受度和互动性。开发者可以根据应用的风格和用户的需求定制广告的展示方式,以实现最佳的广告效果和用户体验。
原生广告模版渲染和开发者自渲染
模板渲染广告:
广告加载参数AdLoadParams.Builder方法说明
| 方法 | 说明 | 是否必填 |
|---|---|---|
| setSposId:(NSString *)sposId | 设置代码位id,sposId不能为空 | 必填 |
| setLoadTimeOut:(NSInteger)loadTimeOut | 加载超时时间,默认5s(单位:毫秒) | 可选 |
| setMute:(BOOL)isMute | 设置视频素材是否默认静音 | 可选 |
| setShake:(BOOL)isShake | 是否允许摇一摇广告,默认YES | 可选 |
| setAdSize:(CGSize)adSize | 原生广告加载的尺寸,width必传,高度可选 | 可选 |
| setSizeToFit:(BOOL)sizeToFit | 原生广告是否自适应尺寸 | 可选 |
AdvistaTemplateAd方法说明
| 方法/属性 | 含义 |
|---|---|
| isReady | 对于已经加载成功,但未及时展示的广告,在展示前用此方法判断广告是否还可用 |
| getECPM | 获取当前广告的价格 单位 分(人民币) |
| getAdView | 获取当前原生广告的视图进行填充 |
模板渲染原生广告的使用
#import "FeedsViewController.h"
#import "UIView+Toast.h"
@implementation FeedsViewController
- (IBAction)loadAndShow:(id)sender {
AdLoadParamsBuilder *builder = [[AdLoadParamsBuilder alloc]init];
[builder setMute:YES];
[builder setShake:YES];
[builder setSposId:@"20300726"];
[builder setSizeToFit:NO];
// [builder setWidth:UIViewAutoresizingFlexibleWidth];
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
CGFloat width = screenWidth; // 添加这行
[builder setAdSize:CGSizeMake(width, 0)]; // 添加这行
[[AdvistaSDK sharedInstance] loadNativeAdWithParams:builder.build listener:self];
}
- (void)onAdClicked {
}
- (void)onAdClosed {
}
- (void)onAdExposure {
}
- (void)onAdFailedToLoad:(NSInteger)code errorMsg:(nonnull NSString *)errorMsg {
}
- (void)onAdLoaded:(nonnull AdvistaTemplateAd *)ad {
if (ad) {
self.feedsAd = ad;
[self.view makeToast:@"原生广告加载成功"];
}
}
- (void)onResourceReady {
[self showAd];
}
- (void)onShowError:(NSInteger)code errorMsg:(nonnull NSString *)errorMsg {
}
- (void)showAd {
if (self.feedsAd && self.feedsAd.isReady) {
// 先移除之前的广告视图
for (UIView *subview in self.view.subviews) {
if ([subview isKindOfClass:[AdvistaBaseAdView class]]) {
[subview removeFromSuperview];
}
}
AdvistaBaseAdView *adView = [_feedsAd getAdView];
[self.view addSubview:adView];
}
}
@end开发者自渲染:
广告加载参数AdLoadParams.Builder方法说明
| 方法 | 说明 | 是否必填 |
|---|---|---|
| setSposId:(NSString *)sposId | 设置代码位id,sposId不能为空 | 必填 |
| setLoadTimeOut:(NSInteger)loadTimeOut | 加载超时时间,默认5s(单位:毫秒) | 可选 |
| setUserId:(NSString *)userId | 设置用户ID,用于激励视频奖励验证 | 可选 |
| setExtraInfo:(NSString *)extraInfo | 设置自定义信息,会传递给服务端 | 可选 |
AdvistaSelfRenderAdListener代理方法
@protocol AdvistaSelfRenderAdListener <NSObject>
- (void)onSelfRenderAdLoaded:(AdvistaNativeFeedsData *)nativeFeedsData;
- (void)onSelfRenderAdLoadError:(NSInteger)code message:(NSString *)message;
- (void)onSelfRenderAdClosed;
- (void)onSelfRenderAdExposure;
- (void)onSelfRenderAdExposureFailed:(NSInteger)code message:(NSString *)message;
- (void)onSelfRenderAdClicked;
@end自渲染素材类AdvistaNativeFeedsData
| 属性 | 说明 |
|---|---|
| getMaterialType | 0: 素材是图片内容 , 1: 素材是视频内容 |
| getVideoUrl | 视频地址 |
| getImageUrl | 图片地址 |
| getIconUrl | 广告的logo |
| getAdsLogoBitmap | 广告角标 |
| getDesc | 描述 |
| getECPM | 价格 |
| getTitle | 标题 |
| getCtaText | 交互按钮文案 |
| getLogoBitmap | 广告的logo地址 |
| getMainImageWidth | 图片宽度 |
| getMainImageHeight | 图片高度 |
| getVideoPlayer | 广告视频播放的view |
AdvistaNativeFeedsData方法介绍
| 方法 | 说明 |
|---|---|
| registerSelfRenderViews | 绑定广告数据对象,渲染广告视图前调用,注册可点击子视图数组,设置摇一摇尺寸 |
AdvistaNativeVideoViewDelegate方法
@protocol AdvistaNativeVideoViewDelegate <NSObject>
- (void)onVideoLoading;//视频加载
- (void)onVideoReady;//视频ready
- (void)onVideoStart;//视频开始
- (void)onVideoProgress:(double)progress;//视频进度
- (void)onVideoPause;//视频暂停
- (void)onVideoResume;//视频恢复
- (void)onVideoCompleted;//视频结束
- (void)onVideoStop;//视频停止
- (void)onVideoError:(NSInteger)errorType;//视频错误接入示例
#import "SelfRenderViewController.h"
#import "AdvistaSdk.h"
#import "AdvistaSelfRenderAd.h"
#import "AdvistaNativeVideoPlayerView.h"
#import "UIView+Toast.h"
#import "Constant.h"
@interface SelfRenderViewController() <AdvistaSelfRenderAdListener>
@end
@implementation SelfRenderViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setupUI];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
tapGesture.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tapGesture];
self.selfRenderText.text = ADVISTA_SELF_RENDER_ID;
}
- (void)setupUI {
// 创建广告容器视图
self.adContainerView = [[UIView alloc] init];
self.adContainerView.backgroundColor = [UIColor whiteColor];
self.adContainerView.layer.cornerRadius = 8;
self.adContainerView.layer.shadowColor = [UIColor blackColor].CGColor;
self.adContainerView.layer.shadowOffset = CGSizeMake(0, 2);
self.adContainerView.layer.shadowOpacity = 0.1;
self.adContainerView.layer.shadowRadius = 4;
self.adContainerView.hidden = YES;
[self.view addSubview:self.adContainerView];
// 创建广告图片视图
self.adImageView = [[UIImageView alloc] init];
self.adImageView.contentMode = UIViewContentModeScaleAspectFill;
self.adImageView.clipsToBounds = YES;
self.adImageView.layer.cornerRadius = 4;
[self.adContainerView addSubview:self.adImageView];
// 创建标题标签
self.titleLabel = [[UILabel alloc] init];
self.titleLabel.font = [UIFont boldSystemFontOfSize:16];
self.titleLabel.textColor = [UIColor blackColor];
self.titleLabel.numberOfLines = 2;
[self.adContainerView addSubview:self.titleLabel];
// 创建副标题标签
self.subTitleLabel = [[UILabel alloc] init];
self.subTitleLabel.font = [UIFont systemFontOfSize:14];
self.subTitleLabel.textColor = [UIColor grayColor];
self.subTitleLabel.numberOfLines = 1;
[self.adContainerView addSubview:self.subTitleLabel];
// 创建更多按钮
self.moreButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.moreButton setTitle:@"了解更多" forState:UIControlStateNormal];
[self.moreButton setTitleColor:[UIColor systemBlueColor] forState:UIControlStateNormal];
self.moreButton.titleLabel.font = [UIFont systemFontOfSize:12];
self.moreButton.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.0];
self.moreButton.layer.cornerRadius = 4;
self.moreButton.contentEdgeInsets = UIEdgeInsetsMake(4, 8, 4, 8);
[self.adContainerView addSubview:self.moreButton];
// 创建关闭按钮
self.closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.closeButton setTitle:@"×" forState:UIControlStateNormal];
[self.closeButton setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
self.closeButton.titleLabel.font = [UIFont boldSystemFontOfSize:18];
// 添加点击事件
[self.closeButton addTarget:self action:@selector(onCloseButtonTapped) forControlEvents:UIControlEventTouchUpInside];
[self.adContainerView addSubview:self.closeButton];
// 创建广告角标
self.adsLogoView = [[UIImageView alloc] init];
self.adsLogoView.contentMode = UIViewContentModeScaleAspectFit;
[self.adContainerView addSubview:self.adsLogoView];
// 创建视频状态标签
self.videoStatusLabel = [[UILabel alloc] init];
self.videoStatusLabel.font = [UIFont systemFontOfSize:12];
self.videoStatusLabel.textColor = [UIColor whiteColor];
self.videoStatusLabel.textAlignment = NSTextAlignmentCenter;
self.videoStatusLabel.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
self.videoStatusLabel.layer.cornerRadius = 4;
self.videoStatusLabel.clipsToBounds = YES;
self.videoStatusLabel.text = @"视频加载中...";
self.videoStatusLabel.hidden = YES;
[self.adContainerView addSubview:self.videoStatusLabel];
// 创建视频进度条
self.videoProgressView = [[UIProgressView alloc] init];
self.videoProgressView.progressTintColor = [UIColor systemBlueColor];
self.videoProgressView.trackTintColor = [UIColor lightGrayColor];
self.videoProgressView.hidden = YES;
[self.adContainerView addSubview:self.videoProgressView];
// 创建播放/暂停按钮
self.playPauseButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.playPauseButton setTitle:@"播放" forState:UIControlStateNormal];
[self.playPauseButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
self.playPauseButton.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
self.playPauseButton.layer.cornerRadius = 4;
self.playPauseButton.hidden = YES;
[self.playPauseButton addTarget:self action:@selector(onPlayPauseTapped) forControlEvents:UIControlEventTouchUpInside];
[self.adContainerView addSubview:self.playPauseButton];
// 创建静音按钮
self.muteButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.muteButton setTitle:@"静音" forState:UIControlStateNormal];
[self.muteButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
self.muteButton.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
self.muteButton.layer.cornerRadius = 4;
self.muteButton.hidden = YES;
[self.muteButton addTarget:self action:@selector(onMuteTapped) forControlEvents:UIControlEventTouchUpInside];
[self.adContainerView addSubview:self.muteButton];
// 设置约束
[self setupConstraints];
}
- (void)setupConstraints {
// 设置广告容器约束
self.adContainerView.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[self.adContainerView.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor],
[self.adContainerView.topAnchor constraintEqualToAnchor:self.view.topAnchor],
[self.adContainerView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:10],
[self.adContainerView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-10],
[self.adContainerView.heightAnchor constraintEqualToConstant:100]
]];
// 设置广告图片约束 - 左侧
self.adImageView.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[self.adImageView.leadingAnchor constraintEqualToAnchor:self.adContainerView.leadingAnchor constant:12],
[self.adImageView.topAnchor constraintEqualToAnchor:self.adContainerView.topAnchor constant:12],
[self.adImageView.bottomAnchor constraintEqualToAnchor:self.adContainerView.bottomAnchor constant:-12],
[self.adImageView.widthAnchor constraintEqualToConstant:132],
[self.adImageView.heightAnchor constraintEqualToConstant:74]
]];
// 设置标题约束 - 右侧
self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[self.titleLabel.leadingAnchor constraintEqualToAnchor:self.adImageView.trailingAnchor constant:12],
[self.titleLabel.topAnchor constraintEqualToAnchor:self.adImageView.topAnchor],
[self.titleLabel.trailingAnchor constraintEqualToAnchor:self.adContainerView.trailingAnchor constant:-12]
]];
// 设置更多按钮约束 - 底部
self.moreButton.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[self.moreButton.trailingAnchor constraintEqualToAnchor:self.adContainerView.trailingAnchor constant:-40],
[self.moreButton.bottomAnchor constraintEqualToAnchor:self.adImageView.bottomAnchor],
[self.moreButton.widthAnchor constraintEqualToConstant:68]
]];
// 添加调试日志
// 设置副标题约束 - 标题下方
self.subTitleLabel.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[self.subTitleLabel.bottomAnchor constraintEqualToAnchor:self.adImageView.bottomAnchor],
[self.subTitleLabel.leadingAnchor constraintEqualToAnchor:self.titleLabel.leadingAnchor],
[self.subTitleLabel.trailingAnchor constraintEqualToAnchor:self.moreButton.leadingAnchor]
]];
// 设置关闭按钮约束 - 右上角
self.closeButton.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[self.closeButton.trailingAnchor constraintEqualToAnchor:self.adContainerView.trailingAnchor constant:-10],
[self.closeButton.bottomAnchor constraintEqualToAnchor:self.adImageView.bottomAnchor]
]];
// 设置广告角标约束
self.adsLogoView.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[self.adsLogoView.leadingAnchor constraintEqualToAnchor:self.adImageView.leadingAnchor],
[self.adsLogoView.bottomAnchor constraintEqualToAnchor:self.adImageView.bottomAnchor]
]];
// 修改视频状态标签约束 - 不要覆盖整个广告图片区域
self.videoStatusLabel.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[self.videoStatusLabel.leadingAnchor constraintEqualToAnchor:self.adImageView.leadingAnchor],
[self.videoStatusLabel.trailingAnchor constraintEqualToAnchor:self.adImageView.trailingAnchor],
[self.videoStatusLabel.topAnchor constraintEqualToAnchor:self.adImageView.topAnchor],
[self.videoStatusLabel.heightAnchor constraintEqualToConstant:20] // 设置固定高度,不要覆盖整个区域
]];
// 修改视频进度条约束 - 放在广告图片底部
self.videoProgressView.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[self.videoProgressView.leadingAnchor constraintEqualToAnchor:self.adImageView.leadingAnchor],
[self.videoProgressView.trailingAnchor constraintEqualToAnchor:self.adImageView.trailingAnchor],
[self.videoProgressView.bottomAnchor constraintEqualToAnchor:self.adImageView.bottomAnchor constant:-5],
[self.videoProgressView.heightAnchor constraintEqualToConstant:2]
]];
// 修改播放/暂停按钮约束 - 放在广告图片中心,但不要与状态标签重叠
self.playPauseButton.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[self.playPauseButton.centerXAnchor constraintEqualToAnchor:self.adImageView.centerXAnchor],
[self.playPauseButton.centerYAnchor constraintEqualToAnchor:self.adImageView.centerYAnchor constant:10], // 向下偏移10点,避免与状态标签重叠
[self.playPauseButton.widthAnchor constraintEqualToConstant:60],
[self.playPauseButton.heightAnchor constraintEqualToConstant:30]
]];
self.muteButton.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[self.muteButton.trailingAnchor constraintEqualToAnchor:self.adImageView.trailingAnchor constant:-5],
[self.muteButton.topAnchor constraintEqualToAnchor:self.adImageView.topAnchor constant:5],
[self.muteButton.widthAnchor constraintEqualToConstant:40],
[self.muteButton.heightAnchor constraintEqualToConstant:25]
]];
}
- (void)loadAd {
self.isLoadAndShow = NO;
AdLoadParamsBuilder* builder = [[AdLoadParamsBuilder alloc]init];
[builder setSposId:self.selfRenderText.text];
AdLoadParams *params = builder.build;
[[AdvistaSDK sharedInstance] loadSelfRenderAdWithParams:params listener:self];
}
- (BOOL)isReady {
if (self.nativeData) {
return YES;
}
return NO;
}
- (void)showAd {
if (self.nativeData) {
[self renderAdWithNativeData:self.nativeData];
}
}
- (void)loadAndShow {
self.isLoadAndShow = YES;
AdLoadParamsBuilder* builder = [[AdLoadParamsBuilder alloc]init];
[builder setSposId:self.selfRenderText.text];
AdLoadParams *params = builder.build;
[[AdvistaSDK sharedInstance] loadSelfRenderAdWithParams:params listener:self];
}
- (void)renderAdWithNativeData:(AdvistaNativeFeedsData *)nativeData {
self.adContainerView.hidden = NO;
self.adContainerView.alpha = 1.0;
self.titleLabel.text = [nativeData getTitle];
self.subTitleLabel.text = [nativeData getDesc];
UIImage *logoImage = [nativeData getAdsLogoBitmap];
if (logoImage) {
self.adsLogoView.image = logoImage;
}
// 根据素材类型设置内容
if (nativeData.materialType == 1) {
// 视频素材
[self setupVideoContent:nativeData];
} else {
// 图片素材
[self setupImageContent:nativeData];
}
// 注册自渲染视图
[nativeData registerSelfRenderViews:self.adContainerView
clickViews:@[self.adContainerView, self.moreButton]
shakeWidth:100
shakeHeight:50];
}
- (void)setupVideoContent:(AdvistaNativeFeedsData *)nativeData {
// 隐藏图片,显示视频
self.adImageView.hidden = YES;
// 显示视频控制UI
self.videoStatusLabel.hidden = NO;
self.videoProgressView.hidden = NO;
self.playPauseButton.hidden = NO;
self.muteButton.hidden = NO;
// 获取视频播放器
AdvistaNativeVideoPlayerView *videoPlayer = [nativeData getVideoPlayer];
if (videoPlayer) {
// 设置视频播放器的监听器
videoPlayer.listener = self;
[videoPlayer showInView:self.adContainerView withFrame:self.adImageView.frame];
}
}
- (void)setupImageContent:(AdvistaNativeFeedsData *)nativeData {
// 显示图片,隐藏视频
self.adImageView.hidden = NO;
// 加载广告图片
NSString *imageUrl = [nativeData getImageUrl];
if (imageUrl && imageUrl.length > 0) {
[self loadImageFromURL:imageUrl];
}
}
- (void)loadImageFromURL:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
if (url) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *data = [NSData dataWithContentsOfURL:url];
if (data) {
UIImage *image = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
self.adImageView.image = image;
});
}
});
}
}
- (void)onSelfRenderAdLoaded:(AdvistaNativeFeedsData *)nativeFeedsData{
[self.view makeToast:@"加载成功" duration:1.0 position:[CSToastManager defaultPosition]];
if (nativeFeedsData) {
self.nativeData = nativeFeedsData;
if (self.isLoadAndShow) {
[self showAd];
}
}
}
- (void)onSelfRenderAdLoadError:(NSInteger)code message:(NSString *)message{
[self.view makeToast:message];
}
- (void)onSelfRenderAdClosed {
// 可以在这里添加额外的关闭处理逻辑
}
- (void)onSelfRenderAdExposure {
// 可以在这里添加曝光成功的处理逻辑
}
- (void)onSelfRenderAdExposureFailed:(NSInteger)code message:(NSString *)message {
// 可以在这里添加曝光失败的处理逻辑
[self.view makeToast:[NSString stringWithFormat:@"广告曝光失败: %@", message] duration:1.0 position:[CSToastManager defaultPosition]];
}
- (void)onSelfRenderAdClicked {
// 可以在这里添加点击处理逻辑
[self.view makeToast:@"广告被点击了!" duration:1.0 position:[CSToastManager defaultPosition]];
}
// 在文件末尾添加关闭按钮的点击处理方法
- (void)onCloseButtonTapped {
// 隐藏广告容器
[self hideAd];
}
// 添加隐藏广告的方法
- (void)hideAd {
// 隐藏广告容器
[UIView animateWithDuration:0.3 animations:^{
self.adContainerView.alpha = 0.0;
} completion:^(BOOL finished) {
// [self.adContainerView removeFromSuperview];
self.adContainerView.hidden = YES;
}];
// 停止视频播放(如果有)
if (self.nativeData && self.nativeData.videoPlayerView) {
[self.nativeData.getVideoPlayer destroy];
}
// 清理资源
[self cleanupAdResources];
}
// 添加清理广告资源的方法
- (void)cleanupAdResources {
// 清理自渲染视图
if(self.nativeData){
[self.nativeData destroy];
}
}
// 在文件最后添加
#pragma mark - AdvistaNativeVideoViewListener
- (void)onVideoLoading {
dispatch_async(dispatch_get_main_queue(), ^{
self.videoStatusLabel.text = @"视频加载中...";
self.videoStatusLabel.hidden = NO;
self.playPauseButton.hidden = YES;
});
}
- (void)onVideoReady {
dispatch_async(dispatch_get_main_queue(), ^{
self.videoStatusLabel.text = @"视频准备就绪";
self.videoStatusLabel.hidden = NO;
self.playPauseButton.hidden = NO;
[self.playPauseButton setTitle:@"播放" forState:UIControlStateNormal];
});
}
- (void)onVideoStart {
dispatch_async(dispatch_get_main_queue(), ^{
self.videoStatusLabel.hidden = YES;
self.playPauseButton.hidden = NO;
[self.playPauseButton setTitle:@"暂停" forState:UIControlStateNormal];
});
}
- (void)onVideoProgress:(double)progress {
dispatch_async(dispatch_get_main_queue(), ^{
self.videoProgressView.progress = progress;
});
}
- (void)onVideoPause {
dispatch_async(dispatch_get_main_queue(), ^{
[self.playPauseButton setTitle:@"播放" forState:UIControlStateNormal];
});
}
- (void)onVideoResume {
dispatch_async(dispatch_get_main_queue(), ^{
[self.playPauseButton setTitle:@"暂停" forState:UIControlStateNormal];
});
}
- (void)onVideoCompleted {
dispatch_async(dispatch_get_main_queue(), ^{
self.videoStatusLabel.text = @"视频播放完成";
self.videoStatusLabel.hidden = NO;
[self.playPauseButton setTitle:@"重播" forState:UIControlStateNormal];
});
}
- (void)onVideoStop {
dispatch_async(dispatch_get_main_queue(), ^{
self.videoStatusLabel.text = @"视频已停止";
self.videoStatusLabel.hidden = NO;
[self.playPauseButton setTitle:@"播放" forState:UIControlStateNormal];
});
}
- (void)onVideoError:(NSInteger)errorType {
dispatch_async(dispatch_get_main_queue(), ^{
self.videoStatusLabel.text = [NSString stringWithFormat:@"视频错误: %ld", (long)errorType];
self.videoStatusLabel.hidden = NO;
[self.playPauseButton setTitle:@"重试" forState:UIControlStateNormal];
});
}
- (void)onPlayPauseTapped {
AdvistaNativeVideoPlayerView *videoPlayer = [self.nativeData getVideoPlayer];
if (videoPlayer) {
if ([self.playPauseButton.titleLabel.text isEqualToString:@"播放"] ||
[self.playPauseButton.titleLabel.text isEqualToString:@"重播"]) {
[videoPlayer startVideo];
} else if ([self.playPauseButton.titleLabel.text isEqualToString:@"暂停"]) {
[videoPlayer pauseVideo];
}
}
}
- (void)onMuteTapped {
AdvistaNativeVideoPlayerView *videoPlayer = [self.nativeData getVideoPlayer];
if (videoPlayer) {
BOOL isMuted = videoPlayer.isMuted;
[videoPlayer setVideoMute:!isMuted];
[self.muteButton setTitle:isMuted ? @"静音" : @"取消静音" forState:UIControlStateNormal];
}
}
// 点击空白处时调用的方法
- (void)dismissKeyboard {
[self.view endEditing:YES];
}
@end激励视频
概述
激励视频广告是一种全屏视频形式,用户完整观看后可领取奖励。这种广告常见于游戏中,如复活、获取道具或额外通关奖励等场景,以及应用内的增值服务,例如单次体验付费功能。
广告加载参数AdLoadParams.Builder方法说明
| 方法 | 说明 | 是否必填 |
|---|---|---|
| setSposId:(NSString *)sposId | 设置代码位id,sposId不能为空 | 必填 |
| setLoadTimeOut:(NSInteger)loadTimeOut | 加载超时时间,默认5s(单位:毫秒) | 可选 |
| setMute:(BOOL)isMute | 设置视频素材是否默认静音 | 可选 |
| setShake:(BOOL)isShake | 是否允许摇一摇广告,默认YES | 可选 |
| setUserId:(NSString *)userId | 设置用户ID,用于激励视频奖励验证 | 可选 |
| setExtraInfo:(NSString *)extraInfo | 设置自定义信息,会传递给服务端 | 可选 |
AdvistaTemplateAd方法说明
| 方法/属性 | 含义 |
|---|---|
| isReady | 对于已经加载成功,但未及时展示的广告,在展示前用此方法判断广告是否还可用 |
| showAdInWindow | 用于调用已经加载成功的广告的展示 |
| getECPM | 获取当前广告的价格 单位 分(人民币) |
AdvistaRewardVideoAd的代理方法:
@protocol AdvistaAdDelegate <NSObject>
@required
/// 广告加载成功
- (void)onAdLoaded:(AdvistaTemplateAd *)ad;
/// 广告的加载的各种错误信息
- (void)onAdFailedToLoad:(NSInteger)code errorMsg:(NSString *)errorMsg;
/// 广告展示的错误信息
- (void)onShowError:(NSInteger)code errorMsg:(NSString *)errorMsg;
/// 点击了广告
- (void)onAdClicked;
/// 关闭了广告
- (void)onAdClosed;
/// 广告曝光了
- (void)onAdExposure;
/// 广告资源加载成功
- (void)onResourceReady;
@optional
/// 激励视频奖励验证结果
- (void)onRewardVerify:(AdvistaRewardInfo *)rewardInfo;
@endAdvistaRewardInfo属性介绍
| 属性 | 含义 |
|---|---|
| rewardValid | 服务端校验结果 |
| userId | 用户ID |
| transId | transid |
| rewardAmount | 奖励数量 |
| rewardName | 奖励名称 |
| errCode | 错误码 |
| errMsg | 错误信息 |
| extraInfo | 自定义信息 |
激励视频广告的使用
#import "RewardVideoViewController.h"
#import "AdvistaSdk.h"
#import "AdvistaTemplateAd.h"
#import "UIView+Toast.h"
#import "Constant.h"
@interface RewardVideoViewController ()
@end
@implementation RewardVideoViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.rewardTxt.returnKeyType = UIReturnKeyDone;
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
tapGesture.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tapGesture];
self.rewardTxt.text = ADVISTA_REWARD_ID;
}
- (void)checkReady{
if (self.rewardVideoAd) {
if (self.rewardVideoAd.isReady) {
[self.view makeToast:@"广告准备就绪" duration:1.0 position:[CSToastManager defaultPosition]];
} else {
[self.view makeToast:@"广告未准备就绪" duration:1.0 position:[CSToastManager defaultPosition]];
}
}
}
- (void)checkReady:(id)sender {
[self checkReady];
}
- (void)loadAd{
_loadShow = NO;
AdLoadParamsBuilder *builder = [[AdLoadParamsBuilder alloc]init];
[builder setMute:YES];
[builder setShake:_shakeSwitch.on];
[builder setSposId:self.rewardTxt.text];
[[AdvistaSDK sharedInstance] loadRewardVideoWithParams:builder.build listener:self];
}
- (void)showAd{
if (self.rewardVideoAd && self.rewardVideoAd.isReady) {
// 先移除之前的广告视图
[self.rewardVideoAd showAdInWindow:self.view.window];
}
}
- (void)showAd:(id)sender {
[self showAd];
}
- (void)loadAndShow{
_loadShow = YES;
AdLoadParamsBuilder *builder = [[AdLoadParamsBuilder alloc]init];
[builder setMute:YES];
[builder setShake:_shakeSwitch.on];
[builder setSposId:self.rewardTxt.text];
[[AdvistaSDK sharedInstance] loadRewardVideoWithParams:builder.build listener:self];
}
- (void)loadAndShow:(id)sender {
[self loadAndShow];
}
- (void)onAdClicked {
[self.view makeToast:@"广告点击" duration:1.0 position:[CSToastManager defaultPosition]];
}
- (void)onAdClosed {
[self.view makeToast:@"广告关闭" duration:1.0 position:[CSToastManager defaultPosition]];
}
- (void)onAdExposure {
[self.view makeToast:@"广告曝光" duration:1.0 position:[CSToastManager defaultPosition]];
}
- (void)onAdFailedToLoad:(NSInteger)code errorMsg:(nonnull NSString *)errorMsg {
[self.view makeToast:@"广告加载失败" duration:1.0 position:[CSToastManager defaultPosition]];
}
- (void)onAdLoaded:(nonnull AdvistaTemplateAd *)ad {
[self.view makeToast:@"广告加载成功" duration:1.0 position:[CSToastManager defaultPosition]];
self.rewardVideoAd = ad;
}
- (void)onResourceReady {
[self.view makeToast:@"广告isReady" duration:1.0 position:[CSToastManager defaultPosition]];
if (_loadShow) {
[self showAd];
}
}
- (void)onShowError:(NSInteger)code errorMsg:(nonnull NSString *)errorMsg {
}
- (void)onRewardVerify:(AdvistaRewardInfo *)rewardInfo{
if (rewardInfo.rewardValid) {
// 奖励验证成功,发放奖励
NSLog(@"奖励验证成功: %@, 数量: %@", rewardInfo.rewardName, rewardInfo.rewardAmount);
} else {
// 奖励验证失败
NSLog(@"奖励验证失败: %@", rewardInfo.errMsg);
}
}
@end错误码说明
SDK 在回调中会返回错误码和错误信息,常见的错误码如下:
SDK 初始化相关错误码
| 错误码 | 说明 |
|---|---|
| 10001 | 初始化失败 |
| 10002 | SDK 已经初始化 |
| 10003 | SDK 未初始化 |
广告加载相关错误码
| 错误码 | 说明 |
|---|---|
| 60001 | 无广告填充 |
| 60002 | 应用ID或代码位ID不存在 |
| 60003 | 代码位ID为空 |
| 60004 | 应用或代码位ID不合法 |
| 60005 | 代码位ID不合法 |
| 60006 | 应用或代码位ID不匹配 |
| 60007 | 代码位类型不匹配 |
| 60008 | 代码位请求尺寸不能为空 |
| 60009 | 加载超时 |
| 60010 | 其他异常,请联系技术人员 |
| 60011 | AdListener对象为空 |
广告展示相关错误码
| 错误码 | 说明 |
|---|---|
| 70001 | viewGroup为空 |
| 70002 | 广告超时 |
| 70003 | 请将原生广告添加到viewGroup中 |
| 70004 | 原生广告容器太小,无法展示 |
| 70005 | 广告已被销毁 |
| 70006 | 广告已展示 |
| 70007 | 广告渲染类型不匹配 |
| 70008 | 请将激励视频广告添加到window中 |
| 70009 | Window已销毁 |
| 70010 | 广告已过期,无法展示 |
