// // AppDelegate.m // LN_School // // Created by apple on 2017/4/5. // Copyright © 2017年 Danson. All rights reserved. // #import "AppDelegate.h" #import "ExceptionHandle.h" #import "workVC.h" #import "HomePageViewController.h" #import "statisticsVC.h" #import "ContactVC.h" #import "personVC.h" #import "WaringVC.h" #import "CheckCourseVC.h" #import "MyUINavigationController.h" #import "LoginViewController.h" #import //客服 #import "QMProfileManager.h" @interface AppDelegate () { NSString *pushType; } @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //异常捕获 [ExceptionHandle catchException]; //设置根试图 self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; LoginViewController *vc = [[LoginViewController alloc] init]; [self.window setRootViewController:vc]; //版本更新检查 [self onCheckVersion]; //第三方sdk启动 [self registerThirdSDK]; //推送 /* 若用户点击icon启动,lauchOptions内无数据 */ #if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_10_0 //这里即使不判断系统版本,后面也做了避免消息重复处理。didReceiveNotificationResponse 统一处理 //远程通知 if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) { //关于这个方法远程和进程不一样 一个是userinfo字典。一个是本地通知 NSDictionary* userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:userInfo]; [self remoteNotificationDealWithDic:dic]; } #endif return YES; } - (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 { UIApplicationState state = [[UIApplication sharedApplication] applicationState]; NSLog(@"%ld",(long)state); if (state == UIApplicationStateInactive) {//---说明是锁屏 }else if(state == UIApplicationStateBackground){//---说明进入后台 NSLog(@"background"); } } - (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. //重置角标 [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];//本地 [GeTuiSdk resetBadge];//同步给个推 } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } #pragma mark 第三方sdk注册 -(void)registerThirdSDK{ //百度地图 // 如果要关注网络及授权验证事件,请设定 generalDelegate参数 BOOL ret = [[[BMKMapManager alloc]init] start:BAIDU_APPKEY generalDelegate:self]; if (!ret) { NSLog(@"manager start failed!"); } //客服注册 QMProfileManager *manger = [QMProfileManager sharedInstance]; [manger loadProfile:@"sinatechcn" password:@"321456"];//8062moor 123456 // 通过个推平台分配的appId、 appKey 、appSecret 启动SDK,注:该方法需要在主线程中调用 [GeTuiSdk startSdkWithAppId:kGtAppId appKey:kGtAppKey appSecret:kGtAppSecret delegate:self]; [self registerRemoteNotification]; } #pragma mark 初始化页面 - (void)initHomeVC { NSArray *titleArray = @[@"首页",@"统计",@"我的"]; NSArray *imageArray = @[@"HomePageNormal",@"MyStudentsNormal",@"PersonalCenterNormal"]; NSArray *image_hArray = @[@"HomePageSelected",@"MyStudentsSelected",@"PersonalCenterSelected"]; NSArray *vcArray = @[@"HomePageViewController",@"workVC"/*@"statisticsVC"*/,@"personVC"]; UITabBarController *tabBar = [[UITabBarController alloc] init]; NSMutableArray *navArray = [NSMutableArray arrayWithCapacity:titleArray.count]; for (int i = 0; i < titleArray.count; i ++) { NSString *vcName = vcArray[i]; UIViewController *vc = [[NSClassFromString(vcName) alloc] init]; UITabBarItem *item = [[UITabBarItem alloc] initWithTitle:titleArray[i] image:[[[UIImage imageNamed:imageArray[i]] tint:[UIColor grayColor]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] selectedImage:[[UIImage imageNamed:image_hArray[i]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]]; vc.tabBarItem = item; MyUINavigationController *nav = [[MyUINavigationController alloc] initWithRootViewController:vc]; [navArray addObject:nav]; } //统一设置tabBarItem的标题属性 [[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor grayColor],NSFontAttributeName:[UIFont scaleSize:14]} forState:UIControlStateNormal]; [[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:RQMianColor,NSFontAttributeName:[UIFont scaleSize:14]} forState:UIControlStateSelected]; tabBar.viewControllers = navArray; tabBar.selectedIndex = 0; [self.window setRootViewController:tabBar]; } #pragma mark 推送注册 /** 注册 APNs */ - (void)registerRemoteNotification { /* 警告:Xcode8 需要手动开启"TARGETS -> Capabilities -> Push Notifications" */ if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) { UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; center.delegate = self; [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionCarPlay) completionHandler:^(BOOL granted, NSError *_Nullable error) { if (!error) { NSLog(@"request authorization succeeded!(iOS >= 10.0)"); } }]; } else if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) { UIUserNotificationType types = (UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge); UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil]; [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; } //远程需添加 [[UIApplication sharedApplication] registerForRemoteNotifications]; } /** 远程通知注册成功委托 */ - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]]; token = [token stringByReplacingOccurrencesOfString:@" " withString:@""]; NSLog(@"\n>>>[DeviceToken Success]:%@\n\n", token); // 向个推服务器注册deviceToken [GeTuiSdk registerDeviceToken:token]; } /** 远程通知注册失败委托 */ - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { // NSLog(@"FailToRegisterForRemoteNotificationsWithError:%@",error); } //iOS7.0 以后支持 APP 后台刷新数据,会回调 performFetchWithCompletionHandler 接口。为保证个推SDK的数据刷新,需在该回调接口中调用[GeTuiSdk resume]方法帮助个推 SDK 刷新数据。 - (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { /// Background Fetch 恢复SDK 运行 [GeTuiSdk resume]; completionHandler(UIBackgroundFetchResultNewData); } #pragma mark - iOS < 10 /* 1.点击通知栏, 2.要求app未被杀死,如果app是terminate就去didfinishlaunch获取;这一点在ios10以后改善了 */ //------远程推送 //处理PNs 通知点击事件 A,统计有效用户点击数 - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { NSLog(@"didReceiveRemoteNotification and iOS<10"); // 将收到的APNs信息传给个推统计 [GeTuiSdk handleRemoteNotification:userInfo]; completionHandler(UIBackgroundFetchResultNewData); [self remoteNotificationDealWithDic:userInfo]; } #pragma mark iOS > 10 /* 1.对于iOS 10 及以后版本,为处理 APNs 通知点击,统计有效用户点击数,需先添加 UNUserNotificationCenterDelegate 2.app可以处于任何状态(terminate,前/后台) */ #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler { NSLog(@"willPresentNotification and iOS>10前台:%@", notification.request.content.userInfo); // 根据APP需要,判断是否要提示用户Badge、Sound、Alert(ios>10 如果需要应用在前台也展示通知) completionHandler(UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert); } // iOS 10: 统一获取推送的接口 点击通知进入App时触发,在该方法内统计有效用户点击数 (点击弹窗,不管app处于任何状态(terminate,前/后台)都会调用) - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler { NSLog(@"didReceiveNotificationResponse iOS>10:%@", response.notification.request.content.userInfo); //远程推送 //将收到的APNs信息传给个推统计 [GeTuiSdk handleRemoteNotification:response.notification.request.content.userInfo]; completionHandler(); NSDictionary* userInfo = response.notification.request.content.userInfo; [self remoteNotificationDealWithDic:userInfo]; } #endif #pragma mark - 个推相关方法 /** SDK启动成功返回cid */ - (void)GeTuiSdkDidRegisterClient:(NSString *)clientId { //个推SDK已注册,返回clientId NSLog(@"\n>>>[GeTuiSdk RegisterClient]:%@\n\n", clientId); myDelegate.token = clientId; [LoginViewController saveIosMei]; } /** SDK遇到错误回调 */ - (void)GeTuiSdkDidOccurError:(NSError *)error { //个推错误报告,集成步骤发生的任何错误都在这里通知,如果集成后,无法正常收到消息,查看这里的通知。 NSLog(@"\n>>>[GexinSdk error]:%@\n\n", [error localizedDescription]); } /** SDK收到透传消息回调 *//*(个推-客户端)*/ //只要你不是点通知窗口进来的,and发消息的时候有选择离线的情况,都会进这里---by@lee - (void)GeTuiSdkDidReceivePayloadData:(NSData *)payloadData andTaskId:(NSString *)taskId andMsgId:(NSString *)msgId andOffLine:(BOOL)offLine fromGtAppId:(NSString *)appId { //收到个推消息 if (payloadData) { NSString *payloadMsg = [[NSString alloc] initWithBytes:payloadData.bytes length:payloadData.length encoding:NSUTF8StringEncoding]; NSLog(@"GeTuiSdkDidReceivepayloadMsg:%@",payloadMsg); //判断是否被处理过[即发送离线消息的时候,会走apns+个推sdk(有效期内)] NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; NSString *oldmsgId = [userDefaults objectForKey:@"remoteNotifymsgId"]; if ([oldmsgId isEqualToString:msgId]) { return; } NSDictionary * dictionary = [NSJSONSerialization JSONObjectWithData:payloadData options:NSJSONReadingMutableContainers error:nil]; if (dictionary.count == 0) { return; } //sdk离线情况(非前台)点开进入会因didreceive已经处理,不再重复处理弹框】 pushType = [NSString stringWithFormat:@"%@",dictionary[@"code"]]; if (pushType != 0) { //报警信息 [RQ_SHARE_FUNCTION showAlertWithTitle:dictionary[@"title"] message:dictionary[@"body"] alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"取消" otherButtonTitles:@[@"前往"] otherButtonStyles:nil completion:^(NSUInteger selectedOtherButtonIndex) { if (selectedOtherButtonIndex == 0) { [self gotopPush]; } }]; }else{ //其它信息 [self showMsgByArertWithTitle:dictionary[@"title"] message:dictionary[@"body"]]; } } } #pragma mark 远程通知的数据处理 -(void)remoteNotificationDealWithDic:(NSDictionary *)userInfo{ /* { "_ge_" = 1; "_gmid_" = "OSL-0818_bJ6zVRy8cC6JsflZOYPXO9:965f14a1051748c4a48f9db2437362e5:d48422d462d2bcf0b9d962f150b235b9"; "_gurl_" = "sdk.open.extension.getui.com:8123"; aps = { alert = { body = "\U60a8\U9a7e\U6821\U6709\U8f66\U8f86\U7ec8\U7aef\U62a5\U8b66\U9700\U89e3\U9664\Uff0c\U8bf7\U67e5\U770b\U5e76\U5904\U7406"; title = "\U544a\U8b66\U6d88\U606f"; }; badge = 2; category = "button\U663e\U793a"; "content-available" = 1; "mutable-content" = 1; sound = default; }; payload = "{\"title\":\"\U544a\U8b66\U6d88\U606f\",\"type\":\"1\",\"msg\":\"\U60a8\U9a7e\U6821\U6709\U8f66\U8f86\U7ec8\U7aef\U62a5\U8b66\U9700\U89e3\U9664\Uff0c\U8bf7\U67e5\U770b\U5e76\U5904\U7406\"}"; } */ // _gmid_对应-- taskId msgId clientID //这里使用msgid判断是否被处理【不过似乎应该用taskid?@lee,幻想着一个任务多条消息] NSString *msgId = [userInfo[@"_gmid_"] componentsSeparatedByString:@":"][1]; NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; NSString *oldMsgId = [userDefaults objectForKey:@"remoteNotifymsgId"]; if ([msgId isEqualToString:oldMsgId]) { return; } //开始处理 [userDefaults setObject:msgId forKey:@"remoteNotifymsgId"]; [userDefaults synchronize]; NSString *jsonStr = userInfo[@"payload"]; if ([jsonStr length] == 0) { return; } NSData *data = [jsonStr dataUsingEncoding:NSUTF8StringEncoding]; if (data) { NSDictionary * payloadDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; if (payloadDic.count == 0) { return; } pushType = [NSString stringWithFormat:@"%@",payloadDic[@"code"]]; if (pushType != 0) { [self gotopPush]; }else{ //其它信息 [self showMsgByArertWithTitle:payloadDic[@"title"] message:payloadDic[@"body"]]; } } } -(void)showMsgByArertWithTitle:(NSString *)title message:(NSString *)message{ if (message.length == 0) { return; } //其它信息 [RQ_SHARE_FUNCTION showAlertWithTitle:title message:message alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"我知道了" otherButtonTitles:nil otherButtonStyles:nil completion:nil]; } #pragma mark - 推送跳转 -(void)gotopPush{ switch ([pushType integerValue]) { case 1: [self goWaringVC]; break; case 2: [self goCheckCourseVC]; break; default: break; } } -(void)goWaringVC{ if (defUser.userDict[@"school"] == nil) { [self showMsgByArertWithTitle:@"提示" message:@"请在登录成功后,前往报警统计界面查看详情"]; return; } WaringVC *vc = [[WaringVC alloc]init]; vc.isNotification = YES; MyUINavigationController *nav = [[MyUINavigationController alloc]initWithRootViewController:vc]; [myDelegate.window setRootViewController:nav]; } -(void)goCheckCourseVC{ if (defUser.userDict[@"school"] == nil) { [self showMsgByArertWithTitle:@"提示" message:@"请在登录成功后,前往学时审核界面查看详情"]; return; } CheckCourseVC *vc = [[CheckCourseVC alloc]init]; vc.isNotification = YES; MyUINavigationController *nav = [[MyUINavigationController alloc]initWithRootViewController:vc]; [myDelegate.window setRootViewController:nav]; } #pragma mark 检查新旧 -(void)onCheckVersion { if (![NetManager connectedToNetWork]) { return; } NSDictionary *infoDic = [[NSBundle mainBundle] infoDictionary]; NSString *currentVersion = [infoDic objectForKey:@"CFBundleShortVersionString"]; NSString *URL = @"http://itunes.apple.com/cn/lookup?id=1284632997"; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setURL:[NSURL URLWithString:URL]]; [request setHTTPMethod:@"POST"]; NSOperationQueue *queue=[NSOperationQueue mainQueue]; [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { //这个导致部分手机网络不好时候出现闪退情况 if (!data) { return; } //如果data等于nil的时候 再去解析 会发生崩溃 NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; if (!dic) { return; } NSArray *infoArray = [dic objectForKey:@"results"]; if ([infoArray count]) { NSDictionary *releaseInfo = [infoArray objectAtIndex:0]; NSString *lastVersion = [releaseInfo objectForKey:@"version"]; NSInteger lastInt = [[lastVersion substringToIndex:1] integerValue]; NSInteger currInt = [[currentVersion substringToIndex:1] integerValue]; if (lastInt > currInt) { [self updateVersion]; }else{ double lastDoub = [[lastVersion substringWithRange:NSMakeRange(2, 3)]doubleValue]; double currDoub = [[currentVersion substringWithRange:NSMakeRange(2, 3)]doubleValue]; if (lastDoub > currDoub) { [self updateVersion]; } } } }]; } -(void)updateVersion { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"更新提示" message:@"有新的版本发布,是否前往更新?" delegate:self cancelButtonTitle:@"关闭" otherButtonTitles:@"更新", nil]; alert.tag = 10000; [alert show]; } -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { if (alertView.tag == 10000) { if (buttonIndex == 1) { NSURL *url = [NSURL URLWithString:@"itms-apps://itunes.apple.com/cn/app/id1284632997?l=en&mt=8"]; [[UIApplication sharedApplication]openURL:url]; } } } @end