FCAdsSDK 1.0.1

FCAdsSDK 1.0.1

suqiangaiken 维护。



 
依赖
GDTMobSDK= 4.14.42
广告-CN= 5.2.0.5
KSA指纹= 3.3.51.1
百度指纹= 5.313
 

FCAdsSDK 1.0.1

  • yifan

亿帆SDK对接文档: V1.0.0

1.开发文档修改记录

版本号 修改内容 更新步骤 更新时间
1.0.0 2023.09.08

2.支持的SDK平台及广告位

平台 版本 开屏 激励视频 横幅 插屏 信息流 全屏视频
穿山甲 5.2.0.5
优量汇 4.14.42
百青藤 5.313
快手 3.3.51.1

注意: 1.该版本是基于上述SDK平台版本进行开发的 2.SDK支持的架构有:armv7 x86_64 arm64 3.支持iOS版本为9.0及以上

3. 快速接入

3.1 开发环境准备

  • 开发工具:建议使用Xcode 12及以上版本
  • 部署目标:iOS 9.0及以上版本
  • 开发管理工具:CocoaPods

3.2 引入SDK

方法一:

右键单击项目,选择“将文件添加到…”菜单,选择解压SDK包后得到的FCAdsSDK.framework文件,然后点击“添加”。或者,将文件拖动到Xcode项目文件夹结构中,在弹出的界面中勾选“如果需要则复制项目到目标分组文件夹”,并确保“添加到目标”项选中相应的目标。同时将FCAdsSDK.framework文件夹内的FCAdsSDK.bundle文件导入Xcode。

方法二(推荐):

通过Cocoapods引入第三方广告SDK以及第三方依赖(如果遇到拉取不下来的问题,可能是github访问问题,可以使用VPN解决)。

#优量汇⼴告
 pod 'GDTMobSDK', '4.14.42'
#穿⼭甲⼴告
 pod 'Ads-CN', '5.2.0.5'
#快⼿⼴告SDK
 pod 'KSAdSDK', '3.3.51.1', :inhibit_warnings => false
#百度⼴告SDK
 pod 'BaiduMobAdSDK', '5.313'

注意事项:

1.HTTP权限设置:

设置HTTP权限请求,需要在info.plist中增加一条App Transport Security Settings,添加Allow Arbitrary Loads(NSAllowsArbitraryLoads),值为YES

2.删除Scene:

1.首先直接删除SceneDelegate.h .m文件 2.在AppDelegate.h添加@property (strong, nonatomic) UIWindow * window;属性 3.移除AppDelegate中的UIScene代理 4.最后在info.plist文件中移除Application Scene Manifest

3.头文件冲突:

如果遇到头文件冲突的问题,可能是other linker flags的设置问题。删除TARGETS->Linking->Other Linker Flags中的-all_load

4.Bitcode:

由于第三方库的原因,我们需要在Xcode中关闭Bitcode。设置TARGETS->Build Settings->Enable Bitcode为NO

5.位置权限:

如果应用开启了位置权限,SDK可以获取应用位置信息用以精准推送广告,需要在应用的info.plist添加相应权限提示信息,避免AppStore审核被拒:

Privacy - Location When In Use Usage Description
Privacy - Location Always and When In Use Usage Description
Privacy - Location Always Usage Description
Privacy - Location Usage Description

6.iOS14适配(重要):

由于iOS14.5系统策略更新,我们需要在App中添加SKAdNetwork标识和ATT权限,以避免广告收益降低。

1.升级穿山甲iOS SDK 3.4.2.3及以上版本,升级广点通4.12.3及以上版本,提供了iOS14与SKAdNetwork的支持 2.将SKAdNetwork ID添加到info.plist中,以保证SKAdNetwork的正确运行,以下内容复制到您的info.plist中,

穿⼭甲:238da6jt44.skadnetwork,22mmun2rn5.skadnetwork,x2jnk7ly8j.skadnetwork
⼴点通:f7s53z58qe.skadnetwork
爱奇艺:27a282f54n.skadnetwork
<key>SKAdNetworkItems</key>
  <array>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>238da6jt44.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>22mmun2rn5.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>f7s53z58qe.skadnetwork</string>
    </dict>
     <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>r3y5dwb26t.skadnetwork</string>
    </dict>
  </array>

