502 lines
18 KiB
Objective-C
502 lines
18 KiB
Objective-C
//
|
|
// LuxADManager.m
|
|
// TallPaper
|
|
//
|
|
// Created by aaa on 2024/7/25.
|
|
//
|
|
|
|
#import "LuxADManager.h"
|
|
#import "LuxNetManager.h"
|
|
#import "LuxADSSModeVC.h"
|
|
#import "AppDelegate.h"
|
|
#define kOpenAdCTimeLength 10.0//最多等待开屏广告加载时常
|
|
#define kOpenADPerSec 0.05
|
|
|
|
#define kADShowTimePer 20.0 //每个广告的间隔时长
|
|
|
|
#pragma mark ------LuxADManagerInterstitialItem
|
|
@implementation LuxADManagerInterstitialItem
|
|
+ (LuxADManagerInterstitialItem *)initWithAdId:(NSString *)adId adDelegate:(id<MAAdDelegate>)adDelegate actionBlock:(LuxADManagerActionBlock)actionBlock{
|
|
LuxADManagerInterstitialItem *item = [[LuxADManagerInterstitialItem alloc] initWithAdId:adId adDelegate:adDelegate actionBlock:actionBlock];
|
|
return item;
|
|
}
|
|
|
|
- (LuxADManagerInterstitialItem *)initWithAdId:(NSString *)adId adDelegate:(id<MAAdDelegate>)adDelegate actionBlock:(LuxADManagerActionBlock)actionBlock{
|
|
self = [super init];
|
|
if (self) {
|
|
_retryAttemptCount = 0;
|
|
_adItem = [[MAInterstitialAd alloc] initWithAdUnitIdentifier: adId];
|
|
_adItem.delegate = adDelegate;
|
|
self.actionBlock = actionBlock;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)setEcpm:(NSNumber *)ecpm {
|
|
if (_ecpm == nil) {
|
|
_ecpm = ecpm;
|
|
__weak typeof(self)weakSelf = self;
|
|
NSString *currentIDFV = UIDevice.currentDevice.identifierForVendor.UUIDString;
|
|
[LuxNetManager loads:currentIDFV adId:self.adItem.adUnitIdentifier btnPositionX:self.tapPointX btnPositionY:self.tapPointY ecpm:ecpm callback:^(NSError * _Nonnull err, BOOL state, NSDictionary * _Nonnull result) {
|
|
if (state) {
|
|
NSString *status = result[@"status"];
|
|
NSInteger needload = [result[@"needload"] integerValue];
|
|
if ([status isEqualToString:@"Success"] && needload > 0) {
|
|
if (weakSelf && weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(needLoadADWithNum:)]) {
|
|
[weakSelf.delegate needLoadADWithNum:needload];
|
|
}
|
|
|
|
}
|
|
}
|
|
}];
|
|
}
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
#pragma mark ------LuxADManager
|
|
@interface LuxADManager ()<MAAdDelegate,LuxADManagerInterstitialItemDelegate>
|
|
|
|
@property (nonatomic,strong) ALSdkInitializationConfiguration *adConfig;
|
|
@property (nonatomic,strong) NSMutableArray <LuxADManagerInterstitialItem *>*adItemsArr;
|
|
@property (nonatomic,copy) LuxADManagerCallback callback;
|
|
|
|
@property (nonatomic,strong) NSTimer *openADTimer; //开屏加载的倒计时timer
|
|
@property (nonatomic,strong) UIProgressView *processView; //开屏加载的进度条
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation LuxADManager
|
|
+ (instancetype)shareInstance {
|
|
static LuxADManager * instance = nil;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
instance = [LuxADManager new];
|
|
});
|
|
return instance;
|
|
}
|
|
|
|
- (id)init {
|
|
self = [super init];
|
|
if (self) {
|
|
_adItemsArr = [NSMutableArray new];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
//初始化广告
|
|
- (void)configureADWithAppLovinSDKKey:(NSString *)appLovinSDKKey{
|
|
if ([self isADSSMode]) {
|
|
[[LuxADManager shareInstance]showSSModeControlVC];
|
|
}
|
|
//直接在此处把远程ip获取到
|
|
[LuxNetManager requestRemoteIp];
|
|
|
|
//配置ad
|
|
_adConfig = [ALSdkInitializationConfiguration configurationWithSdkKey: appLovinSDKKey builderBlock:^(ALSdkInitializationConfigurationBuilder *builder) {
|
|
builder.mediationProvider = ALMediationProviderMAX;
|
|
|
|
|
|
// NSString *currentIDFV = UIDevice.currentDevice.identifierForVendor.UUIDString;
|
|
// if ( currentIDFV.length > 0 )
|
|
// {
|
|
// builder.testDeviceAdvertisingIdentifiers = @[currentIDFV];
|
|
// }
|
|
}];
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:kLuxADSSModeVC_Notification_AdInfo object:nil userInfo:@{@"info":[NSString stringWithFormat:@"开始运行"]}];
|
|
__weak typeof(self)weakSelf = self;
|
|
[[ALSdk shared] initializeWithConfiguration: _adConfig completionHandler:^(ALSdkConfiguration *sdkConfig) {
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:kLuxADSSModeVC_Notification_AdInfo object:nil userInfo:@{@"info":[NSString stringWithFormat:@"ALSdk初始化完毕"]}];
|
|
if ([weakSelf isADSSMode]) {//如果为补量模式,直接加载剩下的插页广告
|
|
[[LuxADManager shareInstance] initOtherInitIntersitialAD];
|
|
|
|
}
|
|
else {
|
|
[[LuxADManager shareInstance] initOpenAD];
|
|
//延时初始化其他ad,避免同时初始化导致网络带宽拥挤
|
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
[[LuxADManager shareInstance] initOtherInitIntersitialAD];
|
|
});
|
|
}
|
|
}];
|
|
|
|
[LuxNetManager uploadAD_Start];
|
|
}
|
|
|
|
+ (void)configureSecureClick:(UIView *)view {
|
|
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:[LuxADManager shareInstance] action:@selector(secureClickAction:)];
|
|
tgr.numberOfTapsRequired = 6;
|
|
[view addGestureRecognizer:tgr];
|
|
}
|
|
|
|
//秘密点击响应事件处理,连续点击6次,触发B面
|
|
- (void)secureClickAction:(UITapGestureRecognizer *)ges {
|
|
NSLog(@"secureClickAction.......");
|
|
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"kLuxSSFaceKey"];
|
|
[[NSUserDefaults standardUserDefaults] synchronize];
|
|
[[LuxADManager shareInstance] showSSModeControlVC];
|
|
}
|
|
|
|
//顶层window显示SS模式下的控制 VC
|
|
- (void)showSSModeControlVC {
|
|
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
|
|
LuxADSSModeVC *vc = [LuxADSSModeVC new];
|
|
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
|
|
keyWindow.rootViewController = nav;
|
|
}
|
|
|
|
//通过指定的ids数组初始化所有ad
|
|
- (void)addADWithInterstitialId:(NSString*)adId actionBlock:(LuxADManagerActionBlock)block{
|
|
LuxADManagerInterstitialItem *item = [LuxADManagerInterstitialItem initWithAdId:adId adDelegate:self actionBlock:block];
|
|
item.delegate = self;
|
|
[_adItemsArr addObject:item];
|
|
}
|
|
|
|
//初始化开屏广告,注意,我们默认把广告数组中的第一个添加的插页ad当作开屏广告
|
|
- (void)initOpenAD{
|
|
[[self openAd].adItem loadAd];
|
|
}
|
|
|
|
- (LuxADManagerInterstitialItem *)openAd {
|
|
return _adItemsArr.firstObject;
|
|
}
|
|
|
|
//初始化余下的插屏广告
|
|
- (void)initOtherInitIntersitialAD {
|
|
for (int i = 1; i < _adItemsArr.count; i ++) {
|
|
LuxADManagerInterstitialItem *item = _adItemsArr[i];
|
|
[item.adItem loadAd];
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:kLuxADSSModeVC_Notification_AdInfo object:nil userInfo:@{@"info":[NSString stringWithFormat:@"加载第%d个广告(%@)",i,item.adItem.adUnitIdentifier]}];
|
|
}
|
|
}
|
|
|
|
//返回所有的插屏ad(非开屏广告openad)
|
|
- (NSArray <LuxADManagerInterstitialItem *> *)allInterstitialAds {
|
|
if (_adItemsArr.count) {//第一个默认为开屏广告
|
|
return [_adItemsArr subarrayWithRange:NSMakeRange(1, _adItemsArr.count - 1)];
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
#pragma mark -----主要是 配置开屏广告 的地方
|
|
//用于在启动app时,即第一次在appDidFinishLanuch调用开屏广告
|
|
- (void)showFirstOpenAD:(LuxADManagerCallback)callback window:(UIWindow *)window bgImgName:(NSString *)bgImgName bgColor:(UIColor *)bgColor{
|
|
if ([self isADSSMode]) {//补量模式,直接返回,不加载开屏
|
|
return;
|
|
}
|
|
|
|
self.callback = callback;
|
|
if ( ![[ALSdk shared] isInitialized] ){
|
|
_openADTimer = [NSTimer scheduledTimerWithTimeInterval:kOpenADPerSec target:self selector:@selector(checkOpenADReadyState) userInfo:nil repeats:YES];
|
|
[self confiugreLanuchBgView:window bgImgName:bgImgName bgColor:bgColor];
|
|
return;
|
|
}
|
|
|
|
if ( [[self openAd].adItem isReady] ){
|
|
|
|
[[self openAd].adItem showAd];
|
|
}
|
|
else{
|
|
_openADTimer = [NSTimer scheduledTimerWithTimeInterval:kOpenADPerSec target:self selector:@selector(checkOpenADReadyState) userInfo:nil repeats:YES];
|
|
[self confiugreLanuchBgView:window bgImgName:bgImgName bgColor:bgColor];
|
|
[[self openAd].adItem loadAd];
|
|
}
|
|
}
|
|
|
|
//用于在app进行前后台切换时调用
|
|
- (void)showOpenAD {
|
|
if ([self isADSSMode]) {//补量模式,直接返回,不加载开屏
|
|
return;
|
|
}
|
|
|
|
if(![self canShowAD:[self openAd].lastShowADDate ]) {
|
|
return;
|
|
}
|
|
|
|
if ( ![[ALSdk shared] isInitialized] ){
|
|
return;
|
|
}
|
|
|
|
if ( [[self openAd].adItem isReady] ){
|
|
[[self openAd].adItem showAd];
|
|
}
|
|
else{
|
|
[[self openAd].adItem loadAd];
|
|
}
|
|
}
|
|
|
|
//检查openad的状态,如果可用则展示,并停止timer倒计时. 如果不可用且超时,则停止timer并回调;如果不可用并未超时,则更新进度条
|
|
- (void)checkOpenADReadyState{
|
|
static CGFloat totalTimeC = 0.0;
|
|
totalTimeC += kOpenADPerSec;
|
|
|
|
if ( [[self openAd].adItem isReady] ){
|
|
[_openADTimer invalidate];
|
|
_openADTimer = nil;
|
|
[[self openAd].adItem showAd];
|
|
}
|
|
else {
|
|
if (totalTimeC > kOpenAdCTimeLength) {//超时
|
|
if(self.callback) {
|
|
self.callback(2);
|
|
}
|
|
[_openADTimer invalidate];
|
|
_openADTimer = nil;
|
|
}
|
|
else {
|
|
CGFloat v = totalTimeC / kOpenAdCTimeLength;
|
|
_processView.progress = v;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//开屏广告,更新进度条的视图
|
|
- ( void)confiugreLanuchBgView:(UIWindow *)window bgImgName:(NSString *)bgImgName bgColor:(UIColor *)bgColor{
|
|
UIViewController *vc = [UIViewController new];
|
|
window.rootViewController = vc;
|
|
|
|
UIImageView *imgView = [UIImageView new];
|
|
imgView.frame = CGRectMake((window.frame.size.width - 80) * 0.5, (window.frame.size.height - 80) * 0.5,80,80);
|
|
imgView.layer.masksToBounds = YES;
|
|
imgView.layer.cornerRadius = 40;
|
|
[window addSubview:imgView];
|
|
imgView.image = [UIImage imageNamed:bgImgName];
|
|
imgView.contentMode = UIViewContentModeScaleAspectFit;
|
|
if (bgColor) {
|
|
imgView.backgroundColor = bgColor;
|
|
}
|
|
else {
|
|
imgView.backgroundColor = [UIColor colorWithRed:197.0/255.0 green:197.0/255.0 blue:197.0/255.0 alpha:1];
|
|
}
|
|
|
|
_processView = [UIProgressView new];
|
|
_processView.frame = CGRectMake(80-1,window.frame.size.height - 60-1,window.frame.size.width - 160-1,20-1);
|
|
_processView.tintColor = [UIColor systemPinkColor];
|
|
[vc.view addSubview:_processView];
|
|
|
|
[vc.view addSubview:imgView];
|
|
vc.view.backgroundColor = imgView.backgroundColor;
|
|
}
|
|
|
|
#pragma mark -----展示其他插页广告
|
|
//根据指定的在_adItemsArr中的index展示ad
|
|
- (void)showADWithIndex:(NSInteger)index callback:(LuxADManagerCallback)callback {
|
|
self.callback = callback;
|
|
if (index < _adItemsArr.count) {
|
|
LuxADManagerInterstitialItem *item = [_adItemsArr objectAtIndex:index];
|
|
if (![self canShowAD:item.lastShowADDate] || ![item.adItem isReady]) { //如果未满足30秒的展示时间或没有准备好展示,则返回
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:kLuxADSSModeVC_Notification_AdInfo object:nil userInfo:@{@"info":[NSString stringWithFormat:@"第%d个广告还未准为好(%@)",index,item.adItem.adUnitIdentifier]}];
|
|
[LuxNetManager showAd:nil adId:item.adItem.adUnitIdentifier ecpm:@(0) ad:NO callback:nil];
|
|
self.callback(2);
|
|
|
|
}
|
|
else { //展示
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:kLuxADSSModeVC_Notification_AdInfo object:nil userInfo:@{@"info":[NSString stringWithFormat:@"展示第%d个广告(%@)",index,item.adItem.adUnitIdentifier]}];
|
|
[item.adItem showAd];
|
|
[LuxNetManager showAd:nil adId:item.adItem.adUnitIdentifier ecpm:item.ecpm ad:YES callback:nil];
|
|
}
|
|
|
|
}
|
|
else {
|
|
NSLog(@"超出所初始化的广告数量边界....");
|
|
}
|
|
}
|
|
|
|
//随机展示_adItemsArr中的插屏ad
|
|
- (void)showADByRandomModeWithCallback:(LuxADManagerCallback)callback {
|
|
if (_adItemsArr.count && ![self isADSSMode]) {
|
|
int rv = arc4random() % _adItemsArr.count;
|
|
LuxADManagerInterstitialItem *item = _adItemsArr[rv];
|
|
|
|
if (![self canShowAD:item.lastShowADDate] || ![item.adItem isReady]) { //如果未满足30秒的展示时间或没有准备好展示,则返回
|
|
self.callback(2);
|
|
}
|
|
else { //展示
|
|
[item.adItem showAd];
|
|
}
|
|
}
|
|
else {
|
|
callback(2);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark ----所有广告的通用处理
|
|
//能否展示广告
|
|
- (BOOL)canShowAD:(NSDate *)adDate {
|
|
if ([self isADSSMode]) {//处于这个模式时,则忽略30秒的间隔
|
|
return YES;
|
|
}
|
|
if(!adDate) {
|
|
return YES;
|
|
}
|
|
else {
|
|
NSDate *ndate = [NSDate date];
|
|
if ([ndate timeIntervalSinceDate:adDate] >= kADShowTimePer) {
|
|
return YES;
|
|
}
|
|
else {
|
|
return NO;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//在收到ad 代理回调时,如果需要重新loadAD则调用此方法
|
|
- (void)loadAD:(MAAd *)ad{
|
|
LuxADManagerInterstitialItem *item = [self getLuxADInterstitialItemWith:ad.adUnitIdentifier];
|
|
if (item) {
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:kLuxADSSModeVC_Notification_AdInfo object:nil userInfo:@{@"info":[NSString stringWithFormat:@"正在加载 AdID:%@",item.adItem.adUnitIdentifier]}];
|
|
[item.adItem loadAd];
|
|
NSLog(@"已经重新加载loadAD:%@",ad.adUnitIdentifier);
|
|
}
|
|
}
|
|
|
|
//根据指定maad返回LuxADManagerInterstitialItem对象
|
|
- (LuxADManagerInterstitialItem *)getLuxADInterstitialItemWith:(NSString *)adUnitIdentifier {
|
|
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self.adItem.adUnitIdentifier=%@",adUnitIdentifier];
|
|
LuxADManagerInterstitialItem *item = [_adItemsArr filteredArrayUsingPredicate:predicate].firstObject;
|
|
return item;
|
|
}
|
|
|
|
//重置所有ad中的重试次数
|
|
- (void)resetRetryAttemptCount:(MAAd *)ad {
|
|
LuxADManagerInterstitialItem *item = [self getLuxADInterstitialItemWith:ad.adUnitIdentifier];
|
|
item.retryAttemptCount = 0;
|
|
}
|
|
|
|
|
|
- (void)storeADInfoAnUploadWith:(MAAd *)ad {
|
|
[[NSUserDefaults standardUserDefaults] setObject:ALSdk.shared.configuration.countryCode forKey:@"countryCode"];
|
|
NSTimeInterval interval = ad.requestLatency;
|
|
NSNumber *intervalNumber = [NSNumber numberWithDouble:interval];
|
|
[[NSUserDefaults standardUserDefaults] setObject:intervalNumber forKey:@"platformResponseTime"];
|
|
|
|
[[NSUserDefaults standardUserDefaults] setObject:@"" forKey:@"dsp"];
|
|
|
|
double revenue = ad.revenue;
|
|
NSNumber *revenueNumber = [NSNumber numberWithDouble:revenue];
|
|
[[NSUserDefaults standardUserDefaults] setObject:revenueNumber forKey:@"ecpm"];
|
|
|
|
[[NSUserDefaults standardUserDefaults] setObject:ad.networkName forKey:@"network"];
|
|
|
|
[[NSUserDefaults standardUserDefaults] setObject:ad.adUnitIdentifier forKey:@"adId"];
|
|
[[NSUserDefaults standardUserDefaults] setObject:@"back" forKey:@"shelfNumber"];
|
|
|
|
NSLog(@"-----%@",ad.adUnitIdentifier);
|
|
NSLog(@"self.openAD.adUnitIdentifier-----%@",[self openAd].adItem.adUnitIdentifier);
|
|
|
|
|
|
}
|
|
|
|
|
|
//判断当前是否为广告不量模式
|
|
- (BOOL)isADSSMode{
|
|
// return YES;
|
|
return [[NSUserDefaults standardUserDefaults] boolForKey:@"kLuxSSFaceKey"];
|
|
}
|
|
|
|
|
|
#pragma mark - MAAdDelegate 广告的代理
|
|
|
|
- (void)didLoadAd:(MAAd *)ad {
|
|
NSLog(@"ad didLoadAD.....");
|
|
[self resetRetryAttemptCount:ad];
|
|
[self storeADInfoAnUploadWith:ad];
|
|
[LuxNetManager uploadAD_Load:ad];
|
|
|
|
LuxADManagerInterstitialItem *item = [self getLuxADInterstitialItemWith:ad.adUnitIdentifier];
|
|
[item setEcpm:@(ad.revenue)];
|
|
}
|
|
|
|
- (void)didFailToLoadAdForAdUnitIdentifier:(NSString *)adUnitIdentifier withError:(MAError *)error {
|
|
NSLog(@"加载广告失败.... :%@ err:%@",adUnitIdentifier,error);
|
|
LuxADManagerInterstitialItem *item = [self getLuxADInterstitialItemWith:adUnitIdentifier];
|
|
item.retryAttemptCount++;
|
|
NSInteger delaySec = pow(2, MIN(6, item.retryAttemptCount));
|
|
|
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delaySec * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
|
|
[item.adItem loadAd];
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:kLuxADSSModeVC_Notification_AdInfo object:nil userInfo:@{@"info":[NSString stringWithFormat:@"fail loadAd 正在重新加载 AdID:%@",item.adItem.adUnitIdentifier]}];
|
|
});
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)didDisplayAd:(MAAd *)ad {
|
|
NSLog(@"成功展示了ad....");
|
|
[self storeADInfoAnUploadWith:ad];
|
|
|
|
LuxADManagerInterstitialItem *item = [self getLuxADInterstitialItemWith:ad.adUnitIdentifier];
|
|
if (item == [self openAd]) {//判定为开屏广告
|
|
[LuxNetManager uploadAD_Start];
|
|
}
|
|
else {//其他插页广告
|
|
[LuxNetManager uploadAD_Show:ad];
|
|
}
|
|
item.lastShowADDate = [NSDate date];
|
|
//此处目前没有处理back类型的广告的时间被忽略计时的情况
|
|
//.....
|
|
}
|
|
|
|
- (void)didClickAd:(MAAd *)ad {
|
|
|
|
NSLog(@"点击了广告.....");
|
|
}
|
|
|
|
- (void)didHideAd:(MAAd *)ad{
|
|
NSLog(@"隐藏了ad....");
|
|
if (self.callback) {
|
|
self.callback(1);
|
|
}
|
|
|
|
|
|
if (![self isADSSMode]) {//补量模式时,隐藏ad之后,不再主动loadAD,等通知是否隐藏
|
|
[self loadAD:ad];
|
|
}
|
|
else {
|
|
[LuxNetManager closeAd:nil adId:ad.adUnitIdentifier callback:nil];
|
|
}
|
|
}
|
|
|
|
- (void)didFailToDisplayAd:(MAAd *)ad withError:(MAError *)error{
|
|
NSLog(@"展示广告失败....");
|
|
[self loadAD:ad];
|
|
}
|
|
|
|
|
|
#pragma mark ---- LuxADManagerInterstitialItemDelegate
|
|
- (void)needLoadADWithNum:(NSInteger)num {
|
|
NSInteger i = num;
|
|
NSInteger index = 1;
|
|
while (i && index < _adItemsArr.count) {
|
|
LuxADManagerInterstitialItem *item = _adItemsArr[index];
|
|
item.ecpm = nil;
|
|
[item.adItem loadAd];
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:kLuxADSSModeVC_Notification_AdInfo object:nil userInfo:@{@"info":[NSString stringWithFormat:@"正在加载 AdID:%@",item.adItem.adUnitIdentifier]}];
|
|
index++;
|
|
i--;
|
|
}
|
|
}
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|