// // AppDelegate.m // AntsContract // // Created by Ray on 12/16/16. // Copyright © 2016 United Software Applications, Inc. All rights reserved. // #import "AppDelegate.h" #import "ACNetwork.h" #import "TextUtils.h" #import "PDFUtils.h" #import "RAUtils.h" #import "AddExtDocumentViewController.h" #import "LoginViewController.h" #import "RootViewController.h" //#import "AFHTTPSessionManager.h" @interface AppDelegate () @property (nonatomic,strong) NSTimer *heartBeat; @end @implementation AppDelegate -(void) prepareLocalResource { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); NSString *cachefolder = [paths objectAtIndex:0]; NSString *folder = [cachefolder stringByAppendingPathComponent:@"local_resource"]; NSFileManager* fileManager = [NSFileManager defaultManager]; BOOL bdir=YES; if(! [fileManager fileExistsAtPath:folder isDirectory:&bdir]) { NSError *error = nil; bool bsuccess=[fileManager createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:nil error:&error]; if(!bsuccess) { DebugLog(@"Create local resource folder failed"); return ; } // if(![fileManager copyItemAtPath:from toPath:folder error:&error]) // { // return ; // } } UIImage* img=[UIImage imageNamed:@"na"]; NSString* file = [folder stringByAppendingPathComponent:@"NA.png"]; bool bwrite=[UIImagePNGRepresentation(img) writeToFile:file atomically:YES]; if(bwrite) self.na_path = file; else self.na_path = nil; } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. [self prepareLocalResource]; self.accessMode = AppAccessModeOnline; self.bEnable_Cache = true; [self function_test]; return YES; } -(NSString*) filetype:(NSString*)filePath { NSString *suffix = [filePath pathExtension]; if([suffix.lowercaseString isEqualToString:@"jpg"]||[suffix.lowercaseString isEqualToString:@"png"]||[suffix.lowercaseString isEqualToString:@"bmp"]||[suffix.lowercaseString isEqualToString:@"gif"]) return @"image"; else return @"file"; } - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(nonnull NSDictionary *)options { NSLog(@"URL:%@, OPTIONS:%@",[url absoluteString],[RAUtils dict2string:options]); if (self.accessMode == AppAccessModeOffline) { [RAUtils message_alert:@"Cann't upload file on offline mode" title:@"Warning" controller:self.window.rootViewController]; return NO; } NSMutableDictionary* item = [[NSMutableDictionary alloc] init]; item[@"type"]=[self filetype:url.absoluteString]; item[@"url"]= [url path]; item[@"file_name"] = [[url.absoluteString lastPathComponent] stringByRemovingPercentEncoding]; if(self.bLogin) { [self checkSelfWindowIsKeyWindow]; UINavigationController *rootVC = (UINavigationController *)application.keyWindow.rootViewController; UIViewController* presentVC=rootVC.presentedViewController; AddExtDocumentViewController * addVC; if([presentVC isKindOfClass:[UINavigationController class]]) { //如果当前已有模态对话框,则关闭当前的模态框,否则无法弹出上传框。 UIViewController* topvc= ((UINavigationController*)presentVC).topViewController; if([topvc isKindOfClass:[AddExtDocumentViewController class]]) { addVC = (AddExtDocumentViewController*)topvc; if(addVC.arr_documents==nil) addVC.arr_documents = [NSMutableArray arrayWithObjects:item, nil]; else [addVC.arr_documents addObject:item]; [addVC refresh_table]; } else [presentVC dismissViewControllerAnimated:false completion:nil]; } else { addVC = [ [UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"AddExtDocumentViewController"]; addVC.is_present = true; addVC.doc_number = nil; addVC.arr_documents = [NSMutableArray arrayWithObjects:item, nil]; UINavigationController* navi = [[UINavigationController alloc] initWithRootViewController:addVC] ; navi.modalPresentationStyle = UIModalPresentationFormSheet;//有三种状态,自己看看是哪种 [rootVC presentViewController:navi animated:YES completion:^{ // navi.view.superview.bounds = CGRectMake(0, 0, 480, 320); DebugLog(@"filter present........."); // self.btop = false; // <#code#> }]; } } else { self.shareFile = item; [self checkSelfWindowIsKeyWindow]; UINavigationController *rootVC = (UINavigationController *)application.keyWindow.rootViewController; RootViewController* topvc= (RootViewController*)rootVC.topViewController; UIViewController* presentVC=rootVC.presentedViewController; // AddExtDocumentViewController * addVC; if(!presentVC)//([presentVC isKindOfClass:[UINavigationController class]]) { //未弹出login 框 [topvc presentLogin:topvc.ibSignin]; } } // [ pushViewController:addVC animated:false]; // return YES; return YES; } -(void)function_test { return; printf("function test======================"); // NSString* pdffile = [PDFUtils SavePDF:nil source:nil window_rect:CGRectMake(0, 0, 768, 960)]; // [PDFUtils leak_test]; // 获取路径 NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);//坐标 NSString *saveDirectory=[paths objectAtIndex:0]; NSString *saveFileName=[NSString stringWithFormat:@"%@.pdf",[[NSUUID UUID ] UUIDString] ] ;; NSString *newFilePath=[saveDirectory stringByAppendingPathComponent:saveFileName]; const char *filename=[newFilePath UTF8String]; NSLog(@"%@",newFilePath); //设置页面大小 Letter纸 CFStringRef path; CFURLRef url; path=CFStringCreateWithCString(NULL, filename, kCFStringEncodingUTF8); url=CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, 0); CFRelease(path); // CGPDFCONTEXTCREATE CGContextRef pdfContext; CGRect docsize = CGRectMake(0, 0, 612, 1008); CFMutableDictionaryRef myDictionary = NULL; myDictionary= CFDictionaryCreateMutable(NULL, 0, NULL, NULL); CFDictionarySetValue(myDictionary, kCGPDFContextOwnerPassword, CFSTR("usai2010")); CFDictionarySetValue(myDictionary, kCGPDFContextAllowsPrinting, kCFBooleanTrue); CFDictionarySetValue(myDictionary, kCGPDFContextAllowsCopying, kCFBooleanFalse); pdfContext=CGPDFContextCreateWithURL(url, &docsize,myDictionary); CFRelease(myDictionary); CFRelease(url); CGContextBeginPage(pdfContext, &docsize); // cgpdfpage CGContextEndPage(pdfContext); CGPDFContextClose(pdfContext); CGContextRelease(pdfContext); return ; } - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. [self stopHeartBeat]; } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. if (self.bLogin && !self.heartBeat) { [self startHeartBeat]; } } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } -(void) Login:(NSString* )user pwd:(NSString*) pwd canModify:(bool) canModify offPrefix:(NSString*) offPrefix agentName:(NSString*) name { // self.bCanModify = canModify; // self.offPrefix = offPrefix; self.user = user; self.password = pwd; self.bLogin = true; self.accessMode = AppAccessModeOnline; self.agentName = name; // 延迟1s启动心跳,以避免在登录框还在Dismiss动画过程中再次调用Dismiss __weak typeof(self) weakself = self; dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC); dispatch_after(time, dispatch_get_main_queue(), ^{ [weakself heartBeatRightNow:YES]; }); } -(void) SwitchToOffline:(NSString* )user { self.accessMode = AppAccessModeOffline; // self.bCanModify = false; //self.offPrefix = offPrefix; self.user = user; self.password = user; self.bLogin = true; } -(void) Logout { // MainViewController * main_vc= (MainViewController*)self.main_vc; // [main_vc logoutOrder]; // // // [main_vc hideMenu]; // [main_vc switchToHome]; self.user = nil; // self.bCanModify = false; // self.offPrefix = nil; self.password=nil; self.bLogin = false; [self stopHeartBeat]; // self.user_icon=nil; // self.user_type = USER_ROLE_UNKNOWN; // self.bLogin = false; // self.contact_id=nil; // self.customerInfo = nil; // self.order_code = nil; // // [self.recent_model removeAllObjects]; // // [self SetMode:nil]; } #pragma mark - HeartBeat - (void)markHeartBeatTime { NSDate *date = [NSDate date]; NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; [userDefaults setValue:date forKey:@"heartBeatTime"]; [userDefaults synchronize]; } - (BOOL)checkHearBeatTimeOut { NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; // 前一次成功心跳的时间 NSDate *preTime = [userDefaults valueForKey:@"heartBeatTime"]; if (preTime) { NSDate *curTime = [NSDate date]; NSTimeInterval timeInterval = [curTime timeIntervalSinceDate:preTime]; NSTimeInterval timeOutInterval = 1 * 60 * 60; #ifdef DEBUG timeOutInterval = 1 * 60; #endif if (timeInterval > timeOutInterval) { return YES; } } return NO; } - (void)heartBeatRightNow:(BOOL)rightNow { if (rightNow) { [self heartBeatAction:nil]; } // if(self.heartBeat) { // self.heartBeat.fireDate = [NSDate distantPast]; // return; // } NSTimeInterval heartBeatTimeInterval = 3 * 60; #ifdef DEBUG heartBeatTimeInterval = 30; #endif __weak typeof(self) weakself = self; dispatch_async(dispatch_get_global_queue(0, 0), ^{ if (weakself.heartBeat) { [weakself.heartBeat invalidate]; weakself.heartBeat = nil; } weakself.heartBeat = [NSTimer scheduledTimerWithTimeInterval:heartBeatTimeInterval target:weakself selector:@selector(heartBeatAction:) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:weakself.heartBeat forMode:NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop] run]; }); } - (void)startHeartBeat { [self heartBeatRightNow:YES]; } - (void)stopHeartBeat { if (self.heartBeat) { // self.heartBeat.fireDate = [NSDate distantFuture]; [self.heartBeat invalidate]; self.heartBeat = nil; } } - (void)checkSelfWindowIsKeyWindow { UIApplication *application = [UIApplication sharedApplication]; if (![self.window isEqual:application.keyWindow]) { UIWindow *window = application.keyWindow; [window resignKeyWindow]; if (window.superview) { [window removeFromSuperview]; } window.hidden = YES; window = nil; [self.window makeKeyWindow]; } } - (void)heartBeatTimeout { __weak typeof(self) weakself = self; dispatch_async(dispatch_get_main_queue(), ^{ UIApplication *application = [UIApplication sharedApplication]; // 超时登出,登出中停止心跳 [weakself Logout]; if (![weakself.window isEqual:application.keyWindow]) { UIWindow *window = application.keyWindow; [window resignKeyWindow]; if (window.superview) { [window removeFromSuperview]; } window.hidden = YES; window = nil; [weakself.window makeKeyWindow]; } UINavigationController *rootVC = (UINavigationController *)application.keyWindow.rootViewController; // 提示登录 UIViewController* presentVC=rootVC.presentedViewController; if (presentVC && ![presentVC isKindOfClass:[LoginViewController class]]) { //如果当前已有非Login模态对话框,则关闭当前的模态框 [presentVC dismissViewControllerAnimated:NO completion:^{ // 退回到初始视图 // [rootVC popToRootViewControllerAnimated:NO]; // RootViewController* topvc= (RootViewController*)rootVC.topViewController; // [topvc dealWithUILogout]; // // viewDidAppear会自动Present //// dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 0.25 * NSEC_PER_SEC); //// dispatch_after(time, dispatch_get_main_queue(), ^{ //// [topvc presentLogin:topvc.ibSignin]; //// }); // 递归解决多重Present后,dimiss不完全。 [weakself heartBeatTimeout]; }]; } else { if (rootVC.viewControllers.count > 1) { // 退回到初始视图 [rootVC popToRootViewControllerAnimated:NO]; } RootViewController* topvc= (RootViewController*)rootVC.topViewController; [topvc dealWithUILogout]; dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 0.25 * NSEC_PER_SEC); dispatch_after(time, dispatch_get_main_queue(), ^{ [topvc presentLogin:topvc.ibSignin]; }); } }); } - (void)heartBeatAction:(NSTimer *)timer { // 离线状态下不发心跳包 if (self.accessMode == AppAccessModeOffline) return; __weak typeof(self) weakself = self; dispatch_async(dispatch_get_global_queue(0, 0), ^{ int result = [ACNetwork heartBeat]; // int result = 2; if (result == 2) { // 心跳成功才处理计时 [self markHeartBeatTime]; } else if (result == 4) { // 心跳超时 [weakself heartBeatTimeout]; } else if ([weakself checkHearBeatTimeOut]) {// 本地检查超时(上一次成功心跳距现在的间隔时间超出1h) // 本地不检查超时!!!不能知道后台设置的超时时长 // [weakself heartBeatTimeout]; } NSLog(@"heart beat result %d",result); }); } - (void)dealloc { [self stopHeartBeat]; } @end