// // VideoCallViewController.m // watch // // Created by WeiChaoZheng on 2018/10/30. // Copyright © 2018年 xTT. All rights reserved. // #import "VideoCallViewController.h" #import "CallViewController.h" #import "VideoUserModel.h" #import "NewCollectionViewCell.h" #import "AddVideoMomberVC.h" #import #import "AgoraConfigModel.h" #import "JCManager.h" #import "JuphoonModel.h" #import "BairuiModel.h" #import "AppDelegate.h" #import "VideoViewController.h" #import "BRManager.h" #import "TihuModel.h" #import "TihuManager.h" #define btnCollectionViewHeight 44*2+1 /** 视频信息页面 */ @interface VideoCallViewController () /** 设备 支持的视频类型 0 不支持 1 声网 2 环信 4 菊风 5 佰锐 */ @property (assign, nonatomic) int video_type; /** 声网配置model */ @property (strong, nonatomic) AgoraConfigModel *agoraModel; /** 菊风配置model */ @property (strong, nonatomic) JuphoonModel *jhModel; /** 佰锐配置model */ @property (strong, nonatomic) BairuiModel *brModel; /** 鹈鹕配置model */ @property (strong, nonatomic) TihuModel *tihuModel; /** 选中的家庭成员数组 */ @property (strong, nonatomic) NSMutableArray *checked_video_list; /** 未选中的家庭成员数组 */ @property (strong, nonatomic) NSMutableArray *unchecked_video_list; @property (assign, nonatomic) int callTimes; @property (assign, nonatomic) BOOL isCancelTimer; @property (strong, nonatomic) NSString *dwUserStr; @end @implementation VideoCallViewController -(AgoraConfigModel *)agoraModel{ if(!_agoraModel){ _agoraModel = [AgoraConfigModel new]; } return _agoraModel; } -(JuphoonModel *)jhModel{ if(!_jhModel){ _jhModel = [JuphoonModel new]; } return _jhModel; } -(BairuiModel *)brModel{ if(!_brModel){ _brModel = [BairuiModel new]; } return _brModel; } -(TihuModel *)tihuModel{ if(!_tihuModel){ _tihuModel = [TihuModel new]; } return _tihuModel; } -(NSMutableArray *)checked_video_list{ if(!_checked_video_list){ _checked_video_list = [NSMutableArray array]; } return _checked_video_list; } -(NSMutableArray *)unchecked_video_list{ if(!_unchecked_video_list){ _unchecked_video_list = [NSMutableArray array]; } return _unchecked_video_list; } /** 设置按钮不可选且半透明 @param flag Bad is NO , Good is YES @param button button */ -(void)setBtnBadRoGoodFlag:(BOOL)flag WithBtn:(UIButton*) button{ if(flag){ [button setAlpha:1]; [button setEnabled:YES]; }else{ [button setAlpha:0.5]; [button setEnabled:NO]; } } -(void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; NSString * valueStr = [UserDefaults valueForKey:VideoTimeAndIDAndWHRecordKey]; NSArray *strArr = [valueStr componentsSeparatedByString:@"&"]; if(valueStr && strArr.count == 5){ //上传视频时间 NSMutableDictionary *dic = [NSMutableDictionary dictionary]; int durationTime = [strArr[0] intValue]; int wait_duration = [strArr[4] intValue]; if(durationTime >= wait_duration){ durationTime = durationTime - wait_duration; }else{ durationTime = 0; } [dic setValue:@(durationTime) forKey:@"duration"];//减去等待时间 [dic setValue:strArr[1] forKey:@"video_id"]; [dic setValue:@([strArr[2] intValue]) forKey:@"distinguishability_width"]; [dic setValue:@([strArr[3] intValue]) forKey:@"distinguishability_heiger"]; [dic setValue:@(wait_duration) forKey:@"wait_duration"]; [cUser postVideoCallTimeParame:[dic copy] deviceModel:cUser.cDevice success:^(id responseObject) { xLog(@"上传视频时间成功"); //MARK: 上传完视频时间后删除存储的 Key [UserDefaults removeObjectForKey:VideoTimeAndIDAndWHRecordKey]; [self loadData]; } failure:^{ xLog(@"上传视频时间失败"); }]; }else{ [self loadData]; } } -(void)loadData{ self.video_type = cUser.cDevice.support_video.intValue; WEAKSELF if(_video_type == 0){ [self goBack:nil]; return; } //MARK: 获取设备uuid成员列表 [cUser.cDevice getVideoUserListSuccess:^(id _Nonnull responseObject) { [weakSelf.checked_video_list removeAllObjects]; if([responseObject[@"checked_video_list"] isKindOfClass:[NSArray class]]){ for (NSDictionary *item in responseObject[@"checked_video_list"]) { VideoUserModel *model = [VideoUserModel new]; [model mj_setKeyValues:item]; [weakSelf.checked_video_list addObject:model]; } } //2个加减的 按钮 [weakSelf.checked_video_list addObject:[VideoUserModel new]]; [weakSelf.checked_video_list addObject:[VideoUserModel new]]; [weakSelf.unchecked_video_list removeAllObjects]; if([responseObject[@"unchecked_video_list"] isKindOfClass:[NSArray class]]){ for (NSDictionary *item in responseObject[@"unchecked_video_list"]) { VideoUserModel *model = [VideoUserModel new]; [model mj_setKeyValues:item]; [weakSelf.unchecked_video_list addObject:model]; } } [weakSelf.memberCollection reloadData]; } failure:^{ }]; } - (void)viewDidLoad { [super viewDidLoad]; self.zx_navTitle = @"视频通话"; self.renewalBtn.layer.cornerRadius = 3; self.renewalBtn.layer.masksToBounds = YES; self.renewalBtn.backgroundColor = mainColor; //默认隐藏 self.renewalBtn.hidden = YES; [self.videoActionBtn addTarget:self action:@selector(monitorDevice:) forControlEvents:UIControlEventTouchUpInside]; self.videoActionBtn.layer.cornerRadius = 3; self.videoActionBtn.layer.masksToBounds = YES; self.videoActionBtn.backgroundColor = mainColor; self.headView.layer.cornerRadius = 3; self.headView.layer.masksToBounds = YES; //判断性别 NSString *sexImageName ; if([cUser.cDevice.sex isEqualToString:@"girl"]){ //女 sexImageName = @"icon_girl_head_portrait"; }else{ //男 sexImageName = @"icon_boy_head_portrait"; } [self.headView sd_setImageWithURL:[NSURL URLWithString:cUser.cDevice.avator] placeholderImage:[myHelper getImageWithName:sexImageName] options:SDWebImageRetryFailed]; self.nameLabel.text = cUser.cDevice.name; [self initCollectionView]; } /** 初始化 collectionView */ - (void)initCollectionView{ //注册 cell [self.memberCollection registerNib:[UINib nibWithNibName:@"NewCollectionViewCell" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:@"NewCollectionViewCellID"]; self.memberCollection.delegate = self; self.memberCollection.dataSource = self; self.memberCollection.backgroundColor = [UIColor clearColor]; } -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ return self.checked_video_list.count; } - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { return CGSizeMake(46, 65); } - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{ return UIEdgeInsetsMake(0, (ScreenWidth -5 -5 - 5*46 )/6, 0, (ScreenWidth -5 -5 - 5*46 )/6); } //设置水平间距 (同一行的cell的左右间距) -(CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { //间距 5等分 return (ScreenWidth -5 -5 - 5*46 )/6; } //垂直间距 (同一列cell上下间距) - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { return 5; } -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ VideoUserModel *model = self.checked_video_list[indexPath.item]; NewCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"NewCollectionViewCellID" forIndexPath:indexPath]; //MARK: 如果是最后2个 if(indexPath.item >= self.checked_video_list.count-1 -1){ cell.nameLabel.text = @""; [cell setSelectWithThisItem:NO]; if(indexPath.item == self.checked_video_list.count-1){ //最后一个 cell.imageVIew.image = [myHelper getImageWithName:@"icon_delete_members"]; }else{ //倒数第二个 cell.imageVIew.image = [myHelper getImageWithName:@"icon_add_members"]; } return cell; }else{ cell.nameLabel.text = model.relationship; [cell setSelectWithThisItem:NO]; cell.imageVIew.image = [myHelper getClickRelationshipImageWithCodeID:model.relationship_image_id deviceType:cUser.cDevice.deviceType.integerValue]; return cell; } } -(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ //MARK: 如果是最后2个 if(indexPath.item >= self.checked_video_list.count-1 -1){ UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]; AddVideoMomberVC *vc = [sb instantiateViewControllerWithIdentifier:@"AddVideoMomberVC"]; NSMutableArray* temp = [NSMutableArray array]; if(indexPath.item == self.checked_video_list.count-1){ //最后一个 // temp = [NSMutableArray arrayWithArray:[self.checked_video_list copy]]; temp = self.checked_video_list; [temp removeLastObject]; [temp removeLastObject]; //减 vc.isUnCheck = YES; }else{ //加 temp = self.unchecked_video_list; vc.isUnCheck = NO; } [vc.myDataSource addObject:temp]; [self.navigationController pushViewController:vc animated:YES]; } } /** MARK: 视频通话方法 */ - (void)monitorDevice:(UIButton *)sender{ WEAKSELF JLAuthorizationManager *jlManager = [JLAuthorizationManager defaultManager]; [jlManager JL_requestAuthorizationWithAuthorizationType:JLAuthorizationTypeAudio authorizedHandler:^{ [weakSelf videoActionFunction]; } unAuthorizedHandler:^{ LGAlertView *alertView = [[LGAlertView alloc] initWithTitle:[NSString stringWithFormat:@"请在iPhone的\"设置-隐私-麦克风\"选项中,允许%@访问你的麦克风",APPName] message:nil style:LGAlertViewStyleAlert buttonTitles:@[@"确定"] cancelButtonTitle:@"" destructiveButtonTitle:nil actionHandler:^(LGAlertView *alertView, NSString *title, NSUInteger index) { // [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]; } cancelHandler:^(LGAlertView *alertView) { } destructiveHandler:nil]; [alertView showAnimated:YES completionHandler:nil]; }]; [jlManager JL_requestAuthorizationWithAuthorizationType:JLAuthorizationTypeVideo authorizedHandler:nil unAuthorizedHandler:^{ LGAlertView *alertView = [[LGAlertView alloc] initWithTitle:[NSString stringWithFormat:@"请在iPhone的\"设置-隐私-相机\"选项中,允许%@访问你的相机",APPName] message:nil style:LGAlertViewStyleAlert buttonTitles:@[@"确定"] cancelButtonTitle:@"" destructiveButtonTitle:nil actionHandler:^(LGAlertView *alertView, NSString *title, NSUInteger index) { } cancelHandler:^(LGAlertView *alertView) { } destructiveHandler:nil]; [alertView showAnimated:YES completionHandler:nil]; }]; } - (void)videoActionFunction{ // update by lsz 2020-12-11 [self selectCallTypeFunction:0]; [self setDwUserStr:@"video"]; return; //[self showBtnCollectionView]; /* 先创建UIAlertController,preferredStyle:选择UIAlertControllerStyleActionSheet,这个就是相当于创建8.0版本之前的UIActionSheet; typedef NS_ENUM(NSInteger, UIAlertControllerStyle) { UIAlertControllerStyleActionSheet = 0, UIAlertControllerStyleAlert } NS_ENUM_AVAILABLE_IOS(8_0); */ UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; /* typedef NS_ENUM(NSInteger, UIAlertActionStyle) { UIAlertActionStyleDefault = 0, UIAlertActionStyleCancel, 取消按钮 UIAlertActionStyleDestructive 破坏性按钮,比如:“删除”,字体颜色是红色的 } NS_ENUM_AVAILABLE_IOS(8_0); */ // 创建action,这里action1只是方便编写,以后再编程的过程中还是以命名规范为主 WEAKSELF UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"视频通话" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { xLog(@"选择视频通话"); [weakSelf selectCallTypeFunction:0]; [weakSelf setDwUserStr:@"video"]; }]; UIAlertAction *action2 = [UIAlertAction actionWithTitle:@"语音通话" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { xLog(@"选择语音通话"); [weakSelf selectCallTypeFunction:1]; [weakSelf setDwUserStr:@"audio"]; }]; UIAlertAction *action3 = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { NSLog(@"取消"); }]; //把action添加到actionSheet里 [actionSheet addAction:action1]; // 去掉语音通话 update by lsz 2020-12-09 //[actionSheet addAction:action2]; [actionSheet addAction:action3]; //相当于之前的[actionSheet show]; [self presentViewController:actionSheet animated:YES completion:nil]; } /// 选择拨打的是什么类型 0: 视频 1:语音 /// @param type 0: 视频 1:语音 - (void)selectCallTypeFunction:(int)type{ WEAKSELF [cUser getVideoAccoutCallType:type deviceModel:cUser.cDevice Success:^(id responseObject) { if([responseObject[@"deviceVideoType"] isEqualToString:@"SW"]){ //声网 weakSelf.agoraModel = [AgoraConfigModel mj_objectWithKeyValues:responseObject]; weakSelf.agoraModel.call_type = type; //调起 SW [weakSelf SWJoinChannel]; } else if ([responseObject[@"deviceVideoType"] isEqualToString:@"BR"]) { weakSelf.brModel = [BairuiModel mj_objectWithKeyValues:responseObject]; weakSelf.brModel.call_type = type; [weakSelf BR_LoginAndCallVideo]; } else if ([responseObject[@"deviceVideoType"] isEqualToString:@"TH"]) { weakSelf.tihuModel = [TihuModel mj_objectWithKeyValues:responseObject]; weakSelf.tihuModel.call_type = type; [weakSelf TH_LoginAndCallVideo]; } else{ //菊风 (默认) weakSelf.jhModel = [JuphoonModel mj_objectWithKeyValues:responseObject]; //[weakSelf.jhModel setValuesForKeysWithDictionary:responseObject]; weakSelf.jhModel.call_type = type; //调起 Juphoon [weakSelf JH_LoginAndCallVideo]; } } failure:^{ }]; // LGAlertView *alertView = [[LGAlertView alloc] initWithTitle:@"提示" message:@"确定与宝贝视频通话?" style:LGAlertViewStyleAlert buttonTitles:@[@"确定"] cancelButtonTitle:@"取消" destructiveButtonTitle:nil actionHandler:^(LGAlertView *alertView, NSString *title, NSUInteger index) { // // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // [cUser getVideoAccoutCallType:type Success:^(id responseObject) { // if([responseObject[@"deviceVideoType"] isEqualToString:@"SW"]){ // //声网 // weakSelf.agoraModel = [AgoraConfigModel mj_objectWithKeyValues:responseObject]; // //调起 SW // [weakSelf SWJoinChannel]; // }else{ // //菊风 (默认) // weakSelf.jhModel = [JuphoonModel mj_objectWithKeyValues:responseObject]; // // [weakSelf.jhModel setValuesForKeysWithDictionary:responseObject]; // //调起 Juphoon // // [weakSelf JH_LoginAndCallVideo]; // } // // } failure:^{ // // }]; // }); // // } cancelHandler:^(LGAlertView *alertView) { // // } destructiveHandler:nil]; // [alertView showAnimated:YES completionHandler:nil]; } /** 测试 模拟 设备拨打的按钮 */ - (IBAction)testAction:(id)sender { } // - (void)SWJoinChannel{ UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]; CallViewController *callVC = [sb instantiateViewControllerWithIdentifier:@"CallViewController"]; callVC.appid = self.agoraModel.appid; // callVC.token = self.agoraModel.token; callVC.video_id = self.agoraModel.video_id; callVC.device = cUser.cDevice; callVC.channelID = self.agoraModel.channelID; callVC.uid = self.agoraModel.app_uid; callVC.device_uid = self.agoraModel.device_uid; callVC.videoSize = CGSizeMake(self.agoraModel.distinguishability_width, self.agoraModel.distinguishability_heiger) ; //AgoraVideoDimension640x360 callVC.limit_time = self.agoraModel.limit_time; callVC.wait_time = self.agoraModel.wait_time; callVC.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:callVC animated:NO completion:nil]; } #pragma mark --- Juphoon 拨打视频通话 --- -(void)JH_LoginAndCallVideo{ //需要去注册 if(![JCManager shared].client) { [[JCManager shared] initializeWithAPPKey:self.jhModel.appkey]; [[JCManager shared].client setServerAddress:@"http:cn.router.justalkcloud.com:8080"]; [[JCManager shared].client login:self.jhModel.username password:@"test" loginParam:nil]; } else { [[JCManager shared] _stopCallTimeoutTimer]; [[JCManager shared] _stopVideoLimitTimeoutTimer]; } [JCManager shared].gMianVC = self; [JCManager shared].model = self.jhModel; [[JCManager shared] callVideoWithUserName]; //调起页面 UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]; JuPhoonCallViewController *callVC = [sb instantiateViewControllerWithIdentifier:@"JuPhoonCallViewController"]; [JCManager shared].callViewController = callVC; callVC.video_id = self.jhModel.video_id; callVC.distinguishability_width = self.jhModel.distinguishability_width; callVC.distinguishability_heiger = self.jhModel.distinguishability_heiger; xLog(@"JF通话的限制时长:%d", self.jhModel.limit_time); callVC.device = cUser.cDevice; callVC.isReceiveCall = NO; //主叫 callVC.statusLabel.text = @"正在发起通话请求..."; if (self.jhModel.call_type == 0) { [callVC openLocationCarmeraViewWithFullSScreen:YES]; } //清除原本定时器配置 // [[JCManager shared] _stopCallTimeoutTimer]; // [[JCManager shared] _stopVideoLimitTimeoutTimer]; callVC.modalPresentationStyle = UIModalPresentationFullScreen; [self.navigationController presentViewController:callVC animated:YES completion:nil]; } #pragma mark --- Bairui 拨打视频通话 --- - (void)BR_LoginAndCallVideo { if (![[BRManager shared] isUserLogin]) { [[BRManager shared] login:cUser.bairui_id nick: cUser.name]; } [BRManager shared].brModel = self.brModel; [BRManager shared].isReceiveCall = NO; [BRManager shared].video_id = self.brModel.video_id; [BRManager shared].device = cUser.cDevice; [BRManager shared].callType = self.brModel.call_type; WEAKSELF [[BRManager shared] showCallDialog:cUser userId:[_brModel.device_username intValue] callback:^{ [weakSelf cancelTimer]; }]; _callTimes = 0; BOOL online = [[BRManager shared] queryRemoteUserOnline:[_brModel.device_username intValue]]; if (online) { [AnyChatPlatform VideoCallControl:BRAC_VIDEOCALL_EVENT_REQUEST :[_brModel.device_username intValue] :0 :0 :0 :_dwUserStr]; NSLog(@"callType=========1=====> %@", _dwUserStr); } else { [self performSelector:@selector(reCall) withObject:nil afterDelay:3]; } } - (void)cancelTimer { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(reCall) object:nil]; } - (void)reCall { _callTimes++; if (_callTimes > 3) { [AnyChatPlatform VideoCallControl:BRAC_VIDEOCALL_EVENT_REQUEST :[_brModel.device_username intValue] :0 :0 :0 :_dwUserStr]; NSLog(@"callType=========3=====> %@", _dwUserStr); return; } BOOL online = [[BRManager shared] queryRemoteUserOnline:[_brModel.device_username intValue]]; if (online) { [AnyChatPlatform VideoCallControl:BRAC_VIDEOCALL_EVENT_REQUEST :[_brModel.device_username intValue] :0 :0 :0 :_dwUserStr]; NSLog(@"callType=========2=====> %@", _dwUserStr); } else { [self performSelector:@selector(reCall) withObject:nil afterDelay:3]; } NSLog(@"查询用户在线次数:%d", _callTimes); } #pragma mark --- Tihu 拨打视频通话 --- - (void)TH_LoginAndCallVideo { // [MoonChatPlatform startCalling:@"321" phoneType:MoonChatVideo callBlock:^(CallStatus status) { // NSLog(@"==========CallStatus=%zd", status); // }]; // // return; if (![[TihuManager shared] isUserLogin]) { [[TihuManager shared] login:cUser.openid pwd:@"123456"]; } [TihuManager shared].thModel = self.tihuModel; [TihuManager shared].isReceiveCall = NO; [TihuManager shared].video_id = self.tihuModel.video_id; [TihuManager shared].device = cUser.cDevice; [TihuManager shared].callType = self.tihuModel.call_type; WEAKSELF [[TihuManager shared] showCallDialog:cUser.cDevice userId:_tihuModel.device_username callback:^{ [weakSelf cancelTimer2]; }]; _callTimes = 0; _isCancelTimer = NO; [[TihuManager shared] queryRemoteUserOnline:cUser.cDevice.imei callback:^(BOOL online) { if (online) { [MoonChatPlatform startCalling:cUser.cDevice.imei phoneType:MoonChatVideo callBlock:^(CallStatus status) { NSLog(@"========CallStatus=%zd", status); }]; } else { if (!_isCancelTimer) { [weakSelf performSelector:@selector(reCall2) withObject:nil afterDelay:3]; } } NSLog(@"查询用户在线:%d", online); }]; } - (void)cancelTimer2 { _isCancelTimer = YES; [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(reCall2) object:nil]; } - (void)reCall2 { _callTimes++; if (_callTimes > 3) { [MoonChatPlatform startCalling:cUser.cDevice.imei phoneType:MoonChatVideo callBlock:^(CallStatus status) { NSLog(@"=========CallStatus=%zd", status); }]; return; } WEAKSELF [[TihuManager shared] queryRemoteUserOnline:cUser.cDevice.imei callback:^(BOOL online) { if (online) { [MoonChatPlatform startCalling:cUser.cDevice.imei phoneType:MoonChatVideo callBlock:^(CallStatus status) { NSLog(@"========CallStatus=%zd", status); }]; } else { if (!_isCancelTimer) { [weakSelf performSelector:@selector(reCall2) withObject:nil afterDelay:3]; } } NSLog(@"查询用户在线:%d", online); }]; NSLog(@"查询用户在线次数:%d", _callTimes); } -(void)viewDidDisappear:(BOOL)animated{ [super viewDidDisappear:animated]; } @end