Translate_offine/HDwallpaper/LuxADManager/LuxADManager.m
2024-07-29 15:40:08 +08:00

491 lines
16 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{
//直接在此处把远程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];
// }
}];
__weak typeof(self)weakSelf = self;
[[ALSdk shared] initializeWithConfiguration: _adConfig completionHandler:^(ALSdkConfiguration *sdkConfig) {
if ([weakSelf isADSSMode]) {//如果为补量模式,直接加载剩下的插页广告
[[LuxADManager shareInstance] initOtherInitIntersitialAD];
[[LuxADManager shareInstance]showSSModeControlVC];
}
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 ++) {
[_adItemsArr[i].adItem loadAd];
}
}
//返回所有的插屏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秒的展示时间或没有准备好展示,则返回
[LuxNetManager showAd:nil adId:item.adItem.adUnitIdentifier ecpm:@(0) ad:NO callback:nil];
self.callback(2);
}
else { //展示
[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) {
[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];
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];
});
}
- (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];
}
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];
index++;
i--;
}
}
@end