JSGController.m 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. //
  2. // JSGController.m
  3. // AIIM
  4. //
  5. // Created by gan on 2025/4/21.
  6. //
  7. #import <Foundation/Foundation.h>
  8. #import <AVFoundation/AVFoundation.h>
  9. #import "JSGController.h"
  10. #import "WebRTCStore.h"
  11. #import "GWebSocket.h"
  12. #import "UDManager.h"
  13. #import "AppDelegate.h"
  14. #import "AFNetworking/AFNetworkReachabilityManager.h"
  15. #import <SystemConfiguration/SystemConfiguration.h>
  16. #import "CustomJitsiLogger.h"
  17. #import <Bugly/Bugly.h>
  18. @interface JSGController()<WebRTCStoreDelegate,AVAudioPlayerDelegate>
  19. @property (nonatomic,strong) JitsiMeetView *jitsiView;
  20. @property (nonatomic) NSInteger startTime;
  21. @property (nonatomic) BOOL isClose;
  22. @property (nonatomic,strong) AVPlayer *player;
  23. @property (nonatomic, strong) AFNetworkReachabilityManager *reachabilityManager;
  24. @property (nonatomic, assign) BOOL isInConference;
  25. @property (nonatomic, assign) BOOL isReconnecting;
  26. @property (nonatomic, strong) JitsiMeetConferenceOptions * currentOptions;
  27. @property (nonatomic, assign) NSUInteger reconnectAttempt;
  28. @property (nonatomic,strong) AVAudioPlayer * audioPlayer;
  29. @property (nonatomic, strong) UIButton *hangupButton;
  30. @property (nonatomic, strong) UIButton *speackerBt;
  31. @property (nonatomic, strong) UIButton *scanBt;
  32. @property (nonatomic, strong) UILabel *FloadNote;
  33. @property (nonatomic) BOOL isSpeacker;
  34. @property (nonatomic) BOOL isjoin;
  35. @property (nonatomic) BOOL hadCall;
  36. @property (nonatomic) BOOL floadViewState;
  37. @property (nonatomic) BOOL startLison;
  38. @end
  39. @implementation JSGController
  40. - (void)viewDidLoad {
  41. [super viewDidLoad];
  42. NSLog(@"JSGController----------viewDidLoad");
  43. _isjoin = false;
  44. _isClose=YES;
  45. _floadViewState=NO;
  46. _startLison=NO;
  47. _hadCall = NO;
  48. WebRTCStore.shareInstance.isBusy=true;
  49. WebRTCStore.shareInstance.PeerId =self.chatId;
  50. WebRTCStore.shareInstance.delegate = self;
  51. _jitsiView = (JitsiMeetView*)self.view;
  52. _jitsiView.delegate = self;
  53. CustomJitsiLogger *handler = [CustomJitsiLogger sharedHandler];
  54. handler.errorCount = 0;
  55. [handler.criticalErrors removeAllObjects];
  56. weakSelf(self);
  57. handler.WebsocketErrorBlock = ^{
  58. [weakself reconnectConference];
  59. };
  60. //挂断按钮
  61. _hangupButton = [UIButton buttonWithType:UIButtonTypeCustom];
  62. [_hangupButton setImage:[UIImage imageNamed:@"hangup_icon"] forState:UIControlStateNormal];
  63. [_hangupButton addTarget:self action:@selector(hangupButtonTapped) forControlEvents:UIControlEventTouchUpInside];
  64. [self.view addSubview:_hangupButton];
  65. //扩音器按钮
  66. _speackerBt = [UIButton buttonWithType:UIButtonTypeCustom];
  67. [_speackerBt setImage:[UIImage imageNamed:@"speaker_on_icon"] forState:UIControlStateNormal];
  68. [_speackerBt addTarget:self action:@selector(speackerC) forControlEvents:UIControlEventTouchUpInside];
  69. [self.view addSubview:_speackerBt];
  70. //悬浮按钮
  71. _scanBt = [UIButton buttonWithType:UIButtonTypeCustom];
  72. [_scanBt setImage:[UIImage imageNamed:@"huazhonghua_icon"] forState:UIControlStateNormal];
  73. [_scanBt addTarget:self action:@selector(scanToFload) forControlEvents:UIControlEventTouchUpInside];
  74. [self.view addSubview:_scanBt];
  75. _FloadNote = [[UILabel alloc] init];
  76. _FloadNote.text = NSLocalizedString(@"JSmeet-connectNote", @"");
  77. _FloadNote.textColor = [UIColor whiteColor];
  78. _FloadNote.font = [UIFont systemFontOfSize:14.f];
  79. _FloadNote.textAlignment = NSTextAlignmentCenter;
  80. [self.view addSubview:_FloadNote];
  81. //悬浮按钮
  82. }
  83. -(void)viewDidAppear:(BOOL)animated{
  84. [super viewDidAppear:YES];
  85. if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
  86. // 应用已经解锁并且在前台
  87. NSLog(@"应用已经解锁并且在前台viewWillDisappear-----1111-----");
  88. }
  89. }
  90. #pragma mark 应用被唤醒时判断解锁状态
  91. - (void)GapplicationDidBecomeActive:(NSNotification *)notification {
  92. // 应用进入前台
  93. if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
  94. // 应用已经解锁并且在前台
  95. _startLison=NO;
  96. // [[NSNotificationCenter defaultCenter] removeObserver:self name:notification.name object:notification.object];
  97. // [AppDelegate closeVoip];
  98. NSLog(@"GapplicationDidBecomeActive---------------");
  99. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  100. if(self->_isjoin == false){
  101. self->_isjoin =true;
  102. [self startJitsiMeetCall];
  103. }
  104. });
  105. }
  106. }
  107. #pragma mark 切换扬声器按钮
  108. -(void)speackerC{
  109. _isSpeacker=!_isSpeacker;
  110. if(_isSpeacker){
  111. [_speackerBt setImage:[UIImage imageNamed:@"speaker_off_icon"] forState:UIControlStateNormal];
  112. }
  113. else{
  114. [_speackerBt setImage:[UIImage imageNamed:@"speaker_on_icon"] forState:UIControlStateNormal];
  115. }
  116. [_jitsiView changeAudioSession:_isSpeacker];
  117. }
  118. #pragma mark 挂断按钮
  119. - (void)hangupButtonTapped{
  120. [self endJitsiMeetCall];
  121. }
  122. #pragma mark 悬浮按钮
  123. - (void)scanToFload{
  124. if(self.audioOnly){
  125. [[AppDelegate sharedInstance] floadinSmWindow:1];
  126. }
  127. else{
  128. [[AppDelegate sharedInstance] floadinSmWindow:2];
  129. }
  130. }
  131. #pragma mark 开始JitsiMeet 发起呼叫流程
  132. -(void)startJitsiMeetCall{
  133. NSLog(@"startJitsiMeetCall--------1--------");
  134. _isClose=NO;
  135. _isjoin=false;
  136. _isSpeacker = NO;
  137. _hadCall = NO;
  138. [self.view bringSubviewToFront:_hangupButton];
  139. [_hangupButton mas_makeConstraints:^(MASConstraintMaker *make) {
  140. make.size.mas_equalTo(CGSizeMake(50, 50));
  141. make.bottom.mas_equalTo(-SCREEN_X_BTM);
  142. make.centerX.mas_equalTo(self.view.mas_centerX);
  143. }];
  144. [self.view bringSubviewToFront:_speackerBt];
  145. [_speackerBt mas_makeConstraints:^(MASConstraintMaker *make) {
  146. make.size.mas_equalTo(CGSizeMake(40, 40));
  147. make.bottom.mas_equalTo(-SCREEN_X_BTM);
  148. make.right.mas_equalTo(_hangupButton.mas_left).offset(-12);
  149. }];
  150. [self.view bringSubviewToFront:_scanBt];
  151. [_scanBt mas_makeConstraints:^(MASConstraintMaker *make) {
  152. make.size.mas_equalTo(CGSizeMake(40, 40));
  153. make.bottom.mas_equalTo(-SCREEN_X_BTM);
  154. make.left.mas_equalTo(_hangupButton.mas_right).offset(12);
  155. }];
  156. [self.view bringSubviewToFront:_FloadNote];
  157. [_FloadNote mas_makeConstraints:^(MASConstraintMaker *make) {
  158. make.left.equalTo(self.view.mas_left).offset(26);
  159. make.width.mas_lessThanOrEqualTo(self.view.mas_width).offset(-52);
  160. make.bottom.equalTo(self.view.mas_bottom).offset(-150);
  161. }];
  162. if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
  163. // 应用已经解锁并且在前台
  164. NSLog(@"应用已经解锁并且在前台viewWillDisappear-----1111");
  165. }
  166. else{
  167. if(!_startLison){
  168. _startLison=YES;
  169. [[NSNotificationCenter defaultCenter] addObserver:self
  170. selector:@selector(GapplicationDidBecomeActive:)
  171. name:UIApplicationDidBecomeActiveNotification
  172. object:nil];
  173. }
  174. return;
  175. }
  176. if (self.chatId == nil) {//聊天框参数异常
  177. NSLog(@"Room is nul!");
  178. [self endJitsiMeetCall];
  179. return;
  180. }
  181. NSLog(@"startJitsiMeetCall--------2--------");
  182. NSLog(@"%@:%@",self.room,self.chatId);
  183. [AppDelegate JitsiMeetState:YES];
  184. [AppDelegate closeVoip];
  185. //初始化状态参数
  186. _startTime = 0;//通话时长
  187. _reconnectAttempt = 0;//重连次数
  188. _isReconnecting = NO;//是否重连
  189. if(self.isCaller){
  190. NSDate *now = [NSDate date];
  191. NSTimeInterval trt = [now timeIntervalSince1970];
  192. NSInteger time = trt*1000;
  193. self.room = [NSString stringWithFormat:@"%@_%ld",self.chatId,(long)time];
  194. }
  195. else{
  196. [self sendBusy];
  197. }
  198. [self initjsView];//初始化 房间页面
  199. _isjoin =true;
  200. if(self.currentOptions){
  201. [_jitsiView join:self.currentOptions];//进入房间
  202. }
  203. else{
  204. //初始化失败
  205. NSString *bgMark = @"initjsView 初始化失败";
  206. [Bugly reportException:[NSException exceptionWithName:[NSString stringWithFormat:@"voip:%@",bgMark] reason:@"" userInfo:nil]];
  207. [self endJitsiMeetCall];
  208. return;
  209. }
  210. [self.audioPlayer play];
  211. _FloadNote.alpha = 1;
  212. [_jitsiView changeAudioSession:NO];
  213. }
  214. #pragma mark 结束JitsiMeet 隐藏界面 释放资源
  215. -(void)endJitsiMeetCall{
  216. [self.audioPlayer stop];
  217. [self.jitsiView leave];
  218. [_jitsiView closeChat];
  219. [AppDelegate JitsiMeetState:NO];
  220. [self endCall];
  221. [[NSNotificationCenter defaultCenter] removeObserver:self];
  222. }
  223. #pragma mark 重连操作,待完善
  224. - (void)reconnectConference {
  225. NSLog(@"reconnectConference---------1");
  226. if (_isReconnecting) return;
  227. _isReconnecting = YES;
  228. _reconnectAttempt++;
  229. if (_reconnectAttempt > 3) {
  230. _isReconnecting = NO;
  231. return;
  232. }
  233. NSLog(@"reconnectConference---------2");
  234. // 1. 先离开当前会议
  235. [self.jitsiView leave];
  236. // 2. 等待清理完成
  237. NSLog(@"reconnectConference---------3");
  238. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  239. // 3. 重新加入会议
  240. // [self initjsView];
  241. [self.jitsiView join:self.currentOptions];//进入房间
  242. NSLog(@"reconnectConference---------4");
  243. // if(self.startTime==0){
  244. // NSDate *now = [NSDate date];
  245. // NSTimeInterval trt = [now timeIntervalSince1970];
  246. // self.startTime = trt*1000;
  247. // }
  248. // 4. 重置重连状态
  249. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  250. self->_isReconnecting = NO;
  251. });
  252. });
  253. }
  254. -(void)sendBusy{
  255. NSDictionary *userinfo = [UDManager.shareInstance getDDManager:dkuserinfo];
  256. NSLog(@"userinfo:%@",userinfo);
  257. if (userinfo == nil) {
  258. NSLog(@"Room is nul!");
  259. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  260. [self dismissViewControllerAnimated:YES completion:nil];
  261. });
  262. return;
  263. }
  264. NSString *userId = userinfo[@"id"];
  265. NSString *username = userinfo[@"name"];
  266. NSString *useravatar = userinfo[@"avatar"];
  267. NSDate *now = [NSDate date];
  268. NSTimeInterval trt = [now timeIntervalSince1970];
  269. NSInteger time = trt*1000;
  270. NSString *strtime = [NSString stringWithFormat:@"%ld",(long)time];
  271. BOOL conetType=true;
  272. if (self.audioOnly) {
  273. conetType=false;
  274. }
  275. NSDictionary *callMsg = @{
  276. @"code":SendCode_WEBRTC_BUSY,
  277. @"message": @{
  278. @"chatId":self.chatId,
  279. @"fromId":userId,
  280. @"type":@"0",
  281. @"msgtype":@"busy",
  282. @"conetType":[NSNumber numberWithBool:conetType],
  283. @"timestamp":strtime,
  284. @"fromName":username,
  285. @"fromAvatar":useravatar,
  286. @"payload":self.room?:@""
  287. }
  288. };
  289. NSError *error;
  290. NSData *jsonData = [NSJSONSerialization dataWithJSONObject:callMsg options:0 error:&error];
  291. if (!jsonData) {
  292. NSLog(@"Got an error: %@", error);
  293. } else {
  294. NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
  295. NSLog(@"%@", jsonString); // 输出: {"name":"John","age":25}
  296. [GWebSocket.shareInstance sendMsg:jsonString];
  297. }
  298. }
  299. -(void)sendCall{
  300. NSDictionary *userinfo = [UDManager.shareInstance getDDManager:dkuserinfo];
  301. NSLog(@"userinfo:%@",userinfo);
  302. NSString *userId = userinfo[@"id"];
  303. NSString *username = userinfo[@"name"];
  304. NSString *useravatar = userinfo[@"avatar"];
  305. NSLog(@"-------拨打-------");
  306. NSDate *now = [NSDate date];
  307. NSTimeInterval trt = [now timeIntervalSince1970];
  308. NSInteger time = trt*1000;
  309. NSString *strtime = [NSString stringWithFormat:@"%ld",(long)time];
  310. BOOL conetType=true;
  311. if (self.audioOnly) {
  312. conetType=false;
  313. }
  314. NSDictionary *callMsg = @{
  315. @"code":@"8",
  316. @"message": @{
  317. @"chatId":self.chatId,
  318. @"fromId":userId,
  319. @"type":@"0",
  320. @"msgtype":@"calling",
  321. @"conetType":[NSNumber numberWithBool:conetType],
  322. @"timestamp":strtime,
  323. @"fromName":username,
  324. @"fromAvatar":useravatar,
  325. @"payload":self.room
  326. }
  327. };
  328. NSError *error;
  329. NSData *jsonData = [NSJSONSerialization dataWithJSONObject:callMsg options:0 error:&error];
  330. if (!jsonData) {
  331. NSLog(@"Got an error: %@", error);
  332. } else {
  333. NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
  334. NSLog(@"%@", jsonString); // 输出: {"name":"John","age":25}
  335. [GWebSocket.shareInstance sendMsg:jsonString];
  336. }
  337. }
  338. -(void)endCall{
  339. if (_isClose) {
  340. return;
  341. }
  342. NSLog(@"-------挂断-------");
  343. NSDictionary *userinfo = [UDManager.shareInstance getDDManager:dkuserinfo];
  344. if(userinfo==nil){
  345. return;
  346. }
  347. NSString *userId = userinfo[@"id"];
  348. NSString *username = userinfo[@"name"];
  349. NSString *useravatar = userinfo[@"avatar"];
  350. NSDate *now = [NSDate date];
  351. NSTimeInterval trt = [now timeIntervalSince1970];
  352. NSInteger time = trt*1000;
  353. NSString *strtime = [NSString stringWithFormat:@"%ld",(long)time];
  354. if(self.isCaller){
  355. NSString *result = @"false";
  356. NSString *duration = @"0";
  357. if (_startTime>0) {
  358. result = @"true";
  359. _startTime=time-_startTime;
  360. duration=[NSString stringWithFormat:@"%ld",(long)_startTime];
  361. }
  362. BOOL conetType=true;
  363. NSString *content;
  364. if (self.audioOnly) {
  365. conetType=false;
  366. content = @"【语音通话】";
  367. }
  368. else{
  369. content = @"【视频通话】";
  370. }
  371. NSDictionary *callMsg = @{
  372. @"code":@"2",
  373. @"message": @{
  374. //@"id":strtime,
  375. @"localtime":strtime,
  376. @"mine":[NSNumber numberWithBool:YES],
  377. @"messageType":@"7",
  378. @"chatId":self.chatId,
  379. @"fromId":userId,
  380. @"fromName":username,
  381. @"fromAvatar":useravatar,
  382. @"type":@"0",
  383. @"result":result,
  384. @"timestamp":strtime,
  385. @"video":[NSNumber numberWithBool:conetType],
  386. @"duration":duration,
  387. @"content":content,
  388. }
  389. };
  390. NSError *error;
  391. NSData *jsonData = [NSJSONSerialization dataWithJSONObject:callMsg options:0 error:&error];
  392. if (!jsonData) {
  393. NSLog(@"Got an error: %@", error);
  394. } else {
  395. NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
  396. NSLog(@"%@", jsonString); // 输出: {"name":"John","age":25}
  397. [GWebSocket.shareInstance sendMsg:jsonString];
  398. }
  399. }
  400. NSDictionary *callMsg = @{
  401. @"code":@"9",
  402. @"message": @{
  403. @"chatId":self.chatId,
  404. @"fromId":userId,
  405. @"type":@"0",
  406. @"msgtype":@"close",
  407. @"timestamp":strtime,
  408. @"fromName":username,
  409. @"fromAvatar":useravatar,
  410. @"payload":self.room?:@""
  411. }
  412. };
  413. NSError *error;
  414. NSData *jsonData = [NSJSONSerialization dataWithJSONObject:callMsg options:0 error:&error];
  415. if (!jsonData) {
  416. NSLog(@"Got an error: %@", error);
  417. } else {
  418. NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
  419. NSLog(@"%@", jsonString); // 输出: {"name":"John","age":25}
  420. [GWebSocket.shareInstance sendMsg:jsonString];
  421. }
  422. WebRTCStore.shareInstance.isBusy=false;
  423. WebRTCStore.shareInstance.PeerId =nil;
  424. _isClose=YES;
  425. }
  426. #pragma mark 拨打、挂断、重拨 WebRTCStoreDelegate
  427. -(void)WebRTCStoreAct:(NSDictionary *)actData{
  428. NSLog(@"WebRTCStoreAct----msgtype:%@",actData);
  429. NSString *messageType =actData[@"messageType"]?:@"";
  430. if([messageType isEqualToString:MessageType_DFBUSY]){
  431. UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Common_tips", @"提示")
  432. message:NSLocalizedString(@"JSGController-mang", @"對方正忙")
  433. preferredStyle:UIAlertControllerStyleAlert];
  434. UIAlertAction *okAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Common_confirm", @"確定")
  435. style:UIAlertActionStyleDefault
  436. handler:^(UIAlertAction * action) {
  437. // 点击确定后的操作
  438. [self endJitsiMeetCall];
  439. }];
  440. [alert addAction:okAction];
  441. [self presentViewController:alert animated:YES completion:nil];
  442. return;
  443. }
  444. NSString *msgtype = actData[@"msgtype"]?:@"";
  445. if([msgtype isEqualToString:@"close"]){
  446. NSString *chatId =actData[@"fromId"]?:@"";
  447. if([self.chatId isEqualToString:chatId]){//对方挂断
  448. if(self.startTime>0){
  449. }else{
  450. [self endJitsiMeetCall];
  451. }
  452. }
  453. else{//非对方挂断的其他干扰数据
  454. }
  455. }
  456. }
  457. #pragma mark JitsiMeetView act
  458. -(void)initjsView{
  459. // Attach this controller as the delegate.
  460. JitsiMeetConferenceOptions *options=nil;
  461. if(self.isCaller){
  462. NSLog(@"initjsView---00000---");
  463. // create the room.JitsiMeetConferenceOptions
  464. options = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
  465. builder.serverURL = [NSURL URLWithString:JitsiMeetSV];
  466. builder.room = self.room;
  467. builder.audioOnly = self.audioOnly;
  468. [builder setFeatureFlag:@"ios.screensharing.enabled" withBoolean:YES];
  469. //界面优化 - 隐藏不必要的会议功能
  470. [builder setFeatureFlag:@"welcomepage.enabled" withBoolean:NO];
  471. [builder setFeatureFlag:@"pip.enabled" withBoolean:NO];
  472. [builder setFeatureFlag:@"live-streaming.enabled" withBoolean:NO];
  473. [builder setFeatureFlag:@"recording.enabled" withBoolean:NO];
  474. [builder setFeatureFlag:@"kick-out.enabled" withBoolean:NO];
  475. [builder setFeatureFlag:@"security-options.enabled" withBoolean:NO];
  476. [builder setFeatureFlag:@"chat.enabled" withBoolean:NO];
  477. [builder setFeatureFlag:@"invite.enabled" withBoolean:NO];
  478. [builder setFeatureFlag:@"add-people.enabled" withBoolean:NO];
  479. [builder setFeatureFlag:@"video-share.enabled" withBoolean:NO];
  480. [builder setFeatureFlag:@"call-integration.enabled" withBoolean:NO];
  481. [builder setFeatureFlag:@"startWithAudioMuted" withBoolean:NO];
  482. [builder setFeatureFlag:@"prejoinpage.enabled" withBoolean:NO];
  483. [builder setFeatureFlag:@"reconnect.enabled" withBoolean:YES];
  484. [builder setConfigOverride:@"iceTransportPolicy" withValue:@"relay"];
  485. [builder setConfigOverride:@"enableNetworkMonitor" withBoolean:YES];
  486. [builder setConfigOverride:@"toolbarButtons" withArray:@[@"microphone",@"camera"]];
  487. //
  488. // // 界面简化 - 更适合一对一场景
  489. // [builder setFeatureFlag:@"toolbox.alwaysVisible" withBoolean:NO];
  490. // [builder setFeatureFlag:@"filmstrip.enabled" withBoolean:NO];
  491. // [builder setFeatureFlag:@"thumbnail.enabled" withBoolean:NO];
  492. // [builder setFeatureFlag:@"disableRtx" withBoolean:YES];// 一对一不需要RTX
  493. // [builder setFeatureFlag:@"disableNS" withBoolean:YES]; // 降噪可关闭
  494. //
  495. // [builder setFeatureFlag:@"ios.audio-handler" withBoolean:NO];
  496. [builder setConfigOverride:@"toolbarButtons" withArray:@[@"microphone",@"camera"]];
  497. }];
  498. }
  499. else{
  500. // Join the room.
  501. NSLog(@"initjsView---111---");
  502. options
  503. = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
  504. builder.room = self.room;
  505. builder.audioOnly = self.audioOnly;
  506. [builder setFeatureFlag:@"welcomepage.enabled" withBoolean:NO];
  507. [builder setFeatureFlag:@"pip.enabled" withBoolean:NO];
  508. [builder setFeatureFlag:@"ios.screensharing.enabled" withBoolean:YES];
  509. [builder setFeatureFlag:@"chat.enabled" withBoolean:NO];
  510. [builder setFeatureFlag:@"invite.enabled" withBoolean:NO];
  511. [builder setFeatureFlag:@"add-people.enabled" withBoolean:NO];
  512. [builder setFeatureFlag:@"video-share.enabled" withBoolean:NO];
  513. [builder setFeatureFlag:@"call-integration.enabled" withBoolean:NO];
  514. [builder setFeatureFlag:@"startWithAudioMuted" withBoolean:NO];
  515. [builder setFeatureFlag:@"prejoinpage.enabled" withBoolean:NO];
  516. [builder setFeatureFlag:@"reconnect.enabled" withBoolean:YES];
  517. [builder setConfigOverride:@"iceTransportPolicy" withValue:@"relay"];
  518. [builder setConfigOverride:@"enableNetworkMonitor" withBoolean:YES];
  519. [builder setConfigOverride:@"toolbarButtons" withArray:@[@"microphone",@"camera"]];
  520. }];
  521. }
  522. NSLog(@"initjsView---2---:%@",options);
  523. self.currentOptions = options;
  524. }
  525. - (void)conferenceWillJoin:(NSDictionary *)data {
  526. NSLog(@"About to join conference---- %@", self.room);
  527. self.isInConference = NO;
  528. if (self.isCaller) {//拨打方进入房间成功,开始通知对方
  529. if(_hadCall){
  530. return;
  531. }
  532. _hadCall = YES;
  533. [self sendCall];
  534. }
  535. else{//接听方进入房间,播放等待接通铃声
  536. NSLog(@"self.audioPlayer-----------");
  537. // [self.audioPlayer play];
  538. // [self reconnectConference];
  539. }
  540. [self.view bringSubviewToFront:_hangupButton];
  541. [_hangupButton mas_makeConstraints:^(MASConstraintMaker *make) {
  542. make.size.mas_equalTo(CGSizeMake(50, 50));
  543. make.bottom.mas_equalTo(-SCREEN_X_BTM);
  544. make.centerX.mas_equalTo(self.view.mas_centerX);
  545. }];
  546. [self.view bringSubviewToFront:_speackerBt];
  547. [_speackerBt mas_makeConstraints:^(MASConstraintMaker *make) {
  548. make.size.mas_equalTo(CGSizeMake(40, 40));
  549. make.bottom.mas_equalTo(-SCREEN_X_BTM);
  550. make.right.mas_equalTo(_hangupButton.mas_left).offset(-12);
  551. }];
  552. [self.view bringSubviewToFront:_scanBt];
  553. [_scanBt mas_makeConstraints:^(MASConstraintMaker *make) {
  554. make.size.mas_equalTo(CGSizeMake(40, 40));
  555. make.bottom.mas_equalTo(-SCREEN_X_BTM);
  556. make.left.mas_equalTo(_hangupButton.mas_right).offset(12);
  557. }];
  558. [self.view bringSubviewToFront:_FloadNote];
  559. [_FloadNote mas_makeConstraints:^(MASConstraintMaker *make) {
  560. make.left.equalTo(self.view.mas_left).offset(26);
  561. make.width.mas_lessThanOrEqualTo(self.view.mas_width).offset(-52);
  562. make.bottom.equalTo(self.view.mas_bottom).offset(-150);
  563. }];
  564. }
  565. - (void)conferenceJoined:(NSDictionary *)data {
  566. _reconnectAttempt = 0;
  567. _isInConference = YES;
  568. NSLog(@"Conference %@ joined----11222-------", self.room);
  569. if(!self.isCaller){//接听方接通成功
  570. [self.audioPlayer stop];//停止铃声
  571. _FloadNote.alpha = 0;
  572. }
  573. }
  574. - (void)conferenceTerminated:(NSDictionary *)data {//连接错误,重连处理待验证
  575. NSLog(@"conferenceTerminated----------------------:%@",data);
  576. _isInConference = NO;
  577. NSString *error = data[@"error"];
  578. if (error) {
  579. if ([error isEqualToString:@"connection.otherError"]) {
  580. [self reconnectConference];
  581. } else {
  582. NSLog(@"%@",error);
  583. }
  584. }
  585. }
  586. - (void)readyToClose:(NSDictionary *)data {
  587. NSLog(@"readyToClose-----:%@",data);
  588. if (_isReconnecting) {
  589. return;
  590. }
  591. }
  592. - (void)customButtonPressed:(NSDictionary *)data {
  593. NSLog(@"---------Custom button pressed %@", data);
  594. }
  595. -(void)participantJoined:(NSDictionary *)data{
  596. NSLog(@"------1-------participantJoined");
  597. if(_startTime==0){
  598. NSDate *now = [NSDate date];
  599. NSTimeInterval trt = [now timeIntervalSince1970];
  600. _startTime = trt*1000;
  601. }
  602. _FloadNote.alpha = 0;
  603. [self.audioPlayer stop];
  604. // 使用GCD创建一个在3秒后执行的定时器
  605. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  606. NSLog(@"Timer fired using GCD!");
  607. [self inispeacker];
  608. });
  609. }
  610. - (void)participantLeft:(NSDictionary *)data{
  611. NSLog(@"participantLeft:%@",data);
  612. //p2p 一方退出,就挂掉
  613. [self endJitsiMeetCall];
  614. [_jitsiView closeChat];
  615. // [self dismissViewControllerAnimated:YES completion:nil];
  616. }
  617. -(void)inispeacker{
  618. if(self.audioOnly){
  619. _isSpeacker=NO;
  620. [_jitsiView changeAudioSession:NO];
  621. }
  622. else{
  623. _isSpeacker=YES;
  624. [_jitsiView changeAudioSession:YES];
  625. }
  626. if(_isSpeacker){
  627. [_speackerBt setImage:[UIImage imageNamed:@"speaker_off_icon"] forState:UIControlStateNormal];
  628. }
  629. else{
  630. [_speackerBt setImage:[UIImage imageNamed:@"speaker_on_icon"] forState:UIControlStateNormal];
  631. }
  632. }
  633. - (UIStatusBarStyle)preferredStatusBarStyle {
  634. return UIStatusBarStyleLightContent; // 返回白色状态栏
  635. }
  636. #pragma mark lazy
  637. - (AVAudioPlayer *)audioPlayer{
  638. if (!_audioPlayer) {
  639. NSURL *ringtoneURL = [[NSBundle mainBundle] URLForResource:@"ring" withExtension:@"wav"];
  640. _audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:ringtoneURL error:nil];
  641. _audioPlayer.delegate = self;
  642. [_audioPlayer setNumberOfLoops:-1];
  643. }
  644. NSLog(@"audioPlayer1122----");
  645. return _audioPlayer;
  646. }
  647. - (void)enterPictureInPicture:(NSDictionary *)data{
  648. NSLog(@"enterPictureInPicture-------------");
  649. }
  650. @end