|
|
@@ -0,0 +1,1105 @@
|
|
|
+//
|
|
|
+// AppDelegate.m
|
|
|
+// aiim
|
|
|
+//
|
|
|
+// Created by gan on 2025/2/27.
|
|
|
+//
|
|
|
+
|
|
|
+#import "AppDelegate.h"
|
|
|
+#import "UDManager.h"
|
|
|
+#import <UserNotifications/UserNotifications.h>
|
|
|
+#import <PushKit/PushKit.h>
|
|
|
+#import "CallKit/CallKit.h"
|
|
|
+#import <netinet/in.h>
|
|
|
+#import <SystemConfiguration/SystemConfiguration.h>
|
|
|
+#import "UserNetApi.h"
|
|
|
+#import "CryptoAES.h"
|
|
|
+#import "GWebSocket.h"
|
|
|
+#import "GDBManager.h"
|
|
|
+#import "APPLocker.h"
|
|
|
+#import "JSGController.h"
|
|
|
+#import "LoginStateManager.h"
|
|
|
+
|
|
|
+#import "FloatingWindow.h"
|
|
|
+#import "ChatIndexController.h"
|
|
|
+#import "ChatController.h"
|
|
|
+#import "ChatListStore.h"
|
|
|
+#import "ChatsStore.h"
|
|
|
+
|
|
|
+#import "OSSManager.h"
|
|
|
+
|
|
|
+#import <Bugly/Bugly.h>
|
|
|
+
|
|
|
+
|
|
|
+@import JitsiMeetSDK;
|
|
|
+
|
|
|
+@interface AppDelegate ()<UNUserNotificationCenterDelegate,PKPushRegistryDelegate,CXProviderDelegate>
|
|
|
+@property (nonatomic, strong) CXProvider *callProvider;
|
|
|
+@property (nonatomic) NSUUID *uuid;
|
|
|
+@property (nonatomic) NSDictionary *msg;
|
|
|
+@property (strong, nonatomic) NSTimer *timer;
|
|
|
+@property (nonatomic) NSInteger timerActCount;
|
|
|
+@property (strong, nonatomic) NSString *bgMark;
|
|
|
+
|
|
|
+@property (nonatomic) BOOL isTokenCleared;
|
|
|
+
|
|
|
+@property (strong, nonatomic) FloatingWindow *floatWindow;
|
|
|
+@property (nonatomic, strong) JSGController * _Nullable jsyuyinctr;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+@property (nonatomic) BOOL isNotification;
|
|
|
+
|
|
|
+@end
|
|
|
+
|
|
|
+@implementation AppDelegate
|
|
|
+
|
|
|
+
|
|
|
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
|
|
+ // Override point for customization after application launch.
|
|
|
+ app = self;
|
|
|
+ BuglyConfig *config = [[BuglyConfig alloc] init];
|
|
|
+ config.reportLogLevel = BuglyLogLevelVerbose;
|
|
|
+ [Bugly startWithAppId:@"1d9e6b546a" config:config];
|
|
|
+ self.isJitsiMeet=false;
|
|
|
+ _isNotification=false;
|
|
|
+ self.shouldShowLock = YES;
|
|
|
+ self.bgMark=@"";
|
|
|
+
|
|
|
+
|
|
|
+ [self initJSMSDK];
|
|
|
+ [self setupListener];
|
|
|
+ [self checkLoginState:launchOptions];
|
|
|
+ [self registerPushright];
|
|
|
+ [self setupCallProvider];
|
|
|
+ [self initAliyunOss];
|
|
|
+
|
|
|
+ _isTokenCleared=YES;
|
|
|
+
|
|
|
+ _floatWindow = [[FloatingWindow alloc] initWithFrame:self.window.bounds];
|
|
|
+ [_floatWindow hide];
|
|
|
+ self.bgMark = @"";
|
|
|
+
|
|
|
+ NSLog(@"didFinishLaunchingWithOptions------");
|
|
|
+
|
|
|
+
|
|
|
+ AVAudioSession *session = [AVAudioSession sharedInstance];
|
|
|
+ [session setCategory:AVAudioSessionCategoryPlayAndRecord mode:AVAudioSessionModeVoiceChat options:AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryOptionAllowBluetoothA2DP | AVAudioSessionCategoryOptionAllowAirPlay error:nil];
|
|
|
+ [session setActive:YES error:nil];
|
|
|
+
|
|
|
+ return YES;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+-(void)applicationDidBecomeActive:(UIApplication *)application{
|
|
|
+ NSLog(@"applicationDidBecomeActive");
|
|
|
+
|
|
|
+ if(self.isLogin){
|
|
|
+ [self sartWebsocket];
|
|
|
+ if(self.isJitsiMeet){
|
|
|
+ [_floatWindow viewInFload:0];
|
|
|
+ }
|
|
|
+ [self showLockScreen];
|
|
|
+ if(!_isNotification){
|
|
|
+ if ([[self.window jk_currentViewController] isKindOfClass:UITabBarController.class]){
|
|
|
+ UITabBarController * tabbarVc= (UITabBarController *)[self.window jk_currentViewController];
|
|
|
+ if (tabbarVc.selectedIndex==0) {
|
|
|
+ ChatIndexController * chatListVc = tabbarVc.viewControllers[0];
|
|
|
+ if (chatListVc) {
|
|
|
+ [chatListVc reloadList];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ [Bugly reportException:[NSException exceptionWithName:@"applicationDidBecomeActive1" reason:@"1" userInfo:nil]];
|
|
|
+ if ([[self.window jk_currentViewController] isKindOfClass:ChatController.class]) {
|
|
|
+ ChatController * currentChatVc = (ChatController *)[self.window jk_currentViewController];
|
|
|
+ [currentChatVc reloadAllData];
|
|
|
+ [Bugly reportException:[NSException exceptionWithName:@"applicationDidBecomeActive2" reason:@"2" userInfo:nil]];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ [self startTimer];
|
|
|
+ // 应用从后台返回前台时检查是否需要显示锁屏
|
|
|
+}
|
|
|
+-(void)applicationDidEnterBackground:(UIApplication *)application{
|
|
|
+ NSLog(@"applicationDidEnterBackground");
|
|
|
+ _isNotification=false;
|
|
|
+// [self endWebsocket];
|
|
|
+ __block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
|
|
|
+ [application endBackgroundTask:bgTask];
|
|
|
+ bgTask = UIBackgroundTaskInvalid;
|
|
|
+ }];
|
|
|
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
|
+ // 在这里保持任务运行或等待事件,例如等待来电等。
|
|
|
+ [application endBackgroundTask:bgTask];
|
|
|
+ bgTask = UIBackgroundTaskInvalid;
|
|
|
+ });
|
|
|
+ // 应用进入后台时标记需要显示锁屏
|
|
|
+
|
|
|
+ if(self.isJitsiMeet == YES){
|
|
|
+ [self.window endEditing:YES];
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ if ([[APPLocker sharedLocker] isPasswordSet] && [[APPLocker sharedLocker] isLockEnabled]) {
|
|
|
+ self.shouldShowLock = YES;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ [self endTimer];
|
|
|
+}
|
|
|
+
|
|
|
++ (instancetype)sharedInstance {
|
|
|
+ return app;
|
|
|
+}
|
|
|
+
|
|
|
+-(void)initJSMSDK{
|
|
|
+
|
|
|
+ JitsiMeetConferenceOptions *defaultOptions
|
|
|
+ = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
|
|
|
+ builder.serverURL = [NSURL URLWithString:JitsiMeetSV];
|
|
|
+ [builder setFeatureFlag:@"welcomepage.enabled" withBoolean:NO];
|
|
|
+ [builder setFeatureFlag:@"prejoinPage.enabled" withBoolean:NO];
|
|
|
+ //媒体流优化
|
|
|
+ builder.audioMuted = NO; // 提前初始化音频模块
|
|
|
+ builder.videoMuted = NO; // 提前初始化视频模块
|
|
|
+ //禁用非必要功能(减少初始化负载)
|
|
|
+ [builder setFeatureFlag:@"add-people.enabled" withBoolean:NO];
|
|
|
+ [builder setFeatureFlag:@"invite.enabled" withBoolean:NO];
|
|
|
+ [builder setFeatureFlag:@"live-streaming.enabled" withBoolean:NO];
|
|
|
+ [builder setFeatureFlag:@"video-share.enabled" withBoolean:NO];
|
|
|
+ [builder setFeatureFlag:@"call-integration.enabled" withBoolean:NO];
|
|
|
+ [builder setFeatureFlag:@"startWithAudioMuted" withBoolean:NO];
|
|
|
+ [builder setFeatureFlag:@"recording.enabled" withBoolean:NO];
|
|
|
+ [builder setFeatureFlag:@"kick-out.enabled" withBoolean:NO];
|
|
|
+ [builder setFeatureFlag:@"security-options.enabled" withBoolean:NO];
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// //网络传输层加速
|
|
|
+// [builder setConfigOverride:@"disableSimulcast" withBoolean:YES];
|
|
|
+// [builder setFeatureFlag:@"reconnect.enabled" withBoolean:YES];
|
|
|
+// [builder setFeatureFlag:@"websocket-keep-alive.enabled" withBoolean:YES];
|
|
|
+// [builder setFeatureFlag:@"network-monitor.enabled" withBoolean:YES];
|
|
|
+// [builder setConfigOverride:@"iceTransportPolicy" withValue:@"relay"];
|
|
|
+// // 界面渲染加速
|
|
|
+// [builder setFeatureFlag:@"filmstrip.enabled" withBoolean:NO];
|
|
|
+// [builder setFeatureFlag:@"tile-view.enabled" withBoolean:NO];
|
|
|
+//
|
|
|
+// [builder setFeatureFlag:@"pip.enabled" withBoolean:NO];
|
|
|
+// [builder setFeatureFlag:@"chat.enabled" withBoolean:NO];
|
|
|
+ [builder setConfigOverride:@"toolbarButtons" withArray:@[@"microphone",@"camera"]];
|
|
|
+ }];
|
|
|
+ [JitsiMeet sharedInstance].defaultConferenceOptions = defaultOptions;
|
|
|
+ UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
|
|
|
+ _jsyuyinctr = [board instantiateViewControllerWithIdentifier:@"JSGController"];
|
|
|
+ _jsyuyinctr.modalPresentationStyle = UIModalPresentationFullScreen;
|
|
|
+}
|
|
|
+
|
|
|
+-(void)setupListener{
|
|
|
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onLoginSucc) name:nkonLoginSucc object:nil];
|
|
|
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onLogoutSucc) name:nkonLogoutSucc object:nil];
|
|
|
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(addFriend) name:nkonAddFriendNote object:nil];;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
|
|
|
+ NSLog(@"Failed to get token, error: %@", error);
|
|
|
+}
|
|
|
+
|
|
|
+//阿里云oss:https://abtimoss.oss-ap-southeast-1.aliyuncs.com
|
|
|
+//AccessKey ID
|
|
|
+//LTAI5tNoRjDRMuvnKBcop3hL
|
|
|
+//AccessKey Secret
|
|
|
+//kUoR7zqLafRYpcz3vJk1JHTvkRaaSl
|
|
|
+-(void)initAliyunOss{
|
|
|
+ [[OSSManager sharedManager] getOSSInfo];
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+#pragma mark push token voip token
|
|
|
+
|
|
|
+-(void)registerPushright{
|
|
|
+ // 请求推送权限
|
|
|
+ if (@available(iOS 10.0, *)) {
|
|
|
+ UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
|
|
|
+ center.delegate = self; // 设置代理以处理通知相关事件
|
|
|
+ [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionProvidesAppNotificationSettings) completionHandler:^(BOOL granted, NSError * _Nullable error) {
|
|
|
+ if (granted) {
|
|
|
+ // 用户授权成功
|
|
|
+ dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
+ [[UIApplication sharedApplication] registerForRemoteNotifications];
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 用户授权失败
|
|
|
+ }
|
|
|
+ }];
|
|
|
+ } else {
|
|
|
+ // Fallback on earlier versions
|
|
|
+ [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
|
|
|
+ [[UIApplication sharedApplication] registerForRemoteNotifications];
|
|
|
+ }
|
|
|
+ PKPushRegistry *registry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
|
|
|
+ registry.delegate = self;
|
|
|
+ registry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
|
|
|
+ // 将NSData转换为NSString以便于传输或存储
|
|
|
+
|
|
|
+ NSRange range = NSMakeRange(0, 16); // 例如,从索引0开始,获取前10个字节
|
|
|
+ NSData *subData1 = [deviceToken subdataWithRange:range];
|
|
|
+ range = NSMakeRange(16, 16);
|
|
|
+ NSData *subData2 = [deviceToken subdataWithRange:range];
|
|
|
+ range = NSMakeRange(24, 32);
|
|
|
+ NSString *token1=[[subData1 description] substringWithRange:range];
|
|
|
+ NSString *token2=[[subData2 description] substringWithRange:range];
|
|
|
+ NSString *token = [NSString stringWithFormat:@"%@%@",token1,token2];
|
|
|
+ NSLog(@"%@",token);
|
|
|
+ // 将token发送到你的服务器或其他需要的地方
|
|
|
+ [UDManager.shareInstance setSDManager:token key:dkpushtoken];
|
|
|
+ NSString *bgMark = [NSString stringWithFormat:@"推送token:%ld",token.length];
|
|
|
+ [Bugly reportException:[NSException exceptionWithName:bgMark reason:@"" userInfo:nil]];
|
|
|
+ if(self.isLogin){
|
|
|
+ [self updivicetoken];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark login sttate
|
|
|
+- (void)checkLoginState:(NSDictionary *)launchOptions{
|
|
|
+ [[LoginStateManager sharedManager] getUserInfo];
|
|
|
+ [LoginStateManager sharedManager].checkLoginState = ^(BOOL isLogin) {
|
|
|
+ if (isLogin) {
|
|
|
+ self.isLogin =TRUE;
|
|
|
+
|
|
|
+ [self updivicetoken];
|
|
|
+ [self updiviceVoIPtoken];
|
|
|
+ [self sartWebsocket];
|
|
|
+ [self openFMDB];
|
|
|
+ [self openMainController];
|
|
|
+ // 检查是否需要显示启动锁屏
|
|
|
+ if ([[APPLocker sharedLocker] isPasswordSet] && [[APPLocker sharedLocker] isLockEnabled]) {
|
|
|
+ [self showLockScreen];
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ self.shouldShowLock = NO;
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ [self openLoginController];
|
|
|
+ }
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+-(void)updivicetoken{
|
|
|
+ NSString *token =[UDManager.shareInstance getSDManager:dkpushtoken];
|
|
|
+ NSDictionary *usinfo = [UDManager.shareInstance getDDManager:dkuserinfo];
|
|
|
+ NSLog(@"dkpushtoken:%@",token);
|
|
|
+ NSDictionary *ud=@{
|
|
|
+ @"registrationId": token?:@"",
|
|
|
+ @"userId":usinfo[@"id"]?:@"",
|
|
|
+ @"platformType":@"i"
|
|
|
+ };
|
|
|
+ NSString *bgMark = [NSString stringWithFormat:@"上传推送token:%ld",token.length];
|
|
|
+ [Bugly reportException:[NSException exceptionWithName:bgMark reason:@"" userInfo:nil]];
|
|
|
+ [UserNetApi setUserinfo:ud succ:^(int code, NSDictionary * res) {
|
|
|
+ self->_isTokenCleared=NO;
|
|
|
+ NSData *jsonData = [NSJSONSerialization dataWithJSONObject:res options:0 error:nil];
|
|
|
+ if (!jsonData) {
|
|
|
+ NSLog(@"Got an error:");
|
|
|
+ } else {
|
|
|
+ NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
|
|
+ NSLog(@"%@", jsonString); // 输出:{"name":"John","age":25}
|
|
|
+ }
|
|
|
+ } fail:^(NSError * _Nonnull error) {
|
|
|
+ NSLog(@"--%@",error);
|
|
|
+ }];
|
|
|
+}
|
|
|
+-(void)updiviceVoIPtoken{
|
|
|
+ NSString *token =[UDManager.shareInstance getSDManager:dkvoiptoken];
|
|
|
+ NSDictionary *usinfo = [UDManager.shareInstance getDDManager:dkuserinfo];
|
|
|
+ NSLog(@"dkvoiptoken:%@",token);
|
|
|
+ NSString *bgMark = [NSString stringWithFormat:@"上传 voip 推送token:%ld",token.length];
|
|
|
+ [Bugly reportException:[NSException exceptionWithName:bgMark reason:@"" userInfo:nil]];
|
|
|
+ if([token isKindOfClass:[NSNull class]]){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ NSDictionary *ud=@{
|
|
|
+ @"voipTk": token?:@"",
|
|
|
+ @"userId":usinfo[@"id"]?:@"",
|
|
|
+ @"platformType":@"i"
|
|
|
+ };
|
|
|
+
|
|
|
+ [UserNetApi setUserinfo:ud succ:^(int code, NSDictionary * res) {
|
|
|
+ NSLog(@"updiviceVoIPtoken:%@",[res description]);
|
|
|
+ self->_isTokenCleared=NO;
|
|
|
+ } fail:^(NSError * _Nonnull error) {
|
|
|
+ NSLog(@"--%@",error);
|
|
|
+ }];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)addFriend{
|
|
|
+ NSLog(@"addFriend------------");
|
|
|
+ UITabBarController * tabbarVc = (UITabBarController *)self.window.rootViewController;
|
|
|
+ UITabBarItem *tabBarItem = tabbarVc.tabBar.items[1];
|
|
|
+ tabBarItem.badgeValue = @"";
|
|
|
+}
|
|
|
+
|
|
|
+- (void)exGroup{
|
|
|
+ NSLog(@"exGroup------------");
|
|
|
+ UITabBarController * tabbarVc = (UITabBarController *)self.window.rootViewController;
|
|
|
+ UITabBarItem *tabBarItem = tabbarVc.tabBar.items[2];
|
|
|
+ tabBarItem.badgeValue = @"";
|
|
|
+}
|
|
|
+
|
|
|
+- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
|
|
|
+ NSLog(@"Received notification: %@", userInfo);
|
|
|
+
|
|
|
+ NSDictionary *temp =userInfo[@"imMsg"];
|
|
|
+ if(temp){
|
|
|
+ if ([temp jk_hasKey:@"addFriend"]) {
|
|
|
+ [self addFriend];
|
|
|
+ }
|
|
|
+ NSDictionary *msg =temp[@"message"];
|
|
|
+ NSString *msgtype=msg[@"msgtype"];
|
|
|
+ if([msgtype isEqualToString:@"close"]){
|
|
|
+ if(self.uuid!=nil){
|
|
|
+ NSString *fromId = self.msg[@"fromId"];
|
|
|
+ if ( [fromId isEqualToString:msg[@"fromId"]]) {
|
|
|
+
|
|
|
+ [self.callProvider reportCallWithUUID:self.uuid endedAtDate:nil reason:CXCallEndedReasonDeclinedElsewhere];
|
|
|
+ self.uuid = nil;
|
|
|
+ self.msg =nil;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理推送消息,例如更新UI或处理数据等
|
|
|
+ completionHandler(UIBackgroundFetchResultNewData);
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark - PKPushRegistryDelegate
|
|
|
+- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type {
|
|
|
+ // 处理推送凭证更新,例如保存 token 到服务器
|
|
|
+ NSLog(@"Credentials updated: %@", credentials.token);
|
|
|
+ NSData *deviceToken = (NSData *)credentials.token;
|
|
|
+ NSRange range = NSMakeRange(0, 16); // 例如,从索引0开始,获取前10个字节
|
|
|
+ NSData *subData1 = [deviceToken subdataWithRange:range];
|
|
|
+ range = NSMakeRange(16, 16);
|
|
|
+ NSData *subData2 = [deviceToken subdataWithRange:range];
|
|
|
+ range = NSMakeRange(24, 32);
|
|
|
+ //NSLog(@"subData1: %@",subData1);
|
|
|
+ //NSLog(@"subData2: %@",subData2);
|
|
|
+ NSString *token1=[[subData1 description] substringWithRange:range];
|
|
|
+ NSString *token2=[[subData2 description] substringWithRange:range];
|
|
|
+ NSString *token = [NSString stringWithFormat:@"%@%@",token1,token2];
|
|
|
+ NSLog(@"%@",token);
|
|
|
+ //将token发送到你的服务器或其他需要的地方
|
|
|
+ NSString *bgMark = [NSString stringWithFormat:@"voip token:%ld",token.length];
|
|
|
+ [Bugly reportException:[NSException exceptionWithName:bgMark reason:@"" userInfo:nil]];
|
|
|
+ [UDManager.shareInstance setSDManager:token key:dkvoiptoken];
|
|
|
+ if(self.isLogin){
|
|
|
+ [self updiviceVoIPtoken];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion{
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ NSDictionary * temp =payload.dictionaryPayload;
|
|
|
+ temp =temp[@"business"];
|
|
|
+ temp=temp[@"incomingCallParams"];
|
|
|
+ NSString *name =temp[@"localizedCallerName"];
|
|
|
+ NSLog(@"name:%@",name);
|
|
|
+
|
|
|
+ temp =payload.dictionaryPayload;
|
|
|
+ temp =temp[@"imMsg"];
|
|
|
+ if(self.uuid!=nil||self.isJitsiMeet){//通知对方正忙,功能需要补上
|
|
|
+ [self isBUSYNow:temp[@"message"]];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ self.msg = temp[@"message"];
|
|
|
+ NSLog(@"self.msg-----:%@",self.msg);
|
|
|
+ CXCallUpdate * callUpdate = [[CXCallUpdate alloc]init];
|
|
|
+ callUpdate.supportsGrouping = YES;
|
|
|
+ callUpdate.supportsDTMF = YES;
|
|
|
+ callUpdate.hasVideo = YES;
|
|
|
+ callUpdate.supportsHolding = YES;
|
|
|
+ [callUpdate setLocalizedCallerName:name];
|
|
|
+ CXHandle * handle = [[CXHandle alloc]initWithType:CXHandleTypePhoneNumber value:@""];
|
|
|
+ callUpdate.remoteHandle = handle;
|
|
|
+ self.uuid = [NSUUID UUID];
|
|
|
+
|
|
|
+ [self.callProvider reportNewIncomingCallWithUUID:self.uuid update:callUpdate completion:^(NSError * _Nullable error) {
|
|
|
+ NSLog(@"%@",error);
|
|
|
+ }];
|
|
|
+
|
|
|
+ completion();
|
|
|
+}
|
|
|
+
|
|
|
+-(void)isBUSYNow:(NSDictionary *)msg{
|
|
|
+
|
|
|
+ NSDate *now = [NSDate date];
|
|
|
+ NSTimeInterval trt = [now timeIntervalSince1970];
|
|
|
+ NSInteger time = trt*1000;
|
|
|
+ NSString *strtime = [NSString stringWithFormat:@"%ld",(long)time];
|
|
|
+ NSDictionary *callMsg = @{
|
|
|
+ @"code":SendCode_WEBRTC_DFBUSY,
|
|
|
+ @"message": @{
|
|
|
+ @"chatId":msg[@"fromId"],
|
|
|
+ @"fromId":msg[@"chatId"],
|
|
|
+ @"type":@"0",
|
|
|
+ @"messageType":MessageType_DFBUSY,
|
|
|
+ @"timestamp":strtime,
|
|
|
+ @"payload":@""
|
|
|
+ }
|
|
|
+ };
|
|
|
+ NSError *error;
|
|
|
+ NSData *jsonData = [NSJSONSerialization dataWithJSONObject:callMsg options:0 error:&error];
|
|
|
+ if (!jsonData) {
|
|
|
+ NSLog(@"Got an error: %@", error);
|
|
|
+ } else {
|
|
|
+ NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
|
|
+ NSLog(@"%@", jsonString); // 输出: {"name":"John","age":25}
|
|
|
+ [GWebSocket.shareInstance sendMsg:jsonString];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark - CXProviderDelegate Methods
|
|
|
+
|
|
|
+- (void)setupCallProvider {
|
|
|
+
|
|
|
+ // 创建配置对象
|
|
|
+ CXProviderConfiguration *config = [[CXProviderConfiguration alloc] init];
|
|
|
+ config.supportsVideo = YES; // 是否支持视频通话
|
|
|
+ config.maximumCallGroups = 1; // 最大通话组数
|
|
|
+ config.maximumCallsPerCallGroup = 1; // 每个通话组的最大通话数
|
|
|
+ config.supportedHandleTypes = [[NSSet alloc] initWithObjects:[NSNumber numberWithInt:CXHandleTypeGeneric],[NSNumber numberWithInt:CXHandleTypePhoneNumber], nil];//[NSSet setWithArray:@[CXHandleTypePhoneNumber]]; // 支持的号码类型
|
|
|
+ config.iconTemplateImageData = UIImagePNGRepresentation([UIImage imageNamed:@"AppIcon"]); // 应用图标
|
|
|
+ config.ringtoneSound = @"ringtone.aiff"; // 铃声文件(可选)
|
|
|
+
|
|
|
+ // 创建CXProvider实例
|
|
|
+ self.callProvider = [[CXProvider alloc] initWithConfiguration:config];
|
|
|
+ [self.callProvider setDelegate:self queue:nil];
|
|
|
+ //self.callRoomMap = [NSMutableDictionary dictionary];
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+- (void)providerDidReset:(CXProvider *)provider {
|
|
|
+ NSLog(@"Provider reset");
|
|
|
+}
|
|
|
+
|
|
|
+- (void)provider:(CXProvider *)provider performStartCallAction:(CXStartCallAction *)action {
|
|
|
+ // 开始通话的逻辑,如连接服务器等
|
|
|
+ NSLog(@"performStartCallAction:%@",action);
|
|
|
+ [action fulfill]; // 当通话开始时调用此方法完成action
|
|
|
+}
|
|
|
+
|
|
|
+-(void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAction *)action{
|
|
|
+
|
|
|
+
|
|
|
+ [self reciveVoip];
|
|
|
+
|
|
|
+ //使用GCD创建一个在3秒后执行的定时器
|
|
|
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
|
+ NSLog(@"performAnswerCallAction:%@",action);
|
|
|
+ if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
|
|
|
+ // 应用已经解锁并且在前台
|
|
|
+ if(self.uuid){
|
|
|
+
|
|
|
+ [self.callProvider reportCallWithUUID:self.uuid endedAtDate:nil reason:CXCallEndedReasonDeclinedElsewhere];
|
|
|
+ self.msg = nil;
|
|
|
+ self.uuid = nil;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+}
|
|
|
+-(void)provider:(CXProvider *)provider timedOutPerformingAction:(CXAction *)action{
|
|
|
+
|
|
|
+ if (!self.uuid) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ [self.callProvider reportCallWithUUID:self.uuid endedAtDate:nil reason:CXCallEndedReasonDeclinedElsewhere];
|
|
|
+ self.msg = nil;
|
|
|
+ self.uuid = nil;
|
|
|
+ NSLog(@"timedOutPerformingAction:%@",action);
|
|
|
+}
|
|
|
+- (void)provider:(CXProvider *)provider performEndCallAction:(CXEndCallAction *)action {
|
|
|
+ // 挂断电话的逻辑,如断开服务器连接等
|
|
|
+ NSLog(@"performEndCallAction:%@",action);
|
|
|
+ NSDate *now = [NSDate date];
|
|
|
+ NSTimeInterval trt = [now timeIntervalSince1970];
|
|
|
+ NSInteger time = trt*1000;
|
|
|
+ NSString *strtime = [NSString stringWithFormat:@"%ld",(long)time];
|
|
|
+ NSDictionary *callMsg = @{
|
|
|
+ @"code":@"9",
|
|
|
+ @"message": @{
|
|
|
+ @"chatId":self.msg[@"fromId"],
|
|
|
+ @"fromId":self.msg[@"chatId"],
|
|
|
+ @"type":@"0",
|
|
|
+ @"msgtype":@"close",
|
|
|
+ @"timestamp":strtime,
|
|
|
+ @"payload":self.msg[@"payload"]
|
|
|
+ }
|
|
|
+ };
|
|
|
+ NSError *error;
|
|
|
+ NSData *jsonData = [NSJSONSerialization dataWithJSONObject:callMsg options:0 error:&error];
|
|
|
+ if (!jsonData) {
|
|
|
+ NSLog(@"Got an error: %@", error);
|
|
|
+ } else {
|
|
|
+ NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
|
|
+ NSLog(@"%@", jsonString); // 输出: {"name":"John","age":25}
|
|
|
+ [GWebSocket.shareInstance sendMsg:jsonString];
|
|
|
+ }
|
|
|
+ self.uuid = nil;
|
|
|
+ self.msg =nil;
|
|
|
+
|
|
|
+ [action fulfill]; // 当通话结束时调用此方法完成action
|
|
|
+}
|
|
|
+
|
|
|
+-(void)reciveVoip{
|
|
|
+ NSLog(@"reciveVoip-------------1");
|
|
|
+ if(self.msg){
|
|
|
+ NSNumber *conetType = self.msg[@"conetType"];
|
|
|
+ NSLog(@"vidio:%@",self.msg[@"payload"]);
|
|
|
+ BOOL audioOnly = YES;
|
|
|
+ if(conetType.boolValue){
|
|
|
+ audioOnly = NO;
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ audioOnly = YES;
|
|
|
+ }
|
|
|
+
|
|
|
+ [self startJSCall:self.msg[@"fromId"] room:self.msg[@"payload"] isCaller:NO audioOnly:audioOnly];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//开启悬浮窗拨打方式
|
|
|
+-(void)startJSCall:(NSString *_Nonnull)chatId room:(NSString *_Nonnull)roomId isCaller:(BOOL)isCaller audioOnly:(BOOL)audioOnly{
|
|
|
+
|
|
|
+ self.isJitsiMeet = YES;
|
|
|
+ if(_jsyuyinctr){
|
|
|
+ _jsyuyinctr.chatId = chatId.copy;
|
|
|
+ _jsyuyinctr.room = roomId.copy;
|
|
|
+ _jsyuyinctr.audioOnly = audioOnly;
|
|
|
+ _jsyuyinctr.isCaller = isCaller;
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
|
|
|
+ _jsyuyinctr = [board instantiateViewControllerWithIdentifier:@"JSGController"];
|
|
|
+ _jsyuyinctr.modalPresentationStyle = UIModalPresentationFullScreen;
|
|
|
+ _jsyuyinctr.chatId = chatId.copy;
|
|
|
+ _jsyuyinctr.room = roomId.copy;
|
|
|
+ _jsyuyinctr.audioOnly = audioOnly;
|
|
|
+ _jsyuyinctr.isCaller = isCaller;
|
|
|
+ }
|
|
|
+ NSLog(@"startJSCall roomId:%@",roomId);
|
|
|
+ [_floatWindow showView:_jsyuyinctr.view];
|
|
|
+ [_jsyuyinctr startJitsiMeetCall];
|
|
|
+ [[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];
|
|
|
+}
|
|
|
+
|
|
|
+-(void)floadinSmWindow:(NSInteger )type{
|
|
|
+ if(type!=0){
|
|
|
+ [_floatWindow viewInFload:type];
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
++(void)closeVoip{
|
|
|
+ if(app.uuid!=nil){
|
|
|
+ [app.callProvider reportCallWithUUID:app.uuid endedAtDate:nil reason:CXCallEndedReasonDeclinedElsewhere];
|
|
|
+ app.uuid = nil;
|
|
|
+ app.msg =nil;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
++(void)JitsiMeetState:(BOOL)state{
|
|
|
+ app.isJitsiMeet=state;
|
|
|
+ if(!state){
|
|
|
+ if(app.shouldShowLock){
|
|
|
+ [app showLockScreen];
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ [app.floatWindow hide];
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
++(void)unlockAPP{
|
|
|
+ app.shouldShowLock=NO;
|
|
|
+}
|
|
|
+
|
|
|
++(void)changeFloadViewState:(BOOL)state{
|
|
|
+ if (state) {
|
|
|
+ [app.floatWindow hide];
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ if ([[APPLocker sharedLocker] isPasswordSet] && [[APPLocker sharedLocker] isLockEnabled]) {
|
|
|
+ [app.floatWindow show:1];
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark 用户点击消息推送或滑动
|
|
|
+- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler {
|
|
|
+
|
|
|
+ // 处理用户对通知的响应(点击、滑动等)
|
|
|
+ if ([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) {
|
|
|
+ // 用户点击了通知
|
|
|
+ NSDictionary *userInfo = response.notification.request.content.userInfo;
|
|
|
+ [self handleNotification:userInfo];
|
|
|
+ NSLog(@"userInfo: %@", userInfo);
|
|
|
+ } else if ([response.actionIdentifier isEqualToString:@"customActionIdentifier"]) {
|
|
|
+ // 处理自定义动作(如果有的话)
|
|
|
+ }
|
|
|
+ completionHandler(); // 调用完成处理程序以结束操作
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+- (void)handleNotification:(NSDictionary *)userInfo {
|
|
|
+ NSDictionary * tempDict = userInfo[@"imMsg"];
|
|
|
+ NSDictionary * imMsg = tempDict[@"message"];
|
|
|
+ _isNotification=true;
|
|
|
+ NSMutableDictionary * mutablemsg = imMsg.mutableCopy;
|
|
|
+ NSLog(@"------mutablemsg:%@",mutablemsg);
|
|
|
+ NSDictionary * user = [UDManager.shareInstance getDDManager:dkuserinfo];
|
|
|
+ if([user[@"id"] isEqual:imMsg[@"fromId"]]){
|
|
|
+ [mutablemsg setObject:@"true" forKey:@"mine"];
|
|
|
+ }else{
|
|
|
+ if([Friendchat isEqual:imMsg[@"type"]]){
|
|
|
+ [mutablemsg setObject:imMsg[@"fromId"] forKey:@"chatId"];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (imMsg) {
|
|
|
+ if (![LoginStateManager sharedManager].isLoggedIn) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ([imMsg jk_hasKey:@"addFriend"]) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ NSString *strtype = mutablemsg[@"type"];
|
|
|
+ NSInteger type = [strtype integerValue];
|
|
|
+ NSString *chatId = mutablemsg[@"chatId"];
|
|
|
+ NSString *titlename = mutablemsg[@"fromName"]?:@"";
|
|
|
+ NSString *avatar = mutablemsg[@"fromAvatar"]?:@"";
|
|
|
+
|
|
|
+
|
|
|
+// NSLog(@"top className:%@",[[self.window jk_topMostController] class]);
|
|
|
+// NSLog(@"current className:%@",[[self.window jk_currentViewController] class]);
|
|
|
+ if ([[self.window jk_currentViewController] isKindOfClass:ChatController.class]) {
|
|
|
+ ChatController * currentChatVc = (ChatController *)[self.window jk_currentViewController];
|
|
|
+ if (![currentChatVc.chatId isEqualToString:mutablemsg[@"chatId"]]) {
|
|
|
+ currentChatVc.chatId = chatId;
|
|
|
+ currentChatVc.type = type;
|
|
|
+ currentChatVc.titlename = titlename;
|
|
|
+ currentChatVc.avatar = avatar;
|
|
|
+ [currentChatVc reloadAllData];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ currentChatVc.chatId = chatId;
|
|
|
+ currentChatVc.type = type;
|
|
|
+ currentChatVc.titlename = titlename;
|
|
|
+ currentChatVc.avatar = avatar;
|
|
|
+ [currentChatVc reloadAllData];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
|
|
|
+ ChatController *chatctr = [board instantiateViewControllerWithIdentifier:@"ChatController"];
|
|
|
+ UINavigationController *uiNavC = [[UINavigationController alloc] initWithRootViewController:chatctr];
|
|
|
+ uiNavC.modalPresentationStyle = UIModalPresentationFullScreen;
|
|
|
+ chatctr.chatId = chatId;
|
|
|
+ chatctr.type = type;
|
|
|
+ chatctr.titlename = titlename;
|
|
|
+ chatctr.avatar = avatar;
|
|
|
+ UITabBarController * tabbarVc = (UITabBarController *)self.window.rootViewController;
|
|
|
+ ChatIndexController * chatListVc = tabbarVc.viewControllers[0];
|
|
|
+ if (chatListVc) {
|
|
|
+ [chatListVc presentViewController:uiNavC animated:YES completion:nil];
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark -user state and note
|
|
|
+
|
|
|
+-(void)onLoginSucc{
|
|
|
+ self.isLogin =TRUE;
|
|
|
+ [self openFMDB];
|
|
|
+ [self openMainController];
|
|
|
+ [self updivicetoken];
|
|
|
+ [self updiviceVoIPtoken];
|
|
|
+ [self sartWebsocket];
|
|
|
+}
|
|
|
+-(void)onLogoutSucc{
|
|
|
+ self.isLogin =false;
|
|
|
+ NSLog(@"1-----------------1");
|
|
|
+// [GDBManager.shareInstance delLocalmsglistTable:userid];
|
|
|
+// [GDBManager.shareInstance delchatlistTable:nil fail:nil];
|
|
|
+// [GDBManager.shareInstance deleteDB];
|
|
|
+ [UDManager.shareInstance removeUDManager:gkeytoken];
|
|
|
+ [UDManager.shareInstance removeUDManager:dkuserloginId];
|
|
|
+ [UDManager.shareInstance removeUDManager:dkuserinfo];
|
|
|
+ [UDManager.shareInstance removeUDManager:dkuserId];
|
|
|
+ [self clearVoipToken];
|
|
|
+ [self openLoginController];
|
|
|
+ [self endWebsocket];
|
|
|
+}
|
|
|
+
|
|
|
+-(void)clearVoipToken{
|
|
|
+
|
|
|
+ NSString *voiptoken = [UDManager.shareInstance getSDManager:dkvoiptoken];
|
|
|
+ NSLog(@"voiptoken:%@",voiptoken);
|
|
|
+ if([voiptoken isKindOfClass:[NSString class]]&&voiptoken.length>10){
|
|
|
+ NSDictionary *dic = @{
|
|
|
+ @"voipTk":voiptoken
|
|
|
+ };
|
|
|
+ [UserNetApi clearVoipTk:dic succ:^(int code, NSDictionary * res) {
|
|
|
+ NSLog(@"clearVoipTk:%@",res);
|
|
|
+ self->_isTokenCleared=YES;
|
|
|
+ } fail:^(NSError * _Nonnull error) {
|
|
|
+
|
|
|
+ }];
|
|
|
+ }
|
|
|
+
|
|
|
+ NSString *pushtoken = [UDManager.shareInstance getSDManager:dkpushtoken];
|
|
|
+ NSLog(@"voiptoken:%@",pushtoken);
|
|
|
+ if([pushtoken isKindOfClass:[NSString class]]&&pushtoken.length>10){
|
|
|
+ NSDictionary *dic = @{
|
|
|
+ @"registrationId":pushtoken
|
|
|
+ };
|
|
|
+ [UserNetApi clearRegistrationId:dic succ:^(int code, NSDictionary * res) {
|
|
|
+ NSLog(@"clearRegistrationId:%@",res);
|
|
|
+ self->_isTokenCleared=YES;
|
|
|
+ } fail:^(NSError * _Nonnull error) {
|
|
|
+
|
|
|
+ }];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+#pragma mark mainControllor Manager
|
|
|
+-(void)openMainController{
|
|
|
+ NSLog(@"openMainController");
|
|
|
+ UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
|
|
|
+ UITabBarController *tbc = [board instantiateViewControllerWithIdentifier:@"GTabBarController"];
|
|
|
+ //UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:tbc];
|
|
|
+ NSArray *ctrs = tbc.viewControllers;
|
|
|
+ //------------1
|
|
|
+ UIViewController *time = ctrs[0];
|
|
|
+ // 创建一个新的 UITabBarItem
|
|
|
+ UIImage *index = [[UIImage imageNamed:@"index"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
|
|
|
+ UIImage *index_cur = [[UIImage imageNamed:@"index_cur"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
|
|
|
+ UITabBarItem *tabBarItem = [[UITabBarItem alloc] initWithTitle:NSLocalizedString(@"TabBarItem1", @"")
|
|
|
+ image:index
|
|
|
+ selectedImage:index_cur];
|
|
|
+ // 设置标签文本
|
|
|
+ tabBarItem.title = NSLocalizedString(@"TabBarItem1", @"");
|
|
|
+
|
|
|
+ // 设置标签的文本颜色
|
|
|
+ [tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateNormal];
|
|
|
+ [tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateSelected];
|
|
|
+ [time setTabBarItem:tabBarItem];
|
|
|
+ //----------------2
|
|
|
+ time = ctrs[1];
|
|
|
+ // 创建一个新的 UITabBarItem
|
|
|
+ UIImage *index1 = [[UIImage imageNamed:@"txl"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
|
|
|
+ UIImage *index_cur1 = [[UIImage imageNamed:@"txl_cur"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
|
|
|
+ UITabBarItem *tabBarItem1 = [[UITabBarItem alloc] initWithTitle:NSLocalizedString(@"TabBarItem2", @"")
|
|
|
+ image:index1
|
|
|
+ selectedImage:index_cur1];
|
|
|
+ // 设置标签文本
|
|
|
+ tabBarItem1.title = NSLocalizedString(@"TabBarItem2", @"");
|
|
|
+
|
|
|
+ // 设置标签的文本颜色
|
|
|
+ [tabBarItem1 setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateNormal];
|
|
|
+ [tabBarItem1 setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateSelected];
|
|
|
+ [time setTabBarItem:tabBarItem1];
|
|
|
+ //------------------3
|
|
|
+ time = ctrs[2];
|
|
|
+ // 创建一个新的 UITabBarItem
|
|
|
+ UIImage *index2 = [[UIImage imageNamed:@"qunzu"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
|
|
|
+ UIImage *index_cur2 = [[UIImage imageNamed:@"qunzu_cur"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
|
|
|
+ UITabBarItem *tabBarItem2 = [[UITabBarItem alloc] initWithTitle:NSLocalizedString(@"TabBarItem3", @"")
|
|
|
+ image:index2
|
|
|
+ selectedImage:index_cur2];
|
|
|
+ // 设置标签文本
|
|
|
+ tabBarItem2.title = NSLocalizedString(@"TabBarItem3", @"");
|
|
|
+
|
|
|
+ // 设置标签的文本颜色
|
|
|
+ [tabBarItem2 setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateNormal];
|
|
|
+ [tabBarItem2 setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateSelected];
|
|
|
+ [time setTabBarItem:tabBarItem2];
|
|
|
+ //------------------4
|
|
|
+ time = ctrs[3];
|
|
|
+ // 创建一个新的 UITabBarItem
|
|
|
+ UIImage *index3 = [[UIImage imageNamed:@"wode"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
|
|
|
+ UIImage *index_cur3 = [[UIImage imageNamed:@"wode_cur"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
|
|
|
+ UITabBarItem *tabBarItem3 = [[UITabBarItem alloc] initWithTitle:NSLocalizedString(@"TabBarItem4", @"")
|
|
|
+ image:index3
|
|
|
+ selectedImage:index_cur3];
|
|
|
+ // 设置标签文本
|
|
|
+ tabBarItem3.title = NSLocalizedString(@"TabBarItem4", @"");
|
|
|
+
|
|
|
+ // 设置标签的文本颜色
|
|
|
+ [tabBarItem3 setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateNormal];
|
|
|
+ [tabBarItem3 setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateSelected];
|
|
|
+ [time setTabBarItem:tabBarItem3];
|
|
|
+
|
|
|
+
|
|
|
+ self.window.rootViewController = tbc;
|
|
|
+}
|
|
|
+-(void)openLoginController{
|
|
|
+ UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
|
|
|
+ GLoginController *login = [board instantiateViewControllerWithIdentifier:@"LoginController"];
|
|
|
+ UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:login];
|
|
|
+ self.window.rootViewController = nav;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+#pragma mark openSocket
|
|
|
+
|
|
|
+-(void)sartWebsocket{
|
|
|
+ NSLog(@"----------------sartWebsocket");
|
|
|
+ [[GWebSocket shareInstance] connectWebSocket];
|
|
|
+}
|
|
|
+
|
|
|
+-(void)endWebsocket{
|
|
|
+ [[GWebSocket shareInstance] closeWebSocket];
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark init DB
|
|
|
+-(void)openFMDB{
|
|
|
+ [GDBManager.shareInstance createDatabase:^(NSArray * _Nullable array) {
|
|
|
+ [GDBManager.shareInstance createLocalMSGtable:^(NSArray * _Nullable array) {
|
|
|
+ } fail:^(NSString * _Nullable error) {
|
|
|
+ }];
|
|
|
+ [GDBManager.shareInstance createChattable:^(NSArray * _Nullable array) {
|
|
|
+ } fail:^(NSString * _Nullable error) {
|
|
|
+ }];
|
|
|
+ [GDBManager.shareInstance createLastreadtimetable:^(NSArray * _Nullable array) {
|
|
|
+ } fail:^(NSString * _Nullable error) {
|
|
|
+ }];
|
|
|
+ } fail:^(NSString * _Nullable error) {
|
|
|
+
|
|
|
+ }];
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+#pragma mark - UISceneSession lifecycle
|
|
|
+
|
|
|
+
|
|
|
+//- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
|
|
|
+// // Called when a new scene session is being created.
|
|
|
+// // Use this method to select a configuration to create the new scene with.
|
|
|
+// return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
|
|
|
+//}
|
|
|
+//
|
|
|
+//
|
|
|
+//- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions {
|
|
|
+// // Called when the user discards a scene session.
|
|
|
+// // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
|
|
|
+// // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
|
|
|
+//}
|
|
|
+
|
|
|
+
|
|
|
+#pragma mark - Core Data stack
|
|
|
+
|
|
|
+@synthesize persistentContainer = _persistentContainer;
|
|
|
+
|
|
|
+- (NSPersistentContainer *)persistentContainer {
|
|
|
+ // The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
|
|
|
+ @synchronized (self) {
|
|
|
+ if (_persistentContainer == nil) {
|
|
|
+ _persistentContainer = [[NSPersistentContainer alloc] initWithName:@"555IM"];
|
|
|
+ [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
|
|
|
+ if (error != nil) {
|
|
|
+ // Replace this implementation with code to handle the error appropriately.
|
|
|
+ // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
|
|
|
+
|
|
|
+ /*
|
|
|
+ Typical reasons for an error here include:
|
|
|
+ * The parent directory does not exist, cannot be created, or disallows writing.
|
|
|
+ * The persistent store is not accessible, due to permissions or data protection when the device is locked.
|
|
|
+ * The device is out of space.
|
|
|
+ * The store could not be migrated to the current model version.
|
|
|
+ Check the error message to determine what the actual problem was.
|
|
|
+ */
|
|
|
+ NSLog(@"Unresolved error %@, %@", error, error.userInfo);
|
|
|
+ abort();
|
|
|
+ }
|
|
|
+ }];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return _persistentContainer;
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark - Core Data Saving support
|
|
|
+
|
|
|
+- (void)saveContext {
|
|
|
+ NSManagedObjectContext *context = self.persistentContainer.viewContext;
|
|
|
+ NSError *error = nil;
|
|
|
+ if ([context hasChanges] && ![context save:&error]) {
|
|
|
+ // Replace this implementation with code to handle the error appropriately.
|
|
|
+ // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
|
|
|
+ NSLog(@"Unresolved error %@, %@", error, error.userInfo);
|
|
|
+ abort();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark 检测网络状态
|
|
|
+
|
|
|
+#pragma mark 定时服务
|
|
|
+-(void)startTimer{
|
|
|
+ _timerActCount=0;
|
|
|
+ if(self.timer){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ self.timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(TimerAction) userInfo:nil repeats:YES];
|
|
|
+ [self.timer setFireDate:[NSDate distantPast]];
|
|
|
+ [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
|
|
|
+}
|
|
|
+
|
|
|
+-(void)endTimer{
|
|
|
+ [self.timer invalidate];
|
|
|
+ self.timer = nil;
|
|
|
+}
|
|
|
+
|
|
|
+-(void)TimerAction{
|
|
|
+ _timerActCount=_timerActCount+1;
|
|
|
+ if(_timerActCount<3){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ _timerActCount=0;
|
|
|
+// NSLog(@"111222222");
|
|
|
+ if(![self isNetworkAvailable]){
|
|
|
+ if(self.isLogin){
|
|
|
+ [self onLogoutSucc];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ if(!self.isLogin){
|
|
|
+ if (!_isTokenCleared) {
|
|
|
+ [self clearVoipToken];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+-(BOOL)isNetworkAvailable{
|
|
|
+ struct sockaddr_in zeroAddress;
|
|
|
+ bzero(&zeroAddress, sizeof(zeroAddress));
|
|
|
+ zeroAddress.sin_len = sizeof(zeroAddress);
|
|
|
+ zeroAddress.sin_family = AF_INET;
|
|
|
+ SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress);
|
|
|
+ if (reachability != NULL) {
|
|
|
+ SCNetworkReachabilityFlags flags;
|
|
|
+
|
|
|
+ if (SCNetworkReachabilityGetFlags(reachability, &flags)) {
|
|
|
+ BOOL isReachable = ((flags & kSCNetworkFlagsReachable) != 0);
|
|
|
+ BOOL needsConnection = ((flags & kSCNetworkFlagsConnectionRequired) != 0);
|
|
|
+
|
|
|
+ BOOL isWWAN = (flags & kSCNetworkReachabilityFlagsIsWWAN) != 0;
|
|
|
+ if(isWWAN){
|
|
|
+ NSLog(@"isWWAN:1----------");
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ NSLog(@"isWWAN:2----------");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if ((isReachable && !needsConnection)) {
|
|
|
+ // 网络是可用的,无需连接
|
|
|
+// NSLog(@"网络是可用的,无需连接");
|
|
|
+ _NetReachable=YES;
|
|
|
+ return YES;
|
|
|
+ } else if ((isReachable && needsConnection)) {
|
|
|
+ // 网络是可用的,需要连接(例如蜂窝数据或WiFi)
|
|
|
+// NSLog(@"网络是可用的,需要连接(例如蜂窝数据或WiFi)");
|
|
|
+ _NetReachable=YES;
|
|
|
+ return YES; // 根据实际需求决定是否返回YES或NO,这里仅为示例返回YES
|
|
|
+ } else {
|
|
|
+ // 网络不可用或无法确定状态
|
|
|
+// NSLog(@"网络不可用或无法确定状态");
|
|
|
+ _NetReachable=NO;
|
|
|
+ return NO;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 无法获取网络状态标志
|
|
|
+// NSLog(@"无法获取网络状态标志");
|
|
|
+ _NetReachable=NO;
|
|
|
+ return NO; // 根据实际需求处理错误情况
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 无法创建reachability对象,可能是因为参数错误等
|
|
|
+// NSLog(@"无法创建reachability对象,可能是因为参数错误等");
|
|
|
+ _NetReachable=NO;
|
|
|
+ return NO; // 根据实际需求处理错误情况
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+-(BOOL)NetReachableState{
|
|
|
+ return _NetReachable;
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark applock
|
|
|
+- (void)showLockScreen {
|
|
|
+ // 确保在主线程执行
|
|
|
+ if (self.shouldShowLock && [[APPLocker sharedLocker] isPasswordSet] && [[APPLocker sharedLocker] isLockEnabled]) {
|
|
|
+ NSLog(@"showLockScreen--------------1");
|
|
|
+ if (self.isJitsiMeet) {
|
|
|
+ [_floatWindow viewInFload:0];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ [_floatWindow show:1];
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!self.isJitsiMeet) {
|
|
|
+ [_floatWindow hide];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)continueAppInitializationAfterUnlock {
|
|
|
+ // 这里可以添加解锁后需要执行的初始化代码
|
|
|
+ NSLog(@"应用锁验证通过,继续应用初始化");
|
|
|
+
|
|
|
+ // 例如:加载主界面数据、初始化服务等
|
|
|
+ [self openMainController];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)continueWithSecurity{
|
|
|
+ NSLog(@"-----安全登录成功-----");
|
|
|
+ [self onLoginSucc];
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+- (void)clearApplicationBadge {
|
|
|
+ dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
+ [UIApplication sharedApplication].applicationIconBadgeNumber = 1; // 先设置为1
|
|
|
+ [UIApplication sharedApplication].applicationIconBadgeNumber = 0; // 再设置为0
|
|
|
+ // 这个技巧可以确保某些情况下角标被正确清除
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+@end
|