3.获取App Tracking Transparency权限,请更新您的Info.plist,添加NSUserTrackingUsageDescription字段和自定义文案描述

<key>NSUserTrackingUsageDescription</key>
<string>该标识符将⽤于向您投放个性化⼴告</string>

4.从iOS 14开始,在应用程序调用App Tracking Transparency向用户提跟踪授权请求之前,IDFA将不可用。如果应用未提出此请求,应用获取到的IDFA将自动清零,可能会导致您的广告收入降低

#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <AdSupport/AdSupport.h>
- (void)requestIDFA {
 [ATTrackingManager
requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthoriza
tionStatus status) {
 }];
 // 
 [self loadAd];
}

3.3 跳转须知

广告接口中的所有ViewController均为必传项,用来处理广告跳转。SDK中所有的跳转均采用present的方式,请确保传入的rootViewController不能为空且没有present其他的控制器,否则会出现presentedViewController已经存在而导致present失败。

3.4 请求失败可能的原因

  1. 应用包名,appID, appKey, posID必须匹配。(不能直接用demo中的appkey和posID在你的工程中请求广告)。
  2. 确保网络连接正常。(可用Wi-Fi和手机网络分别请求广告验证)。
  3. 同一天,同一设备,广告展示有次数限制。(可更换不同设备请求广告)。
  4. 测试设备不要限制广告跟踪(广告请求需要获取idfa)。
  5. 广告请求不能保证每次都有广告返回。(广告不能频繁请求)。

3.5 初始化SDK及全局配置

3.6 扩展字段参数

目前支持多维度的扩展字段,可以设置自定义数据,后台可以根据维度进行云控和数据统计


4. 广告渲染

4.1 开屏广告

*开屏广告目前不支持横屏,支持的广告源:穿山甲、广点通、快手、百度

1. 请求代码


   FCAdSplash *splash = [[FCAdSplash alloc] initWithAdUnitID:@"0bbcfd82-779d-4ff8-9a38-781b31c5ab61"viewController:self];
   splash.delegate = self;
   splash.showLogoRequire = YES;
   splash.logoImage = [UIImage imageNamed:@"app_logo"];
   splash.backgroundImage = [UIImage imageNamed:@"LaunchImage_img"];
   splash.timeout = 5;
   [splash loadAndShowAd];

2. 回调方法

/// 广告数据拉取成功
- (void)fcAdUnifiedViewDidLoad {

}

/// 广告曝光成功
- (void)fcAdExposured {
  
}

/// 广告加载失败
- (void)fcAdFailedWithError:(NSError *)error description:(NSDictionary *)description{


}

/// 内部渠道开始加载时调用
- (void)fcAdSupplierWillLoad:(NSString *)supplierId {


}

/// 广告点击
- (void)fcAdClicked {

}

/// 广告关闭
- (void)fcAdDidClose {
   
}

/// 广告倒计时结束
- (void)fcAdSplashOnAdCountdownToZero {

}

/// 点击了跳过
- (void)fcAdSplashOnAdSkipClicked {
  
}

开屏广告闪屏问题 1、首页闪现后弹出广告。这种现象对用户体验不友好。我们的方案是backgroundImage需要保持和App启动页一致,这样在加载开屏广告的时候,会覆盖在首页上,用户感觉不到是在加载App还是加载广告过程。

4.2 横幅广告

1. 请求代码

- (void)loadAdAndShow {
 
UIView *contentV = [[UIView alloc] initWithFrame:CGRectMake(0, 100, self.view.bounds.size.width, self.view.bounds.size.width * 400.0 /600.0)];
[self.view addSubview:contentV];

FCAdBanner * fcAdBanner = [[FCAdBanner alloc] initWithAdUnitID:pID adContainer:contentV viewController:self];
fcAdBanner.delegate = self;
[fcAdBanner loadAndShowAd];
}

2. 回调方法

/// 广告数据拉取成功回调
- (void)fcAdUnifiedViewDidLoad {

}

