AppDelegate.m 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117
  1. //
  2. // AppDelegate.m
  3. // aiim
  4. //
  5. // Created by gan on 2025/2/27.
  6. //
  7. #import "AppDelegate.h"
  8. #import "UDManager.h"
  9. #import <UserNotifications/UserNotifications.h>
  10. #import <PushKit/PushKit.h>
  11. #import "CallKit/CallKit.h"
  12. #import <netinet/in.h>
  13. #import <SystemConfiguration/SystemConfiguration.h>
  14. #import "UserNetApi.h"
  15. #import "CryptoAES.h"
  16. #import "GWebSocket.h"
  17. #import "GDBManager.h"
  18. #import "APPLocker.h"
  19. #import "JSGController.h"
  20. #import "LoginStateManager.h"
  21. #import "FloatingWindow.h"
  22. #import "ChatIndexController.h"
  23. #import "ChatController.h"
  24. #import "ChatListStore.h"
  25. #import "ChatsStore.h"
  26. #import "OSSManager.h"
  27. #import <Bugly/Bugly.h>
  28. #ifdef DEBUG
  29. #import <DoraemonKit/DoraemonManager.h>
  30. #endif
  31. @import JitsiMeetSDK;
  32. @interface AppDelegate ()<UNUserNotificationCenterDelegate,PKPushRegistryDelegate,CXProviderDelegate>
  33. @property (nonatomic, strong) CXProvider *callProvider;
  34. @property (nonatomic) NSUUID *uuid;
  35. @property (nonatomic) NSDictionary *msg;
  36. @property (strong, nonatomic) NSTimer *timer;
  37. @property (nonatomic) NSInteger timerActCount;
  38. @property (strong, nonatomic) NSString *bgMark;
  39. @property (nonatomic) BOOL isTokenCleared;
  40. @property (strong, nonatomic) FloatingWindow *floatWindow;
  41. @property (nonatomic, strong) JSGController * _Nullable jsyuyinctr;
  42. @property (nonatomic) BOOL isNotification;
  43. @end
  44. @implementation AppDelegate
  45. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  46. // Override point for customization after application launch.
  47. app = self;
  48. BuglyConfig *config = [[BuglyConfig alloc] init];
  49. config.reportLogLevel = BuglyLogLevelVerbose;
  50. [Bugly startWithAppId:@"1d9e6b546a" config:config];
  51. self.isJitsiMeet=false;
  52. _isNotification=false;
  53. self.shouldShowLock = YES;
  54. self.bgMark=@"";
  55. [self initJSMSDK];
  56. [self setupListener];
  57. [self checkLoginState:launchOptions];
  58. [self registerPushright];
  59. [self setupCallProvider];
  60. [self initAliyunOss];
  61. _isTokenCleared=YES;
  62. _floatWindow = [[FloatingWindow alloc] initWithFrame:self.window.bounds];
  63. [_floatWindow hide];
  64. self.bgMark = @"";
  65. NSLog(@"didFinishLaunchingWithOptions------");
  66. AVAudioSession *session = [AVAudioSession sharedInstance];
  67. [session setCategory:AVAudioSessionCategoryPlayAndRecord mode:AVAudioSessionModeVoiceChat options:AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryOptionAllowBluetoothA2DP | AVAudioSessionCategoryOptionAllowAirPlay error:nil];
  68. [session setActive:YES error:nil];
  69. #ifdef DEBUG
  70. //默认
  71. [[DoraemonManager shareInstance] install];
  72. // 或者使用传入位置,解决遮挡关键区域,减少频繁移动
  73. //[[DoraemonManager shareInstance] installWithStartingPosition:CGPointMake(66, 66)];
  74. #endif
  75. return YES;
  76. }
  77. -(void)applicationDidBecomeActive:(UIApplication *)application{
  78. NSLog(@"applicationDidBecomeActive");
  79. if(self.isLogin){
  80. [self sartWebsocket];
  81. if(self.isJitsiMeet){
  82. [_floatWindow viewInFload:0];
  83. }
  84. [self showLockScreen];
  85. if(!_isNotification){
  86. if ([[self.window jk_currentViewController] isKindOfClass:UITabBarController.class]){
  87. UITabBarController * tabbarVc= (UITabBarController *)[self.window jk_currentViewController];
  88. if (tabbarVc.selectedIndex==0) {
  89. ChatIndexController * chatListVc = tabbarVc.viewControllers[0];
  90. if (chatListVc) {
  91. [chatListVc reloadList];
  92. }
  93. }
  94. }
  95. else{
  96. [Bugly reportException:[NSException exceptionWithName:@"applicationDidBecomeActive1" reason:@"1" userInfo:nil]];
  97. if ([[self.window jk_currentViewController] isKindOfClass:ChatController.class]) {
  98. ChatController * currentChatVc = (ChatController *)[self.window jk_currentViewController];
  99. [currentChatVc reloadAllData];
  100. [Bugly reportException:[NSException exceptionWithName:@"applicationDidBecomeActive2" reason:@"2" userInfo:nil]];
  101. }
  102. }
  103. }
  104. }
  105. [self startTimer];
  106. // 应用从后台返回前台时检查是否需要显示锁屏
  107. }
  108. -(void)applicationDidEnterBackground:(UIApplication *)application{
  109. NSLog(@"applicationDidEnterBackground");
  110. _isNotification=false;
  111. // [self endWebsocket];
  112. __block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
  113. [application endBackgroundTask:bgTask];
  114. bgTask = UIBackgroundTaskInvalid;
  115. }];
  116. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  117. // 在这里保持任务运行或等待事件,例如等待来电等。
  118. [application endBackgroundTask:bgTask];
  119. bgTask = UIBackgroundTaskInvalid;
  120. });
  121. // 应用进入后台时标记需要显示锁屏
  122. if(self.isJitsiMeet == YES){
  123. [self.window endEditing:YES];
  124. }
  125. else{
  126. if ([[APPLocker sharedLocker] isPasswordSet] && [[APPLocker sharedLocker] isLockEnabled]) {
  127. self.shouldShowLock = YES;
  128. }
  129. }
  130. [self endTimer];
  131. }
  132. + (instancetype)sharedInstance {
  133. return app;
  134. }
  135. -(void)initJSMSDK{
  136. JitsiMeetConferenceOptions *defaultOptions
  137. = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
  138. builder.serverURL = [NSURL URLWithString:JitsiMeetSV];
  139. [builder setFeatureFlag:@"welcomepage.enabled" withBoolean:NO];
  140. [builder setFeatureFlag:@"prejoinPage.enabled" withBoolean:NO];
  141. //媒体流优化
  142. builder.audioMuted = NO; // 提前初始化音频模块
  143. builder.videoMuted = NO; // 提前初始化视频模块
  144. //禁用非必要功能(减少初始化负载)
  145. [builder setFeatureFlag:@"add-people.enabled" withBoolean:NO];
  146. [builder setFeatureFlag:@"invite.enabled" withBoolean:NO];
  147. [builder setFeatureFlag:@"live-streaming.enabled" withBoolean:NO];
  148. [builder setFeatureFlag:@"video-share.enabled" withBoolean:NO];
  149. [builder setFeatureFlag:@"call-integration.enabled" withBoolean:NO];
  150. [builder setFeatureFlag:@"startWithAudioMuted" withBoolean:NO];
  151. [builder setFeatureFlag:@"recording.enabled" withBoolean:NO];
  152. [builder setFeatureFlag:@"kick-out.enabled" withBoolean:NO];
  153. [builder setFeatureFlag:@"security-options.enabled" withBoolean:NO];
  154. //
  155. // //网络传输层加速
  156. // [builder setConfigOverride:@"disableSimulcast" withBoolean:YES];
  157. // [builder setFeatureFlag:@"reconnect.enabled" withBoolean:YES];
  158. // [builder setFeatureFlag:@"websocket-keep-alive.enabled" withBoolean:YES];
  159. // [builder setFeatureFlag:@"network-monitor.enabled" withBoolean:YES];
  160. // [builder setConfigOverride:@"iceTransportPolicy" withValue:@"relay"];
  161. // // 界面渲染加速
  162. // [builder setFeatureFlag:@"filmstrip.enabled" withBoolean:NO];
  163. // [builder setFeatureFlag:@"tile-view.enabled" withBoolean:NO];
  164. //
  165. // [builder setFeatureFlag:@"pip.enabled" withBoolean:NO];
  166. // [builder setFeatureFlag:@"chat.enabled" withBoolean:NO];
  167. [builder setConfigOverride:@"toolbarButtons" withArray:@[@"microphone",@"camera"]];
  168. }];
  169. [JitsiMeet sharedInstance].defaultConferenceOptions = defaultOptions;
  170. UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
  171. _jsyuyinctr = [board instantiateViewControllerWithIdentifier:@"JSGController"];
  172. _jsyuyinctr.modalPresentationStyle = UIModalPresentationFullScreen;
  173. }
  174. -(void)setupListener{
  175. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onLoginSucc) name:nkonLoginSucc object:nil];
  176. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onLogoutSucc) name:nkonLogoutSucc object:nil];
  177. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(addFriend) name:nkonAddFriendNote object:nil];;
  178. }
  179. - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
  180. NSLog(@"Failed to get token, error: %@", error);
  181. }
  182. //阿里云oss:https://abtimoss.oss-ap-southeast-1.aliyuncs.com
  183. //AccessKey ID
  184. //LTAI5tNoRjDRMuvnKBcop3hL
  185. //AccessKey Secret
  186. //kUoR7zqLafRYpcz3vJk1JHTvkRaaSl
  187. -(void)initAliyunOss{
  188. // [[OSSManager sharedManager] getOSSInfo];
  189. }
  190. #pragma mark push token voip token
  191. -(void)registerPushright{
  192. // 请求推送权限
  193. if (@available(iOS 10.0, *)) {
  194. UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
  195. center.delegate = self; // 设置代理以处理通知相关事件
  196. [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionProvidesAppNotificationSettings) completionHandler:^(BOOL granted, NSError * _Nullable error) {
  197. if (granted) {
  198. // 用户授权成功
  199. dispatch_async(dispatch_get_main_queue(), ^{
  200. [[UIApplication sharedApplication] registerForRemoteNotifications];
  201. });
  202. } else {
  203. // 用户授权失败
  204. }
  205. }];
  206. } else {
  207. // Fallback on earlier versions
  208. [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
  209. [[UIApplication sharedApplication] registerForRemoteNotifications];
  210. }
  211. PKPushRegistry *registry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
  212. registry.delegate = self;
  213. registry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
  214. }
  215. - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  216. // 将NSData转换为NSString以便于传输或存储
  217. NSRange range = NSMakeRange(0, 16); // 例如,从索引0开始,获取前10个字节
  218. NSData *subData1 = [deviceToken subdataWithRange:range];
  219. range = NSMakeRange(16, 16);
  220. NSData *subData2 = [deviceToken subdataWithRange:range];
  221. range = NSMakeRange(24, 32);
  222. NSString *token1=[[subData1 description] substringWithRange:range];
  223. NSString *token2=[[subData2 description] substringWithRange:range];
  224. NSString *token = [NSString stringWithFormat:@"%@%@",token1,token2];
  225. NSLog(@"%@",token);
  226. // 将token发送到你的服务器或其他需要的地方
  227. [UDManager.shareInstance setSDManager:token key:dkpushtoken];
  228. NSString *bgMark = [NSString stringWithFormat:@"推送token:%ld",token.length];
  229. [Bugly reportException:[NSException exceptionWithName:bgMark reason:@"" userInfo:nil]];
  230. if(self.isLogin){
  231. [self updivicetoken];
  232. }
  233. }
  234. #pragma mark login sttate
  235. - (void)checkLoginState:(NSDictionary *)launchOptions{
  236. [[LoginStateManager sharedManager] getUserInfo];
  237. [LoginStateManager sharedManager].checkLoginState = ^(BOOL isLogin) {
  238. if (isLogin) {
  239. self.isLogin =TRUE;
  240. [self updivicetoken];
  241. [self updiviceVoIPtoken];
  242. [self sartWebsocket];
  243. [self openFMDB];
  244. [self openMainController];
  245. // 检查是否需要显示启动锁屏
  246. if ([[APPLocker sharedLocker] isPasswordSet] && [[APPLocker sharedLocker] isLockEnabled]) {
  247. [self showLockScreen];
  248. }
  249. else{
  250. self.shouldShowLock = NO;
  251. }
  252. }else{
  253. [self openLoginController];
  254. }
  255. };
  256. }
  257. -(void)updivicetoken{
  258. NSString *token =[UDManager.shareInstance getSDManager:dkpushtoken];
  259. NSDictionary *usinfo = [UDManager.shareInstance getDDManager:dkuserinfo];
  260. NSLog(@"dkpushtoken:%@",token);
  261. NSDictionary *ud=@{
  262. @"registrationId": token?:@"",
  263. @"userId":usinfo[@"id"]?:@"",
  264. @"platformType":@"i"
  265. };
  266. NSString *bgMark = [NSString stringWithFormat:@"上传推送token:%ld",token.length];
  267. [Bugly reportException:[NSException exceptionWithName:bgMark reason:@"" userInfo:nil]];
  268. [UserNetApi setUserinfo:ud succ:^(int code, NSDictionary * res) {
  269. self->_isTokenCleared=NO;
  270. NSData *jsonData = [NSJSONSerialization dataWithJSONObject:res options:0 error:nil];
  271. if (!jsonData) {
  272. NSLog(@"Got an error:");
  273. } else {
  274. NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
  275. NSLog(@"%@", jsonString); // 输出:{"name":"John","age":25}
  276. }
  277. } fail:^(NSError * _Nonnull error) {
  278. NSLog(@"--%@",error);
  279. }];
  280. }
  281. -(void)updiviceVoIPtoken{
  282. NSString *token =[UDManager.shareInstance getSDManager:dkvoiptoken];
  283. NSDictionary *usinfo = [UDManager.shareInstance getDDManager:dkuserinfo];
  284. NSLog(@"dkvoiptoken:%@",token);
  285. NSString *bgMark = [NSString stringWithFormat:@"上传 voip 推送token:%ld",token.length];
  286. [Bugly reportException:[NSException exceptionWithName:bgMark reason:@"" userInfo:nil]];
  287. if([token isKindOfClass:[NSNull class]]){
  288. return;
  289. }
  290. NSDictionary *ud=@{
  291. @"voipTk": token?:@"",
  292. @"userId":usinfo[@"id"]?:@"",
  293. @"platformType":@"i"
  294. };
  295. [UserNetApi setUserinfo:ud succ:^(int code, NSDictionary * res) {
  296. NSLog(@"updiviceVoIPtoken:%@",[res description]);
  297. self->_isTokenCleared=NO;
  298. } fail:^(NSError * _Nonnull error) {
  299. NSLog(@"--%@",error);
  300. }];
  301. }
  302. - (void)addFriend{
  303. NSLog(@"addFriend------------");
  304. UITabBarController * tabbarVc = (UITabBarController *)self.window.rootViewController;
  305. UITabBarItem *tabBarItem = tabbarVc.tabBar.items[1];
  306. tabBarItem.badgeValue = @"";
  307. }
  308. - (void)exGroup{
  309. NSLog(@"exGroup------------");
  310. UITabBarController * tabbarVc = (UITabBarController *)self.window.rootViewController;
  311. UITabBarItem *tabBarItem = tabbarVc.tabBar.items[2];
  312. tabBarItem.badgeValue = @"";
  313. }
  314. - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  315. NSLog(@"Received notification: %@", userInfo);
  316. NSDictionary *temp =userInfo[@"imMsg"];
  317. if(temp){
  318. if ([temp jk_hasKey:@"addFriend"]) {
  319. [self addFriend];
  320. }
  321. NSDictionary *msg =temp[@"message"];
  322. NSString *msgtype=msg[@"msgtype"];
  323. if([msgtype isEqualToString:@"close"]){
  324. if(self.uuid!=nil){
  325. NSString *fromId = self.msg[@"fromId"];
  326. if ( [fromId isEqualToString:msg[@"fromId"]]) {
  327. [self.callProvider reportCallWithUUID:self.uuid endedAtDate:nil reason:CXCallEndedReasonDeclinedElsewhere];
  328. self.uuid = nil;
  329. self.msg =nil;
  330. }
  331. }
  332. }
  333. }
  334. // 处理推送消息,例如更新UI或处理数据等
  335. completionHandler(UIBackgroundFetchResultNewData);
  336. }
  337. #pragma mark - PKPushRegistryDelegate
  338. - (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type {
  339. // 处理推送凭证更新,例如保存 token 到服务器
  340. NSLog(@"Credentials updated: %@", credentials.token);
  341. NSData *deviceToken = (NSData *)credentials.token;
  342. NSRange range = NSMakeRange(0, 16); // 例如,从索引0开始,获取前10个字节
  343. NSData *subData1 = [deviceToken subdataWithRange:range];
  344. range = NSMakeRange(16, 16);
  345. NSData *subData2 = [deviceToken subdataWithRange:range];
  346. range = NSMakeRange(24, 32);
  347. //NSLog(@"subData1: %@",subData1);
  348. //NSLog(@"subData2: %@",subData2);
  349. NSString *token1=[[subData1 description] substringWithRange:range];
  350. NSString *token2=[[subData2 description] substringWithRange:range];
  351. NSString *token = [NSString stringWithFormat:@"%@%@",token1,token2];
  352. NSLog(@"%@",token);
  353. //将token发送到你的服务器或其他需要的地方
  354. NSString *bgMark = [NSString stringWithFormat:@"voip token:%ld",token.length];
  355. [Bugly reportException:[NSException exceptionWithName:bgMark reason:@"" userInfo:nil]];
  356. [UDManager.shareInstance setSDManager:token key:dkvoiptoken];
  357. if(self.isLogin){
  358. [self updiviceVoIPtoken];
  359. }
  360. }
  361. - (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion{
  362. NSDictionary * temp =payload.dictionaryPayload;
  363. temp =temp[@"business"];
  364. temp=temp[@"incomingCallParams"];
  365. NSString *name =temp[@"localizedCallerName"];
  366. NSLog(@"name:%@",name);
  367. temp =payload.dictionaryPayload;
  368. temp =temp[@"imMsg"];
  369. if(self.uuid!=nil||self.isJitsiMeet){//通知对方正忙,功能需要补上
  370. [self isBUSYNow:temp[@"message"]];
  371. return;
  372. }
  373. self.msg = temp[@"message"];
  374. NSLog(@"self.msg-----:%@",self.msg);
  375. CXCallUpdate * callUpdate = [[CXCallUpdate alloc]init];
  376. callUpdate.supportsGrouping = YES;
  377. callUpdate.supportsDTMF = YES;
  378. callUpdate.hasVideo = YES;
  379. callUpdate.supportsHolding = YES;
  380. [callUpdate setLocalizedCallerName:name];
  381. CXHandle * handle = [[CXHandle alloc]initWithType:CXHandleTypePhoneNumber value:@""];
  382. callUpdate.remoteHandle = handle;
  383. self.uuid = [NSUUID UUID];
  384. [self.callProvider reportNewIncomingCallWithUUID:self.uuid update:callUpdate completion:^(NSError * _Nullable error) {
  385. NSLog(@"%@",error);
  386. }];
  387. completion();
  388. }
  389. -(void)isBUSYNow:(NSDictionary *)msg{
  390. NSDate *now = [NSDate date];
  391. NSTimeInterval trt = [now timeIntervalSince1970];
  392. NSInteger time = trt*1000;
  393. NSString *strtime = [NSString stringWithFormat:@"%ld",(long)time];
  394. NSDictionary *callMsg = @{
  395. @"code":SendCode_WEBRTC_DFBUSY,
  396. @"message": @{
  397. @"chatId":msg[@"fromId"],
  398. @"fromId":msg[@"chatId"],
  399. @"type":@"0",
  400. @"messageType":MessageType_DFBUSY,
  401. @"timestamp":strtime,
  402. @"payload":@""
  403. }
  404. };
  405. NSError *error;
  406. NSData *jsonData = [NSJSONSerialization dataWithJSONObject:callMsg options:0 error:&error];
  407. if (!jsonData) {
  408. NSLog(@"Got an error: %@", error);
  409. } else {
  410. NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
  411. NSLog(@"%@", jsonString); // 输出: {"name":"John","age":25}
  412. [GWebSocket.shareInstance sendMsg:jsonString];
  413. }
  414. }
  415. #pragma mark - CXProviderDelegate Methods
  416. - (void)setupCallProvider {
  417. // 创建配置对象
  418. CXProviderConfiguration *config = [[CXProviderConfiguration alloc] init];
  419. config.supportsVideo = YES; // 是否支持视频通话
  420. config.maximumCallGroups = 1; // 最大通话组数
  421. config.maximumCallsPerCallGroup = 1; // 每个通话组的最大通话数
  422. config.supportedHandleTypes = [[NSSet alloc] initWithObjects:[NSNumber numberWithInt:CXHandleTypeGeneric],[NSNumber numberWithInt:CXHandleTypePhoneNumber], nil];//[NSSet setWithArray:@[CXHandleTypePhoneNumber]]; // 支持的号码类型
  423. config.iconTemplateImageData = UIImagePNGRepresentation([UIImage imageNamed:@"AppIcon"]); // 应用图标
  424. config.ringtoneSound = @"ringtone.aiff"; // 铃声文件(可选)
  425. // 创建CXProvider实例
  426. self.callProvider = [[CXProvider alloc] initWithConfiguration:config];
  427. [self.callProvider setDelegate:self queue:nil];
  428. //self.callRoomMap = [NSMutableDictionary dictionary];
  429. }
  430. - (void)providerDidReset:(CXProvider *)provider {
  431. NSLog(@"Provider reset");
  432. }
  433. - (void)provider:(CXProvider *)provider performStartCallAction:(CXStartCallAction *)action {
  434. // 开始通话的逻辑,如连接服务器等
  435. NSLog(@"performStartCallAction:%@",action);
  436. [action fulfill]; // 当通话开始时调用此方法完成action
  437. }
  438. -(void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAction *)action{
  439. [self reciveVoip];
  440. //使用GCD创建一个在3秒后执行的定时器
  441. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  442. NSLog(@"performAnswerCallAction:%@",action);
  443. if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
  444. // 应用已经解锁并且在前台
  445. if(self.uuid){
  446. [self.callProvider reportCallWithUUID:self.uuid endedAtDate:nil reason:CXCallEndedReasonDeclinedElsewhere];
  447. self.msg = nil;
  448. self.uuid = nil;
  449. }
  450. }
  451. });
  452. }
  453. -(void)provider:(CXProvider *)provider timedOutPerformingAction:(CXAction *)action{
  454. if (!self.uuid) {
  455. return;
  456. }
  457. [self.callProvider reportCallWithUUID:self.uuid endedAtDate:nil reason:CXCallEndedReasonDeclinedElsewhere];
  458. self.msg = nil;
  459. self.uuid = nil;
  460. NSLog(@"timedOutPerformingAction:%@",action);
  461. }
  462. - (void)provider:(CXProvider *)provider performEndCallAction:(CXEndCallAction *)action {
  463. // 挂断电话的逻辑,如断开服务器连接等
  464. NSLog(@"performEndCallAction:%@",action);
  465. NSDate *now = [NSDate date];
  466. NSTimeInterval trt = [now timeIntervalSince1970];
  467. NSInteger time = trt*1000;
  468. NSString *strtime = [NSString stringWithFormat:@"%ld",(long)time];
  469. NSDictionary *callMsg = @{
  470. @"code":@"9",
  471. @"message": @{
  472. @"chatId":self.msg[@"fromId"],
  473. @"fromId":self.msg[@"chatId"],
  474. @"type":@"0",
  475. @"msgtype":@"close",
  476. @"timestamp":strtime,
  477. @"payload":self.msg[@"payload"]
  478. }
  479. };
  480. NSError *error;
  481. NSData *jsonData = [NSJSONSerialization dataWithJSONObject:callMsg options:0 error:&error];
  482. if (!jsonData) {
  483. NSLog(@"Got an error: %@", error);
  484. } else {
  485. NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
  486. NSLog(@"%@", jsonString); // 输出: {"name":"John","age":25}
  487. [GWebSocket.shareInstance sendMsg:jsonString];
  488. }
  489. self.uuid = nil;
  490. self.msg =nil;
  491. [action fulfill]; // 当通话结束时调用此方法完成action
  492. }
  493. -(void)reciveVoip{
  494. NSLog(@"reciveVoip-------------1");
  495. if(self.msg){
  496. NSNumber *conetType = self.msg[@"conetType"];
  497. NSLog(@"vidio:%@",self.msg[@"payload"]);
  498. BOOL audioOnly = YES;
  499. if(conetType.boolValue){
  500. audioOnly = NO;
  501. }
  502. else{
  503. audioOnly = YES;
  504. }
  505. [self startJSCall:self.msg[@"fromId"] room:self.msg[@"payload"] isCaller:NO audioOnly:audioOnly];
  506. }
  507. }
  508. //开启悬浮窗拨打方式
  509. -(void)startJSCall:(NSString *_Nonnull)chatId room:(NSString *_Nonnull)roomId isCaller:(BOOL)isCaller audioOnly:(BOOL)audioOnly{
  510. self.isJitsiMeet = YES;
  511. if(_jsyuyinctr){
  512. _jsyuyinctr.chatId = chatId.copy;
  513. _jsyuyinctr.room = roomId.copy;
  514. _jsyuyinctr.audioOnly = audioOnly;
  515. _jsyuyinctr.isCaller = isCaller;
  516. }
  517. else{
  518. UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
  519. _jsyuyinctr = [board instantiateViewControllerWithIdentifier:@"JSGController"];
  520. _jsyuyinctr.modalPresentationStyle = UIModalPresentationFullScreen;
  521. _jsyuyinctr.chatId = chatId.copy;
  522. _jsyuyinctr.room = roomId.copy;
  523. _jsyuyinctr.audioOnly = audioOnly;
  524. _jsyuyinctr.isCaller = isCaller;
  525. }
  526. NSLog(@"startJSCall roomId:%@",roomId);
  527. [_floatWindow showView:_jsyuyinctr.view];
  528. [_jsyuyinctr startJitsiMeetCall];
  529. [[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];
  530. }
  531. -(void)floadinSmWindow:(NSInteger )type{
  532. if(type!=0){
  533. [_floatWindow viewInFload:type];
  534. }
  535. }
  536. +(void)closeVoip{
  537. if(app.uuid!=nil){
  538. [app.callProvider reportCallWithUUID:app.uuid endedAtDate:nil reason:CXCallEndedReasonDeclinedElsewhere];
  539. app.uuid = nil;
  540. app.msg =nil;
  541. }
  542. }
  543. +(void)JitsiMeetState:(BOOL)state{
  544. app.isJitsiMeet=state;
  545. if(!state){
  546. if(app.shouldShowLock){
  547. [app showLockScreen];
  548. }
  549. else{
  550. [app.floatWindow hide];
  551. }
  552. }
  553. }
  554. +(void)unlockAPP{
  555. app.shouldShowLock=NO;
  556. }
  557. +(void)changeFloadViewState:(BOOL)state{
  558. if (state) {
  559. [app.floatWindow hide];
  560. }
  561. else{
  562. if ([[APPLocker sharedLocker] isPasswordSet] && [[APPLocker sharedLocker] isLockEnabled]) {
  563. [app.floatWindow show:1];
  564. }
  565. }
  566. }
  567. #pragma mark 用户点击消息推送或滑动
  568. - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler {
  569. // 处理用户对通知的响应(点击、滑动等)
  570. if ([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) {
  571. // 用户点击了通知
  572. NSDictionary *userInfo = response.notification.request.content.userInfo;
  573. [self handleNotification:userInfo];
  574. NSLog(@"userInfo: %@", userInfo);
  575. } else if ([response.actionIdentifier isEqualToString:@"customActionIdentifier"]) {
  576. // 处理自定义动作(如果有的话)
  577. }
  578. completionHandler(); // 调用完成处理程序以结束操作
  579. }
  580. - (void)handleNotification:(NSDictionary *)userInfo {
  581. NSDictionary * tempDict = userInfo[@"imMsg"];
  582. NSDictionary * imMsg = tempDict[@"message"];
  583. _isNotification=true;
  584. NSMutableDictionary * mutablemsg = imMsg.mutableCopy;
  585. NSLog(@"------mutablemsg:%@",mutablemsg);
  586. NSDictionary * user = [UDManager.shareInstance getDDManager:dkuserinfo];
  587. if([user[@"id"] isEqual:imMsg[@"fromId"]]){
  588. [mutablemsg setObject:@"true" forKey:@"mine"];
  589. }else{
  590. if([Friendchat isEqual:imMsg[@"type"]]){
  591. [mutablemsg setObject:imMsg[@"fromId"] forKey:@"chatId"];
  592. }
  593. }
  594. if (imMsg) {
  595. if (![LoginStateManager sharedManager].isLoggedIn) {
  596. return;
  597. }
  598. if ([imMsg jk_hasKey:@"addFriend"]) {
  599. return;
  600. }
  601. NSString *strtype = mutablemsg[@"type"];
  602. NSInteger type = [strtype integerValue];
  603. NSString *chatId = mutablemsg[@"chatId"];
  604. NSString *titlename = mutablemsg[@"fromName"]?:@"";
  605. NSString *avatar = mutablemsg[@"fromAvatar"]?:@"";
  606. // NSLog(@"top className:%@",[[self.window jk_topMostController] class]);
  607. // NSLog(@"current className:%@",[[self.window jk_currentViewController] class]);
  608. if ([[self.window jk_currentViewController] isKindOfClass:ChatController.class]) {
  609. ChatController * currentChatVc = (ChatController *)[self.window jk_currentViewController];
  610. if (![currentChatVc.chatId isEqualToString:mutablemsg[@"chatId"]]) {
  611. currentChatVc.chatId = chatId;
  612. currentChatVc.type = type;
  613. currentChatVc.titlename = titlename;
  614. currentChatVc.avatar = avatar;
  615. [currentChatVc reloadAllData];
  616. return;
  617. }
  618. else{
  619. currentChatVc.chatId = chatId;
  620. currentChatVc.type = type;
  621. currentChatVc.titlename = titlename;
  622. currentChatVc.avatar = avatar;
  623. [currentChatVc reloadAllData];
  624. return;
  625. }
  626. }
  627. UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
  628. ChatController *chatctr = [board instantiateViewControllerWithIdentifier:@"ChatController"];
  629. UINavigationController *uiNavC = [[UINavigationController alloc] initWithRootViewController:chatctr];
  630. uiNavC.modalPresentationStyle = UIModalPresentationFullScreen;
  631. chatctr.chatId = chatId;
  632. chatctr.type = type;
  633. chatctr.titlename = titlename;
  634. chatctr.avatar = avatar;
  635. UITabBarController * tabbarVc = (UITabBarController *)self.window.rootViewController;
  636. ChatIndexController * chatListVc = tabbarVc.viewControllers[0];
  637. if (chatListVc) {
  638. [chatListVc presentViewController:uiNavC animated:YES completion:nil];
  639. }
  640. }
  641. }
  642. #pragma mark -user state and note
  643. -(void)onLoginSucc{
  644. self.isLogin =TRUE;
  645. [self openFMDB];
  646. [self openMainController];
  647. [self updivicetoken];
  648. [self updiviceVoIPtoken];
  649. [self sartWebsocket];
  650. }
  651. -(void)onLogoutSucc{
  652. self.isLogin =false;
  653. NSLog(@"1-----------------1");
  654. // [GDBManager.shareInstance delLocalmsglistTable:userid];
  655. // [GDBManager.shareInstance delchatlistTable:nil fail:nil];
  656. // [GDBManager.shareInstance deleteDB];
  657. [UDManager.shareInstance removeUDManager:gkeytoken];
  658. [UDManager.shareInstance removeUDManager:dkuserloginId];
  659. [UDManager.shareInstance removeUDManager:dkuserinfo];
  660. [UDManager.shareInstance removeUDManager:dkuserId];
  661. [self clearVoipToken];
  662. [self openLoginController];
  663. [self endWebsocket];
  664. }
  665. -(void)clearVoipToken{
  666. NSString *voiptoken = [UDManager.shareInstance getSDManager:dkvoiptoken];
  667. NSLog(@"voiptoken:%@",voiptoken);
  668. if([voiptoken isKindOfClass:[NSString class]]&&voiptoken.length>10){
  669. NSDictionary *dic = @{
  670. @"voipTk":voiptoken
  671. };
  672. [UserNetApi clearVoipTk:dic succ:^(int code, NSDictionary * res) {
  673. NSLog(@"clearVoipTk:%@",res);
  674. self->_isTokenCleared=YES;
  675. } fail:^(NSError * _Nonnull error) {
  676. }];
  677. }
  678. NSString *pushtoken = [UDManager.shareInstance getSDManager:dkpushtoken];
  679. NSLog(@"voiptoken:%@",pushtoken);
  680. if([pushtoken isKindOfClass:[NSString class]]&&pushtoken.length>10){
  681. NSDictionary *dic = @{
  682. @"registrationId":pushtoken
  683. };
  684. [UserNetApi clearRegistrationId:dic succ:^(int code, NSDictionary * res) {
  685. NSLog(@"clearRegistrationId:%@",res);
  686. self->_isTokenCleared=YES;
  687. } fail:^(NSError * _Nonnull error) {
  688. }];
  689. }
  690. }
  691. #pragma mark mainControllor Manager
  692. -(void)openMainController{
  693. NSLog(@"openMainController");
  694. UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
  695. UITabBarController *tbc = [board instantiateViewControllerWithIdentifier:@"GTabBarController"];
  696. //UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:tbc];
  697. NSArray *ctrs = tbc.viewControllers;
  698. //------------1
  699. UIViewController *time = ctrs[0];
  700. // 创建一个新的 UITabBarItem
  701. UIImage *index = [[UIImage imageNamed:@"index"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
  702. UIImage *index_cur = [[UIImage imageNamed:@"index_cur"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
  703. UITabBarItem *tabBarItem = [[UITabBarItem alloc] initWithTitle:NSLocalizedString(@"TabBarItem1", @"")
  704. image:index
  705. selectedImage:index_cur];
  706. // 设置标签文本
  707. tabBarItem.title = NSLocalizedString(@"TabBarItem1", @"");
  708. // 设置标签的文本颜色
  709. [tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateNormal];
  710. [tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateSelected];
  711. [time setTabBarItem:tabBarItem];
  712. //----------------2
  713. time = ctrs[1];
  714. // 创建一个新的 UITabBarItem
  715. UIImage *index1 = [[UIImage imageNamed:@"txl"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
  716. UIImage *index_cur1 = [[UIImage imageNamed:@"txl_cur"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
  717. UITabBarItem *tabBarItem1 = [[UITabBarItem alloc] initWithTitle:NSLocalizedString(@"TabBarItem2", @"")
  718. image:index1
  719. selectedImage:index_cur1];
  720. // 设置标签文本
  721. tabBarItem1.title = NSLocalizedString(@"TabBarItem2", @"");
  722. // 设置标签的文本颜色
  723. [tabBarItem1 setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateNormal];
  724. [tabBarItem1 setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateSelected];
  725. [time setTabBarItem:tabBarItem1];
  726. //------------------3
  727. time = ctrs[2];
  728. // 创建一个新的 UITabBarItem
  729. UIImage *index2 = [[UIImage imageNamed:@"qunzu"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
  730. UIImage *index_cur2 = [[UIImage imageNamed:@"qunzu_cur"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
  731. UITabBarItem *tabBarItem2 = [[UITabBarItem alloc] initWithTitle:NSLocalizedString(@"TabBarItem3", @"")
  732. image:index2
  733. selectedImage:index_cur2];
  734. // 设置标签文本
  735. tabBarItem2.title = NSLocalizedString(@"TabBarItem3", @"");
  736. // 设置标签的文本颜色
  737. [tabBarItem2 setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateNormal];
  738. [tabBarItem2 setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateSelected];
  739. [time setTabBarItem:tabBarItem2];
  740. //------------------4
  741. time = ctrs[3];
  742. // 创建一个新的 UITabBarItem
  743. UIImage *index3 = [[UIImage imageNamed:@"wode"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
  744. UIImage *index_cur3 = [[UIImage imageNamed:@"wode_cur"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
  745. UITabBarItem *tabBarItem3 = [[UITabBarItem alloc] initWithTitle:NSLocalizedString(@"TabBarItem4", @"")
  746. image:index3
  747. selectedImage:index_cur3];
  748. // 设置标签文本
  749. tabBarItem3.title = NSLocalizedString(@"TabBarItem4", @"");
  750. // 设置标签的文本颜色
  751. [tabBarItem3 setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateNormal];
  752. [tabBarItem3 setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} forState:UIControlStateSelected];
  753. [time setTabBarItem:tabBarItem3];
  754. self.window.rootViewController = tbc;
  755. }
  756. -(void)openLoginController{
  757. UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
  758. GLoginController *login = [board instantiateViewControllerWithIdentifier:@"LoginController"];
  759. UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:login];
  760. self.window.rootViewController = nav;
  761. }
  762. #pragma mark openSocket
  763. -(void)sartWebsocket{
  764. NSLog(@"----------------sartWebsocket");
  765. [[GWebSocket shareInstance] connectWebSocket];
  766. }
  767. -(void)endWebsocket{
  768. [[GWebSocket shareInstance] closeWebSocket];
  769. }
  770. #pragma mark init DB
  771. -(void)openFMDB{
  772. [GDBManager.shareInstance createDatabase:^(NSArray * _Nullable array) {
  773. [GDBManager.shareInstance createLocalMSGtable:^(NSArray * _Nullable array) {
  774. } fail:^(NSString * _Nullable error) {
  775. }];
  776. [GDBManager.shareInstance createChattable:^(NSArray * _Nullable array) {
  777. } fail:^(NSString * _Nullable error) {
  778. }];
  779. [GDBManager.shareInstance createLastreadtimetable:^(NSArray * _Nullable array) {
  780. } fail:^(NSString * _Nullable error) {
  781. }];
  782. } fail:^(NSString * _Nullable error) {
  783. }];
  784. }
  785. #pragma mark - UISceneSession lifecycle
  786. //- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
  787. // // Called when a new scene session is being created.
  788. // // Use this method to select a configuration to create the new scene with.
  789. // return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
  790. //}
  791. //
  792. //
  793. //- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions {
  794. // // Called when the user discards a scene session.
  795. // // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
  796. // // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
  797. //}
  798. #pragma mark - Core Data stack
  799. @synthesize persistentContainer = _persistentContainer;
  800. - (NSPersistentContainer *)persistentContainer {
  801. // The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
  802. @synchronized (self) {
  803. if (_persistentContainer == nil) {
  804. _persistentContainer = [[NSPersistentContainer alloc] initWithName:@"555IM"];
  805. [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
  806. if (error != nil) {
  807. // Replace this implementation with code to handle the error appropriately.
  808. // 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.
  809. /*
  810. Typical reasons for an error here include:
  811. * The parent directory does not exist, cannot be created, or disallows writing.
  812. * The persistent store is not accessible, due to permissions or data protection when the device is locked.
  813. * The device is out of space.
  814. * The store could not be migrated to the current model version.
  815. Check the error message to determine what the actual problem was.
  816. */
  817. NSLog(@"Unresolved error %@, %@", error, error.userInfo);
  818. abort();
  819. }
  820. }];
  821. }
  822. }
  823. return _persistentContainer;
  824. }
  825. #pragma mark - Core Data Saving support
  826. - (void)saveContext {
  827. NSManagedObjectContext *context = self.persistentContainer.viewContext;
  828. NSError *error = nil;
  829. if ([context hasChanges] && ![context save:&error]) {
  830. // Replace this implementation with code to handle the error appropriately.
  831. // 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.
  832. NSLog(@"Unresolved error %@, %@", error, error.userInfo);
  833. abort();
  834. }
  835. }
  836. #pragma mark 检测网络状态
  837. #pragma mark 定时服务
  838. -(void)startTimer{
  839. _timerActCount=0;
  840. if(self.timer){
  841. return;
  842. }
  843. self.timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(TimerAction) userInfo:nil repeats:YES];
  844. [self.timer setFireDate:[NSDate distantPast]];
  845. [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
  846. }
  847. -(void)endTimer{
  848. [self.timer invalidate];
  849. self.timer = nil;
  850. }
  851. -(void)TimerAction{
  852. _timerActCount=_timerActCount+1;
  853. if(_timerActCount<3){
  854. return;
  855. }
  856. _timerActCount=0;
  857. // NSLog(@"111222222");
  858. if(![self isNetworkAvailable]){
  859. if(self.isLogin){
  860. [self onLogoutSucc];
  861. }
  862. }
  863. else{
  864. if(!self.isLogin){
  865. if (!_isTokenCleared) {
  866. [self clearVoipToken];
  867. }
  868. }
  869. }
  870. }
  871. -(BOOL)isNetworkAvailable{
  872. struct sockaddr_in zeroAddress;
  873. bzero(&zeroAddress, sizeof(zeroAddress));
  874. zeroAddress.sin_len = sizeof(zeroAddress);
  875. zeroAddress.sin_family = AF_INET;
  876. SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress);
  877. if (reachability != NULL) {
  878. SCNetworkReachabilityFlags flags;
  879. if (SCNetworkReachabilityGetFlags(reachability, &flags)) {
  880. BOOL isReachable = ((flags & kSCNetworkFlagsReachable) != 0);
  881. BOOL needsConnection = ((flags & kSCNetworkFlagsConnectionRequired) != 0);
  882. BOOL isWWAN = (flags & kSCNetworkReachabilityFlagsIsWWAN) != 0;
  883. if(isWWAN){
  884. NSLog(@"isWWAN:1----------");
  885. }
  886. else{
  887. NSLog(@"isWWAN:2----------");
  888. }
  889. if ((isReachable && !needsConnection)) {
  890. // 网络是可用的,无需连接
  891. // NSLog(@"网络是可用的,无需连接");
  892. _NetReachable=YES;
  893. return YES;
  894. } else if ((isReachable && needsConnection)) {
  895. // 网络是可用的,需要连接(例如蜂窝数据或WiFi)
  896. // NSLog(@"网络是可用的,需要连接(例如蜂窝数据或WiFi)");
  897. _NetReachable=YES;
  898. return YES; // 根据实际需求决定是否返回YES或NO,这里仅为示例返回YES
  899. } else {
  900. // 网络不可用或无法确定状态
  901. // NSLog(@"网络不可用或无法确定状态");
  902. _NetReachable=NO;
  903. return NO;
  904. }
  905. } else {
  906. // 无法获取网络状态标志
  907. // NSLog(@"无法获取网络状态标志");
  908. _NetReachable=NO;
  909. return NO; // 根据实际需求处理错误情况
  910. }
  911. } else {
  912. // 无法创建reachability对象,可能是因为参数错误等
  913. // NSLog(@"无法创建reachability对象,可能是因为参数错误等");
  914. _NetReachable=NO;
  915. return NO; // 根据实际需求处理错误情况
  916. }
  917. }
  918. -(BOOL)NetReachableState{
  919. return _NetReachable;
  920. }
  921. #pragma mark applock
  922. - (void)showLockScreen {
  923. // 确保在主线程执行
  924. if (self.shouldShowLock && [[APPLocker sharedLocker] isPasswordSet] && [[APPLocker sharedLocker] isLockEnabled]) {
  925. NSLog(@"showLockScreen--------------1");
  926. if (self.isJitsiMeet) {
  927. [_floatWindow viewInFload:0];
  928. return;
  929. }
  930. else{
  931. [_floatWindow show:1];
  932. }
  933. return;
  934. }
  935. if (!self.isJitsiMeet) {
  936. [_floatWindow hide];
  937. }
  938. }
  939. - (void)continueAppInitializationAfterUnlock {
  940. // 这里可以添加解锁后需要执行的初始化代码
  941. NSLog(@"应用锁验证通过,继续应用初始化");
  942. // 例如:加载主界面数据、初始化服务等
  943. [self openMainController];
  944. }
  945. - (void)continueWithSecurity{
  946. NSLog(@"-----安全登录成功-----");
  947. [self onLoginSucc];
  948. }
  949. - (void)clearApplicationBadge {
  950. dispatch_async(dispatch_get_main_queue(), ^{
  951. [UIApplication sharedApplication].applicationIconBadgeNumber = 1; // 先设置为1
  952. [UIApplication sharedApplication].applicationIconBadgeNumber = 0; // 再设置为0
  953. // 这个技巧可以确保某些情况下角标被正确清除
  954. });
  955. }
  956. @end