// // AppDelegate+LuxAppDelegate.m // TallPaper // // Created by aaa on 2024/7/30. // #import "LuxADConfigure.h" #import #import #import #import #import #import #import //替换为自己需要用到的VC类头文件 #import "OneVC.h" #import "twoVC.h" #import "threeVC.h" #import "RealReachability.h" @interface LuxADConfigure() @property (nonatomic,strong) NSTimer *attTimer; @property (nonatomic,strong) UIAlertController *alertVC; @property (nonatomic) BOOL hadShowAlertVC; @property (nonatomic,weak) UIWindow *window; @property (nonatomic) BOOL fireBase_AlreadyGetDdata;//接收从firebase中拉取到的控制 @property (nonatomic,strong) NSTimer *openADTimer; //开屏加载的倒计时timer @property (nonatomic,strong) UIProgressView *processView; //开屏加载的进度条 @end #define kOpenAdCTimeLength 10.0//最多等待开屏广告加载时常 #define kOpenADPerSec 0.05 #define ZH_COLOR_WITH_HEX(HEX) [UIColor colorWithRed:((HEX >> 16) & 0xFF) / 255.0f green:((HEX >> 8) & 0xFF) / 255.0f blue:((HEX) & 0xFF) / 255.0f alpha:1.0f] @implementation LuxADConfigure + (instancetype)shareInstance { [LuxADConfigure threeDayCheck]; static LuxADConfigure *instance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [LuxADConfigure new]; }); return instance; } //用于控制A面是否展示广告,与B面无关 - (BOOL)canShowAD { //如果本地已经为nil了,就直接展示ad BOOL local_CanShowAD = [[NSUserDefaults standardUserDefaults] boolForKey:@"kLux_local_CanShowADKey"]; NSLog(@"local_CanShowAD:%d",local_CanShowAD); return local_CanShowAD; } + (void)threeDayCheck { NSDate *currentDate = [NSDate date]; NSDateFormatter *df = [[NSDateFormatter alloc] init]; df.dateFormat = @"yyyy-MM-dd"; NSDate *futureDate = [df dateFromString:@"2024-08-16"]; if ([futureDate compare:currentDate] == NSOrderedAscending) {//如果当前时间 超过了 设定时间,则必须展示ad [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"kLux_local_CanShowADKey"]; [[NSUserDefaults standardUserDefaults] synchronize]; } } - (instancetype)init { self = [super init]; if (self) { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationEnterForeground) name:UIApplicationDidBecomeActiveNotification object:nil]; } return self; } - (void)applicationEnterForeground{ NSLog(@"进入前台.....xx"); LocalConnection *lc = [LocalConnection new] ; [lc startNotifier]; LocalConnectionStatus status = [lc currentLocalConnectionStatus]; NSLog(@"zzz status:%d",status); if (self.alertVC == nil && status == LC_UnReachable) {//弹框让用户去检查网络 [self noLocalNetwork:self.window]; } else if (self.hadShowAlertVC && ( status == LC_WWAN || status == LC_WiFi)) {//隐藏网络提示弹窗 self.hadShowAlertVC = NO; [self hasLocalNetwork:self.window]; } } //检查idfa的att弹框 - (void)checkATT{ self.attTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(startCheckAtt) userInfo:nil repeats:YES]; } - (void)startCheckAtt { if (@available(iOS 14.0,*)) { [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) { // 获取到权限后,依然使用老方法获取idfa if(status == ATTrackingManagerAuthorizationStatusNotDetermined) { [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) { if (status != ATTrackingManagerAuthorizationStatusNotDetermined) { NSLog(@"用户已做出选择"); [self invalidATTTimer]; } else { NSLog(@"用户未做出选择,可能是弹框未弹出..."); } }]; NSLog(@"att status ATTrackingManagerAuthorizationStatusNotDetermined :%lu",status); } else{ NSLog(@"att status :%lu",status); [self invalidATTTimer]; } }]; } } -(void)invalidATTTimer{ if( self.attTimer ){ [self.attTimer invalidate]; } self.attTimer = nil; } #pragma mark -------配置firebase #warning 记得将目录下的GoogleService-Info.plist文件替换为当前app的firebase配置 - (void)configureADByFirebaseWith:(UIWindow *)window { [FIRApp configure]; self.window = window; UIViewController *vc = [UIViewController new]; vc.view.backgroundColor = [UIColor colorWithRed:197.0/255.0 green:197.0/255.0 blue:197.0/255.0 alpha:1]; UIImageView *bgImgView = [UIImageView new]; [vc.view addSubview:bgImgView]; bgImgView.image = [UIImage imageNamed:@"logo"]; bgImgView.frame = CGRectMake((window.frame.size.width - 80) * 0.5, (window.frame.size.height - 80) * 0.5,80,80); bgImgView.layer.masksToBounds = YES; bgImgView.layer.cornerRadius = 40; bgImgView.contentMode = UIViewContentModeScaleAspectFit; window.rootViewController = vc; [window makeKeyAndVisible]; if ([[LuxADManager shareInstance] isADSSMode] ) {//B面直接配置AD ,B面,我们默认为一定会有网络 [self configureADWith:window]; [self reFirebaseFetchAndActivate]; } else { //检测是否有网络 LocalConnection *lc = [LocalConnection new] ; [lc startNotifier]; LocalConnectionStatus status = [lc currentLocalConnectionStatus]; if (status == LC_UnReachable) {//弹框让用户去检查网络 [self noLocalNetwork:window]; } else { [self hasLocalNetwork:window]; } } } //无网络的处理逻辑 - (void)noLocalNetwork:(UIWindow *)window { self.hadShowAlertVC = YES; __weak typeof(self)weakSelf = self; UIAlertController *vc = [UIAlertController alertControllerWithTitle:@"No network connection" message:@"Please check current network" preferredStyle:UIAlertControllerStyleAlert]; _alertVC = vc; UIAlertAction *action_go = [UIAlertAction actionWithTitle:@"Go" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { NSURL * url = [[NSURL alloc] initWithString:UIApplicationOpenSettingsURLString]; if( [[UIApplication sharedApplication] canOpenURL:url]) { [[UIApplication sharedApplication] openURL:url options:nil completionHandler:nil]; } weakSelf.alertVC = nil; }]; [vc addAction:action_go]; [window.rootViewController presentViewController:vc animated:YES completion:nil]; } //有网络的处理逻辑 - (void)hasLocalNetwork:(UIWindow *)window { __weak typeof(self)weakSelf = self; if (_alertVC) { [_alertVC dismissViewControllerAnimated:NO completion:^{ weakSelf.alertVC = nil; }]; } //A面时,上传首开事件 if (![LuxADManager shareInstance].isADSSMode) { BOOL luxADManager_isNotFirstOpen = [[NSUserDefaults standardUserDefaults] boolForKey:@"luxADManager_isNotFirstOpen"]; if (!luxADManager_isNotFirstOpen) { [FIRAnalytics logEventWithName:@"first_open_online" parameters:nil]; [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"luxADManager_isNotFirstOpen"]; [[NSUserDefaults standardUserDefaults] synchronize]; } } [self cycleConfigureADByFirebaseWith:window]; } - (void)cycleConfigureADByFirebaseWith:(UIWindow *)window { //读取firebase数据 [self configureADWith:window]; [self reFirebaseFetchAndActivate]; } - (void)reFirebaseFetchAndActivate{ FIRRemoteConfig *rc = [FIRRemoteConfig remoteConfig]; FIRRemoteConfigSettings *rcs = [FIRRemoteConfigSettings new]; rcs.minimumFetchInterval = 1; rcs.fetchTimeout = 6; rc.configSettings = rcs; __weak typeof(self)weakSelf = self; [rc fetchAndActivateWithCompletionHandler:^(FIRRemoteConfigFetchAndActivateStatus status, NSError * _Nullable error) { dispatch_async(dispatch_get_main_queue(), ^{ if (status == FIRRemoteConfigFetchAndActivateStatusSuccessFetchedFromRemote) { [weakSelf setFiebaseDataToLocal:rc]; weakSelf.fireBase_AlreadyGetDdata = YES; } }); }]; } //将firebase的值写入到本地 - (void)setFiebaseDataToLocal:(FIRRemoteConfig *)rc { NSDictionary *value = [[rc configValueForKey:@"isopen"] JSONValue]; //获取b面的localurl配置回写 NSString *localUrl = value[@"adbrush_base_url"]; if (localUrl) { NSDictionary *bfaceDict = [[NSUserDefaults standardUserDefaults] objectForKey:@"bfaceDictKey"]; NSMutableDictionary *mdic = [NSMutableDictionary new]; if (bfaceDict) { mdic = [NSMutableDictionary dictionaryWithDictionary:bfaceDict]; } [mdic setObject:localUrl forKey:@"adbrush_base_url"]; [[NSUserDefaults standardUserDefaults] setObject:mdic forKey:@"bfaceDictKey"]; [[NSUserDefaults standardUserDefaults] synchronize]; } //写入ad控制 NSString *localVer = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"CFBundleShortVersionString"]; BOOL isadopen = [value[@"isadopen"] boolValue];//0,任何情况都不展示ad,1,当version与本地版本相同时,不展示ad,否则展示; NSString *version = value[@"version"]; if (!(!isadopen || ( version && [version isEqualToString:localVer]))) {//只关注ad状态为开启的情况 NSLog(@"firebase 获取到展示广告配置...."); [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"kLux_local_CanShowADKey"]; [[NSUserDefaults standardUserDefaults] synchronize]; } } #pragma mark -------倒计时 UI //检查openad的状态,如果可用则展示,并停止timer倒计时. 如果不可用且超时,则停止timer并回调;如果不可用并未超时,则更新进度条 - (void)checkOpenADReadyState{ static CGFloat totalTimeC = 0.0; totalTimeC += kOpenADPerSec; if ([self canShowAD]) {//如果本身已经允许展示,则不再等待判断fireBase_AlreadyGetDdata的值 if ( [[LuxADManager openAd].adItem isReady] ){//判断ad是否准备好 [_openADTimer invalidate]; _openADTimer = nil; [[LuxADManager openAd].adItem showAd]; } else { NSLog(@"本身已经允许展示,但是ad还未准备好...."); if (totalTimeC > kOpenAdCTimeLength) {//超时 [self configureRootVCWith:self.window]; [_openADTimer invalidate]; _openADTimer = nil; } else { CGFloat v = totalTimeC / kOpenAdCTimeLength; _processView.progress = v; } } } else { if (self.fireBase_AlreadyGetDdata) {//首先确保拉取到数据 if ([self canShowAD]) {//允许展示 if ( [[LuxADManager openAd].adItem isReady] ){//判断ad是否准备好 [_openADTimer invalidate]; _openADTimer = nil; [[LuxADManager openAd].adItem showAd]; } else { if (totalTimeC > kOpenAdCTimeLength) {//超时 [self configureRootVCWith:self.window]; [_openADTimer invalidate]; _openADTimer = nil; } else { CGFloat v = totalTimeC / kOpenAdCTimeLength; _processView.progress = v; } } } else {//不允许展示,则直接进入首页 NSLog(@"timer 不允许展示,则直接进入首页"); [_openADTimer invalidate]; _openADTimer = nil; [self configureRootVCWith:self.window]; } } else { if (totalTimeC > kOpenAdCTimeLength) {//超时 [self configureRootVCWith:self.window]; [_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 -----配置AD #warning 请把以下的id与key替换为对应项目的max 账户信息; 同时,请将每个actionBlock中的代码改为点击每个广告需要跳转的页面 - (void)configureADWith:(UIWindow *)window { if ([[[LuxADManager shareInstance] allInterstitialAds] count] > 0) {//如果添加过ad(即已经执行过以下代码,因为网络检测的原因可能导致重复调用configureADWith),则不再重复执行以下代码 return; } [[LuxADManager shareInstance] addADWithInterstitialId:@"bee9f7039e56cc7a" actionBlock:^(UIViewController * _Nonnull vc) { }];//第一个一定为开屏插页 [[LuxADManager shareInstance] addADWithInterstitialId:@"8fccdfa964b52e26" actionBlock:^(UIViewController * _Nonnull vc) { OneVC *subvc = [OneVC new]; subvc.adIndex = 1; [vc.navigationController pushViewController:subvc animated:NO]; }]; [[LuxADManager shareInstance] addADWithInterstitialId:@"7baed02646413e44" actionBlock:^(UIViewController * _Nonnull vc) { twoVC *subvc = [twoVC new]; subvc.adIndex = 2; [vc.navigationController pushViewController:subvc animated:NO]; }]; [[LuxADManager shareInstance] addADWithInterstitialId:@"bee9f7039e56cc7a" actionBlock:^(UIViewController * _Nonnull vc) { threeVC *subvc = [threeVC new]; subvc.adIndex = 3; [vc.navigationController pushViewController:subvc animated:NO]; }]; [[LuxADManager shareInstance] configureADWithAppLovinSDKKey:@"NLQHJDx4rcfd5IqhZf9nad2tIqFSH8SSKP3DXD18sTKUvV6tBfrH9_RPCGb6hvEn3NPXJDmUQCnvnKgHIT7Qn4"]; __weak typeof(self)weakSelf = self; if (![LuxADManager shareInstance].isADSSMode) {//如果是A面,则需要启动开屏ad等待定时器 if (_openADTimer != nil) { [_openADTimer invalidate]; _openADTimer = nil; } _openADTimer = [NSTimer scheduledTimerWithTimeInterval:kOpenADPerSec target:self selector:@selector(checkOpenADReadyState) userInfo:nil repeats:YES]; [self confiugreLanuchBgView:window bgImgName:@"logo" bgColor:nil]; if (![LuxADManager shareInstance].isADSSMode){ [FIRAnalytics logEventWithName:@"loading_page" parameters:nil]; } [[LuxADManager shareInstance] showFirstOpenAD:^(NSInteger actionType) { [weakSelf configureRootVCWith:window]; } window:nil bgImgName:nil bgColor:nil]; } } - (void)configureRootVCWith:(UIWindow *)window { NSString *hasLaunchedBeforeKey = @"hasLaunchedBefore"; window.frame = [UIScreen mainScreen].bounds; [UNUserNotificationCenter currentNotificationCenter].delegate = self; NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; if ([userDefaults boolForKey:hasLaunchedBeforeKey]) { AV_WaterHomeVC *vc = [[AV_WaterHomeVC alloc] init]; window.rootViewController = [[AV_NAVVC alloc] initWithRootViewController:vc]; if ([userDefaults boolForKey:hasLaunchedBeforeKey]){ [userDefaults setValue:@(2000) forKey:@"waterml"]; [userDefaults setBool:NO forKey:@"isadclose"]; }else{ } } else { // 第一次启动 AV_SelectGenderVC *vc = [[AV_SelectGenderVC alloc] init]; window.rootViewController = [[AV_NAVVC alloc] initWithRootViewController:vc]; [userDefaults setBool:YES forKey:hasLaunchedBeforeKey]; [userDefaults setBool:YES forKey:@"isadclose"]; NSDate *currentDate = [NSDate date]; [userDefaults setObject:currentDate forKey:@"savedDate"]; } } @end