// // AppDelegate.m // aiim // // Created by gan on 2025/2/27. // #import "AppDelegate.h" #import "UDManager.h" #import #import #import "CallKit/CallKit.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 #ifdef DEBUG #import #endif @import JitsiMeetSDK; @interface AppDelegate () @property (nonatomic, strong) CXProvider *callProvider; @property (nonatomic) NSUUID *uuid; @property (nonatomic) NSDictionary *msg; @property (strong, nonatomic) NSString *bgMark; @property (strong, nonatomic) FloatingWindow *floatWindow; @property (nonatomic, strong) JSGController * _Nullable jsyuyinctr; @property (nonatomic) BOOL isNotification; @property (nonatomic, assign) NSInteger badgeCount; @property (nonatomic, assign) NSInteger addFriendBadgeCount; @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. app = self; self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.backgroundColor = UIColor.blackColor; BOOL isLoggedIn = [LoginStateManager sharedManager].isLoggedIn; if (isLoggedIn) { [self initDataAfterLogin:YES]; } else { [self openLoginController]; } [self.window makeKeyAndVisible]; 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 registerPushright]; [self setupCallProvider]; _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]; #ifdef DEBUG //默认 [[DoraemonManager shareInstance] install]; // 或者使用传入位置,解决遮挡关键区域,减少频繁移动 //[[DoraemonManager shareInstance] installWithStartingPosition:CGPointMake(66, 66)]; #endif return YES; } -(void)applicationDidBecomeActive:(UIApplication *)application{ NSLog(@"applicationDidBecomeActive"); if(self.isLogin){ 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]]; } } } } } -(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; } } } + (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(onLogout) 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); } #pragma mark push token voip token -(void)registerPushright{ // 请求推送权限 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 { // 用户授权失败 } }]; 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]; } } -(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) { 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]); } fail:^(NSError * _Nonnull error) { NSLog(@"--%@",error); }]; } - (void)addFriend{ self.addFriendBadgeCount++; NSLog(@"addFriend------------:%ld", self.addFriendBadgeCount); [self updateTabBarBadgeValueAtIndex:1 badgeCount:self.addFriendBadgeCount]; [self sendAddFreindNotice]; [self updateApplicationIconBadgeNumber]; } - (void)sendAddFreindNotice { // 发送本地通知 UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init]; content.title = @"好友申请"; content.body = @"您收到了新的好友申请"; content.sound = [UNNotificationSound defaultSound]; content.badge = @(self.addFriendBadgeCount); content.userInfo = @{ @"addFriend":@(1) }; UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:0.1 repeats:NO]; NSString *identifier = [NSString stringWithFormat:@"FriendRequest_%@", [[NSUUID UUID] UUIDString]]; UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger]; [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { if (error) { NSLog(@"发送本地通知失败: %@", error); } else { NSLog(@"发送本地通知成功"); } }]; } - (void)updateApplicationIconBadgeNumber { NSInteger total = self.badgeCount + self.addFriendBadgeCount; if (@available(iOS 16.0, *)) { [[UNUserNotificationCenter currentNotificationCenter] setBadgeCount:total withCompletionHandler:^(NSError * _Nullable error) { if (error) { NSLog(@"设置消息未读数 error: %@", error); } }]; } else { // Fallback on earlier versions [[UIApplication sharedApplication] setApplicationIconBadgeNumber:total]; } } - (void)resetAddFriendBadgeCount { self.addFriendBadgeCount = 0; [self updateTabBarBadgeValueAtIndex:1 badgeCount:0]; [self updateApplicationIconBadgeNumber]; } - (void)resetBadgeCount { self.badgeCount = 0; [self updateApplicationIconBadgeNumber]; } - (void)updateTabBarBadgeValueAtIndex:(NSInteger)index badgeCount:(NSInteger)badgeCount { UITabBarController * tabbarVc = (UITabBarController *)self.window.rootViewController; if (![tabbarVc isKindOfClass:[UITabBarController class]]) { return; } if(index < 0 || index >= tabbarVc.tabBar.items.count){ return; } UITabBarItem *tabBarItem = tabbarVc.tabBar.items[index]; NSString *badgeValue = badgeCount > 0 ? [NSString stringWithFormat:@"%ld", badgeCount] : nil; badgeValue = badgeValue.length > 2 ? @"99+" : badgeValue; tabBarItem.badgeValue = badgeValue; } - (void)updateBadgeCount:(NSInteger)badgeCount { self.badgeCount = badgeCount; [self updateApplicationIconBadgeNumber]; } - (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 willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler { NSDictionary *userInfo = notification.request.content.userInfo; NSInteger addFriend = [[userInfo objectForKey:@"addFriend"] integerValue]; if (addFriend) { // 添加好友通知在app内也要展示 completionHandler(UNNotificationPresentationOptionList | UNNotificationPresentationOptionBanner | UNNotificationPresentationOptionSound | UNNotificationPresentationOptionBadge); } } - (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 initDataAfterLogin:NO]; } -(void)onLogout{ self.isLogin =false; [[LoginStateManager sharedManager] cleanLoginState]; [self openLoginController]; [self resetBadgeCount]; [self resetAddFriendBadgeCount]; } - (void)initDataAfterLogin:(BOOL)needRequest { self.isLogin =TRUE; [self openFMDB]; [self openMainController]; [self updivicetoken]; [self updiviceVoIPtoken]; [self sartWebsocket]; if ([[APPLocker sharedLocker] isPasswordSet] && [[APPLocker sharedLocker] isLockEnabled]) { [self showLockScreen]; } else{ self.shouldShowLock = NO; } if (needRequest) { [[LoginStateManager sharedManager] requestUserInfoWith:^(BOOL isSuccess) { }]; } } #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{ [[GWebSocket shareInstance] connectWebSocket]; } #pragma mark init DB -(void)openFMDB { [[GDBManager shareInstance] initDataBase]; } #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 *)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 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)applicationWillTerminate:(UIApplication *)application { [[OSSManager sharedManager] applicationWillTerminate]; } @end