/// 广告加载失败
- (void)fcAdFailedWithError:(NSError *)error description:(NSDictionary *)description{

}


/// 内部渠道开始加载时调用
- (void)fcAdSupplierWillLoad:(NSString *)supplierId {

}

/// 广告曝光
- (void)fcAdExposured {

}

/// 广告点击
- (void)fcAdClicked {

}

/// 广告关闭回调
- (void)fcAdDidClose {
  
}




4.3 插屏广告

1. 请求代码

- (void)loadAdAndShow {
 
   FCAdInterstitial * fcAdInterstitial = [[FCAdInterstitial alloc] initWithAdUnitID:PID viewController:self];
   fcAdInterstitial.delegate = self;
   [fcAdInterstitial loadAndShowAd];
}

2. 回调方法

/// 广告数据拉取成功回调
- (void)fcAdUnifiedViewDidLoad {

}

/// 广告加载失败
- (void)fcAdFailedWithError:(NSError *)error description:(NSDictionary *)description{

}


/// 内部渠道开始加载时调用
- (void)fcAdSupplierWillLoad:(NSString *)supplierId {

}

/// 广告曝光
- (void)fcAdExposured {

}

/// 广告点击
- (void)fcAdClicked {

}

/// 广告关闭回调
- (void)fcAdDidClose {
  
}




4.4 全屏视频广告

1. 请求代码

- (void)loadAdAndShow {
 
FCAdFullScreenVideo * fcAdFullScreenVideo  = [[FCAdFullScreenVideo alloc] initWithAdUnitID:@"728b5f9b-9b97-404b-8897-1e7b3d719aaf" viewController:self];
fcAdFullScreenVideo.delegate=self;
[fcAdFullScreenVideo loadAndShowAd];
}

2. 回调方法

/// 请求广告数据成功后调用
- (void)fcAdUnifiedViewDidLoad {
  
}

/// 广告曝光
- (void)fcAdExposured {

}

/// 广告点击
- (void)fcAdClicked {
 
}

- (void)fcAdFailedWithError:(NSError *)error description:(NSDictionary *)description{
  
}

/// 内部渠道开始加载时调用
- (void)fcAdSupplierWillLoad:(NSString *)supplierId {


}

/// 广告关闭
- (void)fcAdDidClose {


}

/// 广告播放完成
- (void)fcAdFullScreenVideoOnAdPlayFinish {

}

4.4 激励视频广告

1. 请求代码

- (void)loadAdAndShow {
 
  FCAdRewardVideo * fcAdRewardVideo = [[FCAdRewardVideo alloc] initWithAdUnitID:PID viewController:self];
   fcAdRewardVideo.delegate=self;
   [fcAdRewardVideo loadAndShowAd];
}

2. 回调方法

/// 广告数据加载成功
- (void)fcAdUnifiedViewDidLoad {
 
}

/// 视频缓存成功
- (void)fcAdRewardVideoOnAdVideoCached {
 

}

/// 到达激励时间
- (void)fcAdRewardVideoAdDidRewardEffective {

}

/// 广告曝光
- (void)fcAdExposured {

}

/// 广告点击
- (void)fcAdClicked {
 
}

/// 广告加载失败
- (void)fcAdFailedWithError:(NSError *)error description:(NSDictionary *)description{



}

/// 内部渠道开始加载时调用
- (void)fcAdSupplierWillLoad:(NSString *)supplierId {
 
}

/// 广告关闭
- (void)fcAdDidClose {

}

/// 播放完成
- (void)fcAdRewardVideoAdDidPlayFinish {

}

4.5 激励视频广告

1. 请求代码

- (void)loadAdAndShow {
 
      FCAdNativeExpress * advanceFeed = [[FCAdNativeExpress alloc] initWithAdUnitID:PID adContainer:nil  viewController:self adSize:CGSizeMake(self.view.bounds.size.width, 0)];
   advanceFeed.delegate = self;
   [advanceFeed loadAndShowAd];
}

2. 回调方法

