123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- //
- // AppDelegate.m
- // 速达驾考
- //
- // Created by 张嵘 on 2021/7/23.
- //
- #import "AppDelegate.h"
- #import "DOUAudioStreamer+Options.h"
- #import "WXApi.h"
- #import <GTSDK/GeTuiSdk.h> // GetuiSdk头文件
- #import <Bugly/Bugly.h>
- #import <DouyinOpenSDK/DouyinOpenSDKAuth.h>
- #import <ZFPlayer/ZFLandscapeRotationManager.h>
- @interface AppDelegate () <WXApiDelegate, GeTuiSdkDelegate>
- /// APP管理的导航栏的堆栈
- @property (nonatomic, readwrite, strong) RQNavigationControllerStack *navigationControllerStack;
- /// APP的服务层
- @property (nonatomic, readwrite, strong) RQViewModelServicesImpl *services;
- @end
- @implementation AppDelegate
- @synthesize window;
- #pragma mark- 获取appDelegate
- + (AppDelegate *)sharedDelegate {
- return (AppDelegate *)[[UIApplication sharedApplication] delegate];
- }
- //程序开始
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- // [super application:application didFinishLaunchingWithOptions:launchOptions];
-
- /// 初始化UI之前配置
- [self rq_configureApplication:application initialParamsBeforeInitUI:launchOptions];
-
- // Config Service
- self.services = [[RQViewModelServicesImpl alloc] init];
- // Config Nav Stack
- self.navigationControllerStack = [[RQNavigationControllerStack alloc] initWithServices:self.services];
- // Configure Window
- self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] currentBounds]];
- self.window.backgroundColor = [UIColor whiteColor];
- self.window.qmui_capturesStatusBarAppearance = NO;
- // 重置rootViewController
- [self.services resetRootViewModel:[self rq_createInitialViewModel]];
- // 让窗口可见
- [self.window makeKeyAndVisible];
-
- // 初始化UI后配置
- [self rq_configureApplication:application initialParamsAfterInitUI:launchOptions];
-
- #if defined(DEBUG)||defined(_DEBUG)
- /// 调试模式
- [self rq_configDebugModelTools];
- #endif
-
- // Save the application version info. must write last
- [[NSUserDefaults standardUserDefaults] setValue:RQ_APP_VERSION forKey:RQApplicationVersionKey];
- [[NSUserDefaults standardUserDefaults] synchronize];
-
-
-
- return YES;
- }
- #pragma mark - 在初始化UI之前配置
- - (void)rq_configureApplication:(UIApplication *)application initialParamsBeforeInitUI:(NSDictionary *)launchOptions {
-
- /// 检测网络权限
- [RQ_HTTP_Service networkAuthStatus];
-
- // 配置键盘
- [self rq_configureKeyboardManager];
-
- // 配置文件夹
- [self rq_configureApplicationDirectory];
-
- // 配置FMDB
- [self rq_configureFMDB];
-
- // 配置流音乐播放
- [DOUAudioStreamer setOptions:[DOUAudioStreamer options] | DOUAudioStreamerRequireSHA256];
-
- // 配置微信
- [self rq_configureWechat];
-
- // 配置个推
- [self rq_configureGeTui];
-
- // 配置Bugly
- [self rq_configureBugly];
-
- // 获取视频
- [self rq_configureVideoes];
-
- // 监控自动读题
- [self rq_autoRead];
-
- /// 配置抖音
- [RQ_DOUYIN_MANAGER initDouYinManagerWithApplication:application didFinishLaunchingWithOptions:launchOptions];
- }
- // 配置键盘管理器
- - (void)rq_configureKeyboardManager {
- IQKeyboardManager.sharedManager.enable = YES;
- IQKeyboardManager.sharedManager.enableAutoToolbar = NO;
- IQKeyboardManager.sharedManager.shouldResignOnTouchOutside = YES;
- }
- // 配置文件夹
- - (void)rq_configureApplicationDirectory {
- /// 创建doc
- [RQFileManager createDirectoryAtPath:RQWeChatDocDirPath()];
- /// 创建cache
- [RQFileManager createDirectoryAtPath:RQWeChatCacheDirPath()];
-
- // NSLog(@"RQWeChatDocDirPath is [ %@ ] \n RQWeChatCacheDirPath is [ %@ ]" , RQWeChatDocDirPath() , RQWeChatCacheDirPath());
- }
- /// 配置FMDB
- - (void)rq_configureFMDB {
- // FMDatabaseQueue *databaseQueue = [[FMDatabaseQueue alloc] init];
- // [databaseQueue inDatabase:^(FMDatabase *db) {
- // NSString *version = [[NSUserDefaults standardUserDefaults] valueForKey:RQApplicationVersionKey];
- // if (![version isEqualToString:RQ_APP_VERSION]) {
- // NSString *path = [[NSBundle mainBundle] pathForResource:@"question20211105" ofType:@"db"];
- // NSString *sql = [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
- // /// 执行文件
- // if (![db executeStatements:sql]) {
- // RQLogLastError(db);
- // }
- // }
- // }];
-
- NSFileManager *fileManager =[NSFileManager defaultManager];
- NSError*error;
- if ([fileManager fileExistsAtPath:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:[NSString stringWithFormat:@"question.db"]]]== NO) {
- NSString*resourcePath =[[NSBundle mainBundle] pathForResource:@"question" ofType:@"db"];
- [fileManager copyItemAtPath:resourcePath toPath:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:[NSString stringWithFormat:@"question.db"]] error:&error];
- }
-
- if (RQ_USER_MANAGER.isLogin) {
- // [RQ_UPDATE_LOCALDATA_MANAGER updateLocalWrongAndCollectionWithComplete:nil];
- [RQ_USER_MANAGER isVipWithComplete:^(NSInteger isVip) {}];
- }
-
- }
- - (void)rq_configureWechat {
- /// 向微信注册
- [RQ_WECHAT_MANAGER initWechatManager];
- }
- - (void)rq_configureGeTui {
- // 通过个推平台分配的appId、 appKey 、appSecret 启动SDK,注:该方法需要在主线程中调用
- [GeTuiSdk startSdkWithAppId:@"yeBmFCmPHu8Up6cFXonxU1" appKey:@"0Mp7hV8p6SAyz3ylcGOmo4" appSecret:@"F3oofsCQJT7vPo4zcYmRV4" delegate:self launchingOptions:nil];
-
- // 注册远程通知
- if (@available(iOS 10.0, *)) {
- [GeTuiSdk registerRemoteNotification: (UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge)];
- } else {
- // Fallback on earlier versions
- }
- }
- - (void)rq_configureBugly {
- [Bugly startWithAppId:@"713fbad4c6"];
- }
- - (void)rq_configureVideoes {
- [[RQ_HTTP_Service getTreeList] subscribeNext:^(NSArray <RQTreeListModel *> * dataArr) {
- if (!RQObjectIsNil(dataArr)) {
- RQ_COMMON_MANAGER.treeListArr = dataArr;
- }
- }];
-
- [[RQ_HTTP_Service getDspList] subscribeNext:^(NSArray <VideosItem *> * videosItemArr) {
- if (!RQObjectIsNil(videosItemArr)) {
- RQ_COMMON_MANAGER.dspListArr = videosItemArr;
- }
- }];
- }
- - (void)rq_autoRead {
- [RQ_Exercise_Module rq_RACIsAutoRead];
- }
- #pragma mark - 在初始化UI之后配置
- - (void)rq_configureApplication:(UIApplication *)application initialParamsAfterInitUI:(NSDictionary *)launchOptions {
- [RQ_CACHE_MANAGER removeAllCache];
-
- // [RQ_AD_MANAGER loadAdWithAdType:RQADType_InterstitialSplash customView:nil];
- /// 配置ActionSheet
- [LCActionSheet rq_configureActionSheet];
-
- /// 预先配置平台信息
- // [SBUMengService configureUMengPreDefinePlatforms];
-
- @weakify(self);
- /// 监听切换根控制器的通知
- [[RQNotificationCenter rac_addObserverForName:RQSwitchRootViewControllerNotification object:nil] subscribeNext:^(NSNotification * note) {
- /// 这里切换根控制器
- @strongify(self);
- // 重置rootViewController
- RQSwitchRootViewControllerFromType fromType = [note.userInfo[RQSwitchRootViewControllerUserInfoKey] integerValue];
- NSLog(@"fromType is %zd" , fromType);
- /// 切换根控制器
- [self.services resetRootViewModel:[self rq_createInitialViewModel]];
-
-
- /// 切换了根控制器,切记需要将指示器 移到window的最前面
- #if defined(DEBUG)||defined(_DEBUG)
- // [self.window bringSubviewToFront:[RQDebugTouchView sharedInstance]];
- #endif
- }];
-
- /// 配置H5
- // [SBConfigureManager configure];
- if (@available(iOS 15.0, *)) {
- [UITableView appearance].sectionHeaderTopPadding = 0;
- }
-
- [RQ_CACHE_MANAGER removeAllCache];
-
- [RQ_COMMON_MANAGER checkAppStoreVersionWithComplete:^(BOOL isNeedUpdate) {
- if (isNeedUpdate) {
- [RQ_Question_Module rq_showAppUpdateView];
- }
- }];
-
- /// 更新题库
- [RQ_Question_Module rq_updateQuestion];
-
-
- [[RQ_HTTP_Service getConfigKeyWithPath:RQSDJKAPPICONNEEDCHANGEPath] subscribeNext:^(id _Nullable x) {
- RQ_COMMON_MANAGER.SDJK_APP_ICON_NEED_CHANGE = [x boolValue];
- }];
-
- [[RQ_HTTP_Service getDictTypeWithPath:RQVipTypePath] subscribeNext:^(id _Nullable x) {
- NSArray *a = RQObjectIsNil(x)? @[] : x;
- RQ_COMMON_MANAGER.vipTypeListArr = a;
- }];
-
-
- [RQ_AD_MANAGER loadAdWithAdType:RQADType_Splash customView:nil];
- }
- #pragma mark - 调试(DEBUG)模式下的工具条
- - (void)rq_configDebugModelTools {
- /// 显示FPS
- [[JPFPSStatus sharedInstance] open];
- [QMUIConsole sharedInstance].canShow = YES;
- /// 打开调试按钮
- [RQDebugTouchView sharedInstance];
- /// RQ Fixed: 切换了根控制器,切记需要将指示器 移到window的最前面
- [self.window bringSubviewToFront:[RQDebugTouchView sharedInstance]];
-
- }
- #pragma mark - 创建根控制器
- - (RQBaseViewModel *)rq_createInitialViewModel {
- // The user has logged-in.
- // NSString *version = [[NSUserDefaults standardUserDefaults] valueForKey:RQApplicationVersionKey];
- /// 版本不一样就先走 新特性界面
- // if (![version isEqualToString:RQ_APP_VERSION]){
- // return [[RQNewFeatureViewModel alloc] initWithServices:self.services params:nil];
- // }else{
- /// 这里判断一下
- // if ([SAMKeychain rawLogin] && self.services.client.currentUser) {
- /// 有账号+有用户数据
- /// 已经登录,跳转到主页
- return [[RQMainTabBarViewModel alloc] initWithServices:self.services params:nil];
- // }else if(self.services.client.currentUser){ /// 没账号+有用户数据
- /// 跳转到账户登录页面
- // return [[RQAccountLoginViewModel alloc] initWithServices:self.services params:nil];
- // }else{
- /// 第一次使用微信
- // return [[RQBootLoginViewModel alloc] initWithServices:self.services params:nil];
- // }
- // }
- }
- /**
- 对文件重命名
- @param filePath 旧路径
- @return 新路径
- */
- - (NSString *)p_setupFileRename:(NSString *)filePath {
-
- NSString *lastPathComponent = [NSString new];
- //获取文件名: 视频.MP4
- lastPathComponent = [filePath lastPathComponent];
- //获取后缀:MP4
- NSString *pathExtension = [filePath pathExtension];
- //用传过来的路径创建新路径 首先去除文件名
- NSString *pathNew = [filePath stringByReplacingOccurrencesOfString:lastPathComponent withString:@""];
- //然后拼接新文件名:新文件名为当前的:年月日时分秒 yyyyMMddHHmmss
- NSString *moveToPath = [NSString stringWithFormat:@"%@%@.%@",pathNew,[self htmi_getCurrentTime],pathExtension];
- NSFileManager *fileManager = [NSFileManager defaultManager];
- //通过移动该文件对文件重命名
- BOOL isSuccess = [fileManager moveItemAtPath:filePath toPath:moveToPath error:nil];
- if (isSuccess) {
- NSLog(@"rename success");
- }else{
- NSLog(@"rename fail");
- }
-
- return moveToPath;
- }
- /**
- 获取当地时间
-
- @return 获取当地时间
- */
- - (NSString *)htmi_getCurrentTime {
- NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
- [formatter setDateFormat:@"yyyyMMddHHmmss"];
- NSString *dateTime = [formatter stringFromDate:[NSDate date]];
- return dateTime;
- }
- - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray<id<UIUserActivityRestoring>> * __nullable restorableObjects))restorationHandler {
- return [WXApi handleOpenUniversalLink:userActivity delegate:RQ_WECHAT_MANAGER];
- }
- //- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options {
- // return [WXApi handleOpenURL:url delegate:RQ_WECHAT_MANAGER];
- //}
- #pragma mark - 推送(个推)
- /// 通知展示(iOS10及以上版本)
- /// @param center center
- /// @param notification notification
- /// @param completionHandler completionHandler
- - (void)GeTuiSdkNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification completionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler API_AVAILABLE(ios(10.0)){
- NSString *msg = [NSString stringWithFormat:@"[ TestDemo ] [APNs] %@ \n%@", NSStringFromSelector(_cmd), notification.request.content.userInfo];
- NSLog(@"-----个推-----通知展示----%@",msg);
- // [ 参考代码,开发者注意根据实际需求自行修改 ] 根据APP需要,判断是否要提示用户Badge、Sound、Alert等
- //completionHandler(UNNotificationPresentationOptionNone); 若不显示通知,则无法点击通知
- completionHandler(UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert);
- }
- /// 收到通知信息
- /// @param userInfo apns通知内容
- /// @param center UNUserNotificationCenter(iOS10及以上版本)
- /// @param response UNNotificationResponse(iOS10及以上版本)
- /// @param completionHandler 用来在后台状态下进行操作(iOS10以下版本)
- - (void)GeTuiSdkDidReceiveNotification:(NSDictionary *)userInfo notificationCenter:(UNUserNotificationCenter *)center response:(UNNotificationResponse *)response fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler API_AVAILABLE(ios(10.0)){
- NSString *msg = [NSString stringWithFormat:@"[ TestDemo ] [APNs] %@ \n%@", NSStringFromSelector(_cmd), userInfo];
- NSLog(@"-----个推-----收到通知信息----%@",msg);
- if(completionHandler) {
- // [ 参考代码,开发者注意根据实际需求自行修改 ] 根据APP需要自行修改参数值
- completionHandler(UIBackgroundFetchResultNoData);
- }
- }
- /// 收到透传消息
- /// @param userInfo 推送消息内容
- /// @param fromGetui YES: 个推通道 NO:苹果apns通道
- /// @param offLine 是否是离线消息,YES.是离线消息
- /// @param appId 应用的appId
- /// @param taskId 推送消息的任务id
- /// @param msgId 推送消息的messageid
- /// @param completionHandler 用来在后台状态下进行操作(通过苹果apns通道的消息 才有此参数值)
- - (void)GeTuiSdkDidReceiveSlience:(NSDictionary *)userInfo fromGetui:(BOOL)fromGetui offLine:(BOOL)offLine appId:(NSString *)appId taskId:(NSString *)taskId msgId:(NSString *)msgId fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
- // [ GTSDK ]:汇报个推自定义事件(反馈透传消息),开发者可以根据项目需要决定是否使用, 非必须
- // [GeTuiSdk sendFeedbackMessage:90001 andTaskId:taskId andMsgId:msgId];
- NSString *msg = [NSString stringWithFormat:@"[ TestDemo ] [APN] %@ \nReceive Slience: fromGetui:%@ appId:%@ offLine:%@ taskId:%@ msgId:%@ userInfo:%@ ", NSStringFromSelector(_cmd), fromGetui ? @"个推消息" : @"APNs消息", appId, offLine ? @"离线" : @"在线", taskId, msgId, userInfo];
- NSLog(@"-----个推-----收到透传消息----%@",msg);
- if(completionHandler) {
- // [ 参考代码,开发者注意根据实际需求自行修改 ] 根据APP需要自行修改参数值
- completionHandler(UIBackgroundFetchResultNoData);
- }
- }
- - (void)GeTuiSdkNotificationCenter:(UNUserNotificationCenter *)center openSettingsForNotification:(UNNotification *)notification API_AVAILABLE(ios(10.0)){
- // [ 参考代码,开发者注意根据实际需求自行修改 ] 根据APP需要自行修改参数值
- }
- - (void)GeTuiSdkDidOccurError:(NSError *)error {
- NSString *msg = [NSString stringWithFormat:@"[ TestDemo ] [GeTuiSdk GeTuiSdkDidOccurError]:%@\n\n",error.localizedDescription];
- // SDK发生错误时,回调异常错误信息
- NSLog(@"%@", msg);
- }
- /** SDK启动成功返回cid */
- - (void)GeTuiSdkDidRegisterClient:(NSString *)clientId {
- //个推SDK已注册,返回clientId
- NSLog(@"\n>>>[GeTuiSdk RegisterClient]:%@\n\n", clientId);
- }
- #pragma mark - DouyinOpenSDKLogDelegate
- - (void)onLog:(nonnull NSString *)logInfo {
-
- }
- - (BOOL)application:(UIApplication *)application openURL:(nonnull NSURL *)url options:(nonnull NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
- if ([[DouyinOpenSDKApplicationDelegate sharedInstance] application:application openURL:url sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey] annotation:options[UIApplicationOpenURLOptionsAnnotationKey]]
- ) {
- return YES;
- }
-
- return [WXApi handleOpenURL:url delegate:RQ_WECHAT_MANAGER];
- }
- /// 在这里写支持的旋转方向,为了防止横屏方向,应用启动时候界面变为横屏模式
- //- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
- // if (self.allowOrentitaionRotation) {
- // return UIInterfaceOrientationMaskAllButUpsideDown;
- // }
- // return UIInterfaceOrientationMaskPortrait;
- //}
- - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
- ZFInterfaceOrientationMask orientationMask = [ZFLandscapeRotationManager supportedInterfaceOrientationsForWindow:window];
- if (orientationMask != ZFInterfaceOrientationMaskUnknow) {
- return (UIInterfaceOrientationMask)orientationMask;
- }
- /// 这里是非播放器VC支持的方向
- return UIInterfaceOrientationMaskPortrait;
- }
- @end
|