// // AppDelegate.m // Apex And Drivers // // Created by Ray on 2018/5/26. // Copyright © 2018 USAI. All rights reserved. // #import "AppDelegate.h" #import #import "LoginViewController.h" #import "RAHomeViewController.h" #import #import "RANavigationController.h" #import "RAExceptionHandler.h" #import "RALoginNavigationController.h" #import "RAReachability.h" @interface AppDelegate () @property (nonatomic,strong) CLLocationManager *locationManager; @property (nonatomic,strong) NSDictionary *currentOrderNotification; @end @implementation AppDelegate #pragma mark - Private - (void)showHomeVC{ RAHomeViewController *homeVC = [RAHomeViewController viewControllerFromStoryboard]; RANavigationController *nav = [[RANavigationController alloc] initWithRootViewController:homeVC]; self.window.rootViewController = nav; } - (void)showLoginVC { LoginViewController *rootVC = [LoginViewController viewControllerFromStoryboard]; __weak typeof(self) weakSelf = self; rootVC.loginSuccessful = ^(NSString *user,NSString *password, NSString *firstName){ [[RASingleton sharedInstance] loginUser:user password:password firstName:firstName]; [weakSelf showHomeVC]; }; RALoginNavigationController *nav = [[RALoginNavigationController alloc] initWithRootViewController:rootVC]; self.window.rootViewController = nav; } - (void)saveUploadTasks { if(self.uploadManager.arr_queue!=nil) { [self.uploadManager stopAllTasks]; [self.uploadManager saveTasks]; } } //- (void)requestLocation //{ // [self initLocationManager]; // [self.locationManager requestLocation]; //} -(void)initLocationManager { if (self.locationManager) { return; } self.locationManager = [[CLLocationManager alloc] init]; self.locationManager.delegate = self; self.locationManager.allowsBackgroundLocationUpdates = NO; self.locationManager.pausesLocationUpdatesAutomatically = NO; // 是否允许系统自动暂停定位 self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;//设置定位精度 self.locationManager.distanceFilter = 10; //不需要移动都可以刷新,不然不移动就不会执行定位,不定位的话,那么后台进程也就挂起了 [self.locationManager requestAlwaysAuthorization]; } - (void)startBackgroundLocation { [self.locationManager startUpdatingLocation]; self.locationManager.allowsBackgroundLocationUpdates=false; } - (void)stopBackgroundLocation { if (self.locationManager == nil) { return; } // [self.locationManager stopUpdatingLocation]; self.locationManager.allowsBackgroundLocationUpdates=false; // self.locationManager = nil; } - (void)sendUploadCountNotification { dispatch_async(dispatch_get_main_queue(), ^{ NSUInteger count = self.uploadManager.arr_queue.count; [[NSNotificationCenter defaultCenter] postNotificationName:RANotificationChangeUpload object:nil userInfo:@{@"upload_count" : @(count)}]; }); } - (void)receiveLogoutNotification:(NSNotification *)notification { [self showLoginVC]; } - (void)receiveStartBackgroundLocationNotification:(NSNotification *)notification { [self startBackgroundLocation]; } - (void)receiveStopBackgroundLocationNotification:(NSNotification *)notification { [self stopBackgroundLocation]; } - (void)receiveUploadFinishNotification:(NSNotification *)notification { [self sendUploadCountNotification]; } - (void)receiveUploadCountChangeNotification:(NSNotification *)notification { [self sendUploadCountNotification]; } - (void)receiveRequestUploadCountNotification:(NSNotification *)notification { [self sendUploadCountNotification]; } - (void)registActionNotification { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveLogoutNotification:) name:RANotificationLogout object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveStartBackgroundLocationNotification:) name:RANotificationStartBackgroundLocation object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveStopBackgroundLocationNotification:) name:RANotificationStopBackgroundLocation object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveUploadFinishNotification:) name:UPLOAD_FINISH_NOTIFICATION object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveUploadFinishNotification:) name:UPLOAD_COUNT_CHANGE_NOTIFICATION object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveRequestUploadCountNotification:) name:RANotificationRequestUploadCount object:nil]; } #pragma mark - AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [self initLocationManager]; // Override point for customization after application launch. // NSString *orderID = nil; // NSInteger orderType = OrderTypeNew; // NSString *orderType2 = nil; // if (launchOptions) { // NSDictionary *userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; // NSDictionary *aps = [userInfo objectForKey:@"aps"]; // orderID = [aps objectForKey:@"order-id"]; // orderType = [[aps objectForKey:@"order-type"] integerValue]; // orderType2 = [aps objectForKey:@"order-type2"]; // // } [RAExceptionHandler registHandler:^(NSString *exceptionStr) { NSLog(@"Exception:\n%@",exceptionStr); }]; // 禁止Disk缓存,否则会和程序实现的缓存重复 [[NSURLCache sharedURLCache] setDiskCapacity:0]; #ifdef OFFLINE_MODE [[RAReachability defaultReachability] startNotifier:^(BOOL reachable) { [RASingleton sharedInstance].offline = !reachable; }]; #endif // [RADataProvider downloadOfflineData]; // [RASingleton sharedInstance].offline = YES; // View self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds]; self.window.backgroundColor = [UIColor whiteColor]; if (RASingleton.sharedInstance.autoLogin) { [self showHomeVC]; } else { [self showLoginVC]; } [self.window makeKeyAndVisible]; [RASingleton.sharedInstance loadSavedReuqiredLocation]; // [self registActionNotification]; //消息推送注册 UNUserNotificationCenter * center = [UNUserNotificationCenter currentNotificationCenter]; [center setDelegate:self]; UNAuthorizationOptions type = UNAuthorizationOptionBadge|UNAuthorizationOptionSound|UNAuthorizationOptionAlert; [center requestAuthorizationWithOptions:type completionHandler:^(BOOL granted, NSError * _Nullable error) { if (granted) { NSLog(@"推送通知授权成功"); }else{ NSLog(@"推送通知授权失败"); } }]; [application registerForRemoteNotifications]; // 程序被强杀之后收到通知,点击 通知 启动应用 if (launchOptions && application.applicationState == UIApplicationStateInactive) { NSMutableDictionary *userInfo = [[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey] mutableCopy]; if (userInfo) { [userInfo setObject:@(YES) forKey:@"go2Detail"]; [[NSNotificationCenter defaultCenter] postNotificationName:RANotificationHandleOrder object:nil userInfo:userInfo]; } } // [RASingleton.sharedInstance writeLog:[NSString stringWithFormat:@"isActive: %ld %s launchOptions:%@",application.applicationState,__func__,launchOptions]]; return YES; } - (void)applicationDidBecomeActive:(UIApplication *)application { if (!self.uploadManager) { [RAUploadManager configureUploadManager:^(RAUPloadManagerConfigure *configure) { configure.autoRemoveFinish = YES; // configure.retryCount = 1; // configure.retryTimeIntetval = 10; }]; self.uploadManager = [RAUploadManager sharedManager]; } // [UIApplication sharedApplication].applicationIconBadgeNumber = 0; // 程序在后台收到通知后,直接打开程序的情况下弹窗提示 if (self.currentOrderNotification) { [[NSNotificationCenter defaultCenter] postNotificationName:RANotificationHandleOrder object:nil userInfo:self.currentOrderNotification]; self.currentOrderNotification = nil; } } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. [self saveUploadTasks]; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } #pragma mark - Notification //完成注册后收到devicetoken - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { //上传deviceToken给后台服务器 if (![deviceToken isKindOfClass:[NSData class]]) return; const unsigned *tokenBytes = [deviceToken bytes]; NSString *deviceTokenStr = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x", ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]), ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]), ntohl(tokenBytes[6]), ntohl(tokenBytes[7])]; NSLog(@"deviceToken:%@",deviceTokenStr); // NSString *fullStr = [deviceToken description]; // NSLog(@"fullstr= %@",fullStr); // NSString *deviceTokenStr = [[[[deviceToken description] stringByReplacingOccurrencesOfString:@"<" withString:@""] stringByReplacingOccurrencesOfString:@">" withString:@""] stringByReplacingOccurrencesOfString:@" " withString:@""]; // NSLog(@"deviceTokenStr:\n%@",deviceTokenStr); [[RASingleton sharedInstance] setNotificationToken:deviceTokenStr]; } - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { NSLog(@"注册推送失败:%@",error); } //处理通知 - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler { // 程序在前台收到通知 UNNotificationRequest *request = notification.request; NSDictionary *userInfo = request.content.userInfo; if ([request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) { NSLog(@"收到远程通知: %@",userInfo); } else { NSLog(@"收到本地通知: %@",userInfo); } // UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert completionHandler(UNNotificationPresentationOptionNone); } - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler { NSLog(@"接收到推送内容==%@", response.notification.request.content.userInfo); // 点击通知 // NSDictionary *userInfo = response.notification.request.content.userInfo; // if (userInfo) { // // NSDictionary *aps = [userInfo objectForKey:@"aps"]; // // NSInteger is_order = [[aps objectForKey:@"is-order"] integerValue]; // if (is_order) { // [[NSNotificationCenter defaultCenter] postNotificationName:RANotificationHandleOrder object:nil userInfo:userInfo]; // } // } // [RASingleton.sharedInstance writeLog:[NSString stringWithFormat:@"isActive: %ld %s",[UIApplication sharedApplication].applicationState,__func__]]; self.currentOrderNotification = nil; NSMutableDictionary *userInfo = [response.notification.request.content.userInfo mutableCopy]; [userInfo setObject:@(YES) forKey:@"go2Detail"]; [[NSNotificationCenter defaultCenter] postNotificationName:RANotificationHandleOrder object:nil userInfo:userInfo]; completionHandler(); } - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { // [RASingleton.sharedInstance writeLog:[NSString stringWithFormat:@"isActive: %ld %s",application.applicationState,__func__]]; /** 静默推送alert为空 { "aps" : { "alert" : "", "content-available" : 1 } } */ // "content-available" : 1 收到通知 NSLog(@"收到静默推送: %@",userInfo); if (userInfo) { NSDictionary *aps = [userInfo objectForKey:@"aps"]; // [UIApplication sharedApplication].applicationIconBadgeNumber = [aps[@"badge"] intValue]; NSInteger report_location = [[aps objectForKey:@"report-location"] integerValue]; if (report_location == 1) { NSString *orderID = [aps objectForKey:@"order-id"]; BOOL tracing = [[aps objectForKey:@"tracing"] boolValue]; NSString *locationId = [aps objectForKey:@"location-id"]; if (tracing) { if (RASingleton.sharedInstance.backgroundReportType == RABackgroundReportTypeAllow) { [self reportLastLocation:[RASingleton sharedInstance].lastLocation forOrder:orderID locationID:locationId]; } else { [self rejectReportLocationWithReason:[NSString stringWithFormat:@"Reject tracing by app setting Driver: %@",RASingleton.sharedInstance.user] forOrder:orderID locationID:locationId]; } return; } if (RASingleton.sharedInstance.backgroundReportType == RABackgroundReportTypeAllow) { [self reportLastLocation:[RASingleton sharedInstance].lastLocation forOrder:orderID locationID:locationId]; } else if (RASingleton.sharedInstance.backgroundReportType == RABackgroundReportTypeAlwaysAsk) { [self askForReportLastLocation:orderID locationID:locationId]; } else if (RASingleton.sharedInstance.backgroundReportType == RABackgroundReportTypeReject) { [self rejectReportLocationWithReason:[NSString stringWithFormat:@"Reject ping by app setting,driver: %@",RASingleton.sharedInstance.user] forOrder:orderID locationID:locationId]; } completionHandler(UIBackgroundFetchResultNewData); } else { /** { "aps" : { "alert" : { "title" : "Notification", "body" : "You have a new order" }, "is-order" : 1, "order-id" : "AFS20180530001200", "order-type2" : "Pick Up", "order-type" : 2, "sound" : "default", "content-available" : 1 } } */ NSInteger is_order = [[aps objectForKey:@"is-order"] integerValue]; if (is_order) { // 程序在前台,弹窗提示 if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) { [[NSNotificationCenter defaultCenter] postNotificationName:RANotificationHandleOrder object:nil userInfo:userInfo]; } else { // 程序在后台,记录下来。当程序重新进入前台时弹窗提示(没有点击通知打开程序的情况) self.currentOrderNotification = userInfo; } } completionHandler(UIBackgroundFetchResultNewData); } } else { completionHandler(UIBackgroundFetchResultNoData); } } #pragma mark - Local Notification - (void)sendLocalNotification:(NSString *)title message:(NSString *)msg { // 创建Content UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init]; content.title = title; content.body = msg; content.badge = @([UIApplication sharedApplication].applicationIconBadgeNumber + 1); // 创建Request,保证ID一致 UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"local_notification" content:content trigger:nil]; // 发送 [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { if (!error) { NSLog(@"发送本地通知:%@",request.identifier); } }]; } #pragma mark - Report Location - (void)rejectReportLocationWithReason:(NSString *)reason forOrder:(NSString *)orderID locationID:(NSString *)locationId { dispatch_async(dispatch_get_global_queue(0, 0), ^{ [RADataProvider reportLocationWithUserReason:reason forOrder:orderID locationID:locationId]; }); } - (void)reportLastLocation:(CLLocation *)location forOrder:(NSString *)orderID locationID:(NSString *)locationId { dispatch_async(dispatch_get_global_queue(0, 0), ^{ [RADataProvider reportLastLocation:location forOrderID:orderID locationID:locationId]; }); } - (void)askForReportLastLocation:(NSString *)orderID locationID:(NSString *)locationId{ UIViewController *topVC = self.window.rootViewController; while (topVC.presentedViewController) { topVC = topVC.presentedViewController; } if (topVC) { UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"Warning" message:[NSString stringWithFormat:@"Report Location For Order:%@",orderID] preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [self rejectReportLocationWithReason:[NSString stringWithFormat:@"Driver %@ choose cancel of report location",RASingleton.sharedInstance.user] forOrder:orderID locationID:locationId]; }]; __weak typeof(self) weakSelf = self; UIAlertAction *reportAction = [UIAlertAction actionWithTitle:@"Report" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { [weakSelf reportLastLocation:[RASingleton sharedInstance].lastLocation forOrder:orderID locationID:locationId]; }]; [alertVC addAction:cancelAction]; [alertVC addAction:reportAction]; [topVC presentViewController:alertVC animated:YES completion:nil]; [self sendLocalNotification:@"Report Location Notification" message:[NSString stringWithFormat:@"The Apex ask your location for order:%@",orderID]]; } } #pragma mark - LocationManager Delegate - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { if (locations.count) { [RASingleton sharedInstance].currentLocation = [locations lastObject]; [RASingleton sharedInstance].lastLocation = [locations lastObject]; [RASingleton sharedInstance].lastLocationDateTime=[RAUtils current_date]; NSLog(@"location: %f, %f",[RASingleton sharedInstance].currentLocation.coordinate.latitude,[RASingleton sharedInstance].currentLocation.coordinate.longitude); // 省电,停止不能超过三分钟 // [self performSelector:@selector(stopLocation) withObject:nil afterDelay:10]; // 获取到位置10s后关闭位置服务 // [self performSelector:@selector(startLocation) withObject:nil afterDelay:120]; // 获取到位置120s后重新打开位置服务 //后台延迟定位3km,5分钟。 CLLocationDistance distance = 500; NSTimeInterval time = 60; if([UIApplication sharedApplication].applicationState == UIApplicationStateActive) { // more aggressive when app is active distance = 20; time = 20; } // if(!manager.allowsBackgroundLocationUpdates) // { // // } // [manager allowDeferredLocationUpdatesUntilTraveled:distance timeout:time]; } } - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { [RASingleton sharedInstance].currentLocation = nil; } - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { if (status == kCLAuthorizationStatusDenied) { [RASingleton sharedInstance].currentLocation = nil; }else { [self.locationManager startUpdatingLocation]; } } @end