// 信息流广告比较特殊, 渲染逻辑需要自行处理
- (void)showNativeAd {
   for (NSInteger i = 0; i < self.arrViewsM.count; i++) {
       FCAdNativeExpressView *view = self.arrViewsM[i];
       [view render];
       [_dataArrM insertObject:self.arrViewsM[i] atIndex:1];
   }
   [self.tableView reloadData];

}

/// 广告数据拉取成功
- (void)fcAdNativeExpressOnAdLoadSuccess:(NSArray<FCAdNativeExpressView *> *)views {
   NSLog(@"广告拉取成功 %s", __func__);
   self.arrViewsM = [views mutableCopy];
   
   if (_isLoadAndShow) {
       [self showNativeAd];
   }
   


}


/// 广告曝光
- (void)fcAdNativeExpressOnAdShow:(FCAdNativeExpressView *)adView {

}

/// 广告点击
- (void)fcAdNativeExpressOnAdClicked:(FCAdNativeExpressView *)adView {
 
}

/// 广告渲染成功
/// 注意和广告数据拉取成功的区别  广告数据拉取成功, 但是渲染可能会失败
/// 广告加载失败 是广点通 穿山甲 mercury 在拉取广告的时候就全部失败了
/// 该回调的含义是: 比如: 广点通拉取广告成功了并返回了一组view  但是其中某个view的渲染失败了
/// 该回调会触发多次
- (void)fcAdNativeExpressOnAdRenderSuccess:(FCAdNativeExpressView *)adView {

   [self.tableView reloadData];
}

/// 广告渲染失败
/// 注意和广告加载失败的区别  广告数据拉取成功, 但是渲染可能会失败
/// 广告加载失败 是广点通 穿山甲 mercury 在拉取广告的时候就全部失败了
/// 该回调的含义是: 比如: 广点通拉取广告成功了并返回了一组view  但是其中某个view的渲染失败了
/// 该回调会触发多次
- (void)fcAdNativeExpressOnAdRenderFail:(FCAdNativeExpressView *)adView {

   [_dataArrM removeObject: adView];
   [self.tableView reloadData];
}

/// 广告加载失败
/// 该回调只会触发一次
- (void)fcAdFailedWithError:(NSError *)error description:(NSDictionary *)description{

   [self deallocAd];

}

/// 内部渠道开始加载时调用
- (void)fcAdSupplierWillLoad:(NSString *)supplierId {


}


/// 广告被关闭
- (void)fcAdNativeExpressOnAdClosed:(FCAdNativeExpressView *)adView {
   //需要从tableview中删除

   [_dataArrM removeObject: adView];
   [self.tableView reloadData];
}



// MARK: ======================= UITableViewDelegate, UITableViewDataSource =======================

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//    return _expressAdViews.count*2;
//    return 2;
   return _dataArrM.count;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
   if ([_dataArrM[indexPath.row] isKindOfClass:[BYExamCellModelElement class]]) {
       return ((BYExamCellModelElement *)_dataArrM[indexPath.row]).cellh;
   } else {
       CGFloat height = ([_dataArrM[indexPath.row] expressView]).frame.size.height;
       NSLog(@"=======> %f", height);
       return height;
   }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
   UITableViewCell *cell;
   if ([_dataArrM[indexPath.row] isKindOfClass:[BYExamCellModelElement class]]) {
       cell = [tableView dequeueReusableCellWithIdentifier:@"ExamTableViewCell"];
       ((ExamTableViewCell *)cell).item = _dataArrM[indexPath.row];
       return cell;
   } else {
       cell = [self.tableView dequeueReusableCellWithIdentifier:@"nativeexpresscell" forIndexPath:indexPath];
       cell.selectionStyle = UITableViewCellSelectionStyleNone;

       UIView *subView = (UIView *)[cell.contentView viewWithTag:1000];
       if ([subView superview]) {
           [subView removeFromSuperview];
       }
       UIView *view = [_dataArrM[indexPath.row] expressView];

       view.tag = 1000;
       [cell.contentView addSubview:view];
       cell.accessibilityIdentifier = @"nativeTemp_ad";
//        [view mas_remakeConstraints:^(MASConstraintMaker *make) {
//            make.edges.equalTo(@0);
//        }];

       return cell;
   }
}