// // BRManager.m // tongxin // // Created by ecell on 2020/11/18. // Copyright © 2020 xTT. All rights reserved. // #import "BRManager.h" #import #import "BRVideoCallView.h" #import #import "UIView+XHRemoteImage.h" #import "WHToast.h" #define kUserID 1001 #define kAnyChatIP @"iotcloud.anychat.cn" #define kAnyChatPort 8906 #define kAnyChatUserName @"AnyChat" #define kAnyChatAppid @"A3BEE84E-9C7A-D848-85D3-90F233D9A022" #define kAnyChatDefaultSignUrl @"http://iotcloud.anychat.cn/AnyChatSign/json/getSign" #define BRAC_SO_CORESDK_8KAUDIOSAMPLES 249 ///< 8K音频采样模式 @interface BRManager () { AnyChatPlatform *theAnyChat; AVAudioPlayer *audioPlayer; } @property (strong, nonatomic) LSTPopView *popView; @end static BRManager* _manager; static bool _isLogining; static NSString* _nick; static NSString* _bairuiId; @implementation BRManager + (BRManager*)shared { static dispatch_once_t predicate; dispatch_once(&predicate, ^{ _manager = [[self alloc] init]; //8k设置放在初始化之前 [AnyChatPlatform SetSDKOptionInt:BRAC_SO_CORESDK_8KAUDIOSAMPLES :1]; [AnyChatPlatform InitSDK:0]; [AnyChatPlatform SetSDKOptionInt:BRAC_SO_CORESDK_UPLOADLOGINFO :1]; [[NSNotificationCenter defaultCenter] addObserver:_manager selector:@selector(AnyChatNotifyHandler:) name:@"ANYCHATNOTIFY" object:nil]; }); return _manager; } -(bool)initialize { theAnyChat = [AnyChatPlatform getInstance]; theAnyChat.notifyMsgDelegate = self; theAnyChat.videoCallDelegate = self; return YES; } //0 Unknow,1 Connected,2 Logined,3 In Room,4 Logouted,5 Link Closed -(BOOL)isUserLogin { int result = [AnyChatPlatform QueryUserStateInt:-1 :BRAC_USERSTATE_SELFUSERSTATUS]; NSLog(@"isUserLogin = %d", result); return (result==2 || result==3); } // 用户离线 "{"errorcode":205}" -(BOOL)queryRemoteUserOnline:(int)userId { NSString *qParam = [NSString stringWithFormat:@"{\"userid\":%d}", userId]; NSString *json = [AnyChatPlatform QueryInfoFromServer:ANYCHAT_SERVERQUERY_USERINFOBYID :qParam :0]; NSLog(@"json = %@", json); if (json) { // MARK add by lsz 2021-12-15 json is nil NSData *data = [json dataUsingEncoding:NSUTF8StringEncoding]; NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; NSNumber *code = [dict objectForKey:@"errorcode"]; if (code) { return [code intValue] != 205; } } return NO; } -(void)uninitialize { [AnyChatPlatform Release]; [[NSNotificationCenter defaultCenter] removeObserver:self]; } -(void)login:(NSString *)bairuiId nick:(NSString *) nick { _bairuiId = bairuiId; _nick = nick; [self getSign:@{@"userid": bairuiId , @"struserid": @""} success:^(id responseObject) { NSLog(@"获取签名成功:%@", responseObject); if ([[responseObject objectForKey:@"errorcode"] intValue] ==0) { int timestamp = [[responseObject objectForKey:@"timestamp"] intValue]; NSString *signStr = [responseObject objectForKey:@"sigStr"]; NSLog(@"开始登录。。。"); [AnyChatPlatform Connect:kAnyChatIP : kAnyChatPort]; [AnyChatPlatform LoginEx:nick :[bairuiId intValue] :@"" :kAnyChatAppid :timestamp :signStr :nil]; } else { //[self showSignError]; NSLog(@"签名获取失败:%d", [[responseObject objectForKey:@"errorcode"] intValue]); _isLogining = NO; } } failure:^(NSError *error) { NSLog(@"获取签名失败。。。"); _isLogining = NO; }]; } #pragma mark - AnyChatNotifyMessageDelegate - (void)AnyChatNotifyHandler:(NSNotification*)notify { NSDictionary* dict = notify.userInfo; [theAnyChat OnRecvAnyChatNotify:dict]; } // 连接服务器消息 - (void) OnAnyChatConnect:(BOOL) bSuccess { if (!bSuccess) { NSLog(@"佰锐视频连接失败"); } else { NSLog(@"佰锐视频连接成功"); } } // 用户登陆消息 - (void) OnAnyChatLogin:(int) dwUserId : (int) dwErrorCode { if(dwErrorCode == GV_ERR_SUCCESS) { NSLog(@"佰锐视频登录成功"); _isLogining = NO; // 肯能出现空指针 去掉这行代码 2021-12-24 //[self queryRemoteUserOnline:dwUserId]; } else { [AnyChatPlatform Logout]; _isLogining = NO; NSLog(@"佰锐视频登录失败:%d",dwErrorCode); } } // 用户进入房间消息 - (void) OnAnyChatEnterRoom:(int) dwRoomId : (int) dwErrorCode { VideoViewController *videoVC = [[VideoViewController alloc]init]; videoVC.brModel = self.brModel; videoVC.isReceiveCall = _isReceiveCall; videoVC.callType = _callType; videoVC.video_id = self.brModel.videoId; videoVC.device = APIManager.sharedManager.deviceModel; self.callViewController = videoVC; videoVC.hidesBottomBarWhenPushed = YES; if (![[self.gMianVC.navigationController.viewControllers lastObject] isKindOfClass:videoVC.class]) { UIViewController *topVC = [self getCurrentVC]; [topVC.navigationController pushViewController:videoVC animated:YES]; // old update by lsz //[self.gMianVC.navigationController pushViewController:videoVC animated:YES]; } NSLog(@"======OnAnyChatEnterRoom======%d",dwRoomId); } // MARK: 获取顶部视图 add by lsz 2021-06-19 - (UIViewController *)getCurrentVC { UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController; UIViewController *currentVC = [self getCurrentVCFrom:rootViewController]; return currentVC; } - (UIViewController *)getCurrentVCFrom:(UIViewController *)rootVC { UIViewController *currentVC; if ([rootVC presentedViewController]) { // 视图是被presented出来的 rootVC = [rootVC presentedViewController]; } if ([rootVC isKindOfClass:[UITabBarController class]]) { // 根视图为UITabBarController currentVC = [self getCurrentVCFrom:[(UITabBarController *)rootVC selectedViewController]]; } else if ([rootVC isKindOfClass:[UINavigationController class]]){ // 根视图为UINavigationController currentVC = [self getCurrentVCFrom:[(UINavigationController *)rootVC visibleViewController]]; } else { // 根视图为非导航类 currentVC = rootVC; } return currentVC; } // 房间在线用户消息 - (void) OnAnyChatOnlineUser:(int) dwUserNum : (int) dwRoomId { } // 用户进入房间消息 - (void) OnAnyChatUserEnterRoom:(int) dwUserId { NSLog(@"======OnAnyChatUserEnterRoom======%d",dwUserId); [[NSNotificationCenter defaultCenter] postNotificationName:@"ANY_CHAT_USER_ENTER_ROOM" object:nil userInfo:@{@"dwUserId":[NSNumber numberWithInt:dwUserId]}]; } // 用户退出房间消息 - (void) OnAnyChatUserLeaveRoom:(int) dwUserId { } // 网络断开消息 - (void) OnAnyChatLinkClose:(int) dwErrorCode { //[AnyChatPlatform Logout]; [self finishVideoCall]; } #pragma mark ---- 网络请求获取签名登录 ---- - (void)getSign:(NSDictionary*)paramDict success:(void (^)(id))success failure:(void (^)(NSError *))failure { NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:kAnyChatDefaultSignUrl]]; request.HTTPMethod = @"POST"; request.timeoutInterval = 10.0; request.HTTPBody = [[NSString stringWithFormat:@"userid=%@&struserid=%@&appid=%@", paramDict[@"userid"], paramDict[@"struserid"], kAnyChatAppid] dataUsingEncoding:NSUTF8StringEncoding]; [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; NSURLSession *session = [NSURLSession sharedSession]; [[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { dispatch_async(dispatch_get_main_queue(), ^{ if (!error) { NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; if (success) success(dict); } else { if (failure) failure(error); } }); }] resume]; } - (void)OnAnyChatVideoCallEventCallBack:(int)dwEventType :(int)dwUserId :(int)dwErrorCode :(int)dwFlags :(int)dwParam :(NSString *)lpUserStr { //NSString *s_theCallbackUserName = [AnyChatPlatform GetUserName:dwUserId]; //NSString *callType = lpUserStr; switch (dwEventType) { case BRAC_VIDEOCALL_EVENT_REQUEST: { NSLog(@"收到视频通话请求"); self.isReceiveCall = YES; [self doVideoAnswer:dwUserId :lpUserStr]; break; } case BRAC_VIDEOCALL_EVENT_REPLY: { NSString *status; switch (dwErrorCode) { case GV_ERR_VIDEOCALL_CANCEL: { NSLog(@"用户取消会话"); status = @"用户取消会话"; break; } case GV_ERR_VIDEOCALL_REJECT: { NSLog(@"用户拒绝会话"); status = @"用户拒绝会话"; break; } case GV_ERR_VIDEOCALL_OFFLINE: { NSLog(@"对方不在线"); status = @"对方不在线"; break; } case GV_ERR_VIDEOCALL_BUSY: { NSLog(@"用户在忙"); status = @"用户在忙"; break; } case GV_ERR_VIDEOCALL_TIMEOUT: { NSLog(@"会话请求超时"); status = @"用户在忙"; break; } case GV_ERR_VIDEOCALL_DISCONNECT: { NSLog(@"网络断线"); status = @"对方挂断视频"; break; } case GV_ERR_VIDEOCALL_NOTINCALL: { NSLog(@"用户不在呼叫状态"); status = @"用户不在呼叫状态"; break; } } if (dwErrorCode != 0) { [self stopRing]; [self dismissPopView]; } if (status) { [WHToast showMessage:status duration:3 finishHandler:^{}]; } //if (dwErrorCode == GV_ERR_VIDEOCALL_DISCONNECT) { // [self finishVideoCall]; //} break; } case BRAC_VIDEOCALL_EVENT_START://成功 { //进入房间 [AnyChatPlatform EnterRoom:dwParam :@""]; g_isEnterRoom = YES; NSLog(@"进入房间%d", dwParam); [self stopRing]; [self dismissPopView]; break; } case BRAC_VIDEOCALL_EVENT_FINISH: { [self finishVideoCall]; break; } } } -(void)finishVideoCall { if (g_isEnterRoom) { g_isEnterRoom = NO; [AnyChatPlatform LeaveRoom:-1]; NSLog(@"=======BRAC_VIDEOCALL_EVENT_FINISH LeaveRoom"); } [self.callViewController.navigationController popViewControllerAnimated:YES]; NSString *callTime = self.callViewController.theVideoTimeLab.text; self.callViewController = nil; [self uploadCallTime: callTime]; [AnyChatPlatform Logout]; [self login:_bairuiId nick:_nick]; //[self uninitialize]; NSLog(@"视频通话结束。。。"); } -(void)uploadCallTime:(NSString *)callTime { if(callTime && callTime.length == 8) { NSLog(@"upload call time = %@", callTime); NSArray *hhmmss = [callTime componentsSeparatedByString:@":"]; if (hhmmss && hhmmss.count == 3) { int hh = [[NSString stringWithFormat:@"%@", hhmmss[0]] intValue]; int mm = [[NSString stringWithFormat:@"%@", hhmmss[1]] intValue]; int ss = [[NSString stringWithFormat:@"%@", hhmmss[2]] intValue]; int total = hh*60*60 + mm*60 + ss; //MARK:上传视频时间 NSMutableDictionary *dic = [NSMutableDictionary dictionary]; [dic setValue:@(total) forKey:@"duration"]; [dic setValue:@(0) forKey:@"waitDuration"]; [dic setValue:APIManager.sharedManager.deviceModel.imei forKey:@"imei"]; [dic setValue:self.brModel.videoId forKey:@"videoId"]; [[[APIManager sharedManager] APPOST:VideoRecord_URL parameters:dic isJson:YES resultClass:nil] subscribeNext:^(id _Nullable x) { [UICommon HidenLoading]; NSLog(@"上传视频时间成功"); //MARK: 上传完视频时间后删除存储的 Key [UserDefaults removeObjectForKey:VideoTimeAndIDAndWHRecordKey]; } error:^(NSError * _Nullable error) { NSDictionary *dic = error.userInfo; [UICommon MessageErrorText:dic[NSLocalizedDescriptionKey]]; }]; } } } // 通话类型 0:视频 1:语音 -(void)doVideoAnswer:(int)dwUserId :(NSString *)lpUserStr { _callType = 0; if ([@"audio" isEqualToString:lpUserStr]) { _callType = 1; } self.brModel.call_type = _callType; [self doVideoAnswerCall:dwUserId]; } - (void)doVideoAnswerCall:(int)dwUserId { [self playRing:@"ring"]; kWeakSelf(self) if(_popView) { return; } UINib *nib = [UINib nibWithNibName:@"BRVideoCallView" bundle:nil]; BRVideoCallView *view = [nib instantiateWithOwner:nil options:nil].firstObject; view.nick.text = APIManager.sharedManager.deviceModel.name; [view.headImg setImageWithURL:[NSURL URLWithString:APIManager.sharedManager.deviceModel.image] placeholer:[UIImage imageNamed:@"icon_girl_head_portrait_1"]]; view.progress.hidden = YES; view.cancelCall.hidden = YES; view.layer.cornerRadius = 10; view.layer.masksToBounds = YES; _popView = [LSTPopView initWithCustomView:view popStyle:LSTPopStyleSmoothFromTop dismissStyle:LSTDismissStyleSmoothToBottom]; _popView.isClickBgDismiss = NO; LSTPopViewWK(_popView) view.hungUpBlock = ^{ [wk__popView dismiss]; [weakself rejectCall:dwUserId]; }; view.pickUpBlock = ^ { [wk__popView dismiss]; [weakself acceptCall:dwUserId]; }; [_popView pop]; } - (void)dismissPopView { if (_popView) { [_popView dismiss]; _popView = nil; } } -(void)showCallDialog:(DeviceModel *)user userId:(int)dwUserId callback:(CancelBlock)callback { [self playRing:@"tones"]; kWeakSelf(self) UINib *nib = [UINib nibWithNibName:@"BRVideoCallView" bundle:nil]; BRVideoCallView *view = [nib instantiateWithOwner:nil options:nil].firstObject; view.nick.text = APIManager.sharedManager.deviceModel.name; [view.headImg setImageWithURL:[NSURL URLWithString:APIManager.sharedManager.deviceModel.image] placeholer:[UIImage imageNamed:@"icon_girl_head_portrait_1"]]; view.progress.hidden = NO; [view.progress startAnimating]; view.cancelCall.hidden = NO; view.pickUp.hidden = YES; view.hungUp.hidden = YES; view.layer.cornerRadius = 10; view.layer.masksToBounds = YES; _popView = [LSTPopView initWithCustomView:view popStyle:LSTPopStyleSmoothFromTop dismissStyle:LSTDismissStyleSmoothToBottom]; _popView.isClickBgDismiss = NO; LSTPopViewWK(_popView) view.cancelBlock = ^{ [wk__popView dismiss]; [weakself cancelCall:dwUserId]; if (callback) { callback(); } }; [_popView pop]; } - (void)acceptCall:(int)dwUserId { [self stopRing]; [self dismissPopView]; [AnyChatPlatform VideoCallControl:BRAC_VIDEOCALL_EVENT_REPLY :dwUserId :0 :0 :0 :nil]; } - (void)rejectCall:(int)dwUserId { [self stopRing]; [self dismissPopView]; [AnyChatPlatform VideoCallControl:BRAC_VIDEOCALL_EVENT_REPLY :dwUserId :GV_ERR_VIDEOCALL_REJECT :0 :0 :nil]; } -(void)cancelCall:(int)dwUserId { [self stopRing]; [self dismissPopView]; [AnyChatPlatform VideoCallControl:BRAC_VIDEOCALL_EVENT_REPLY :dwUserId :GV_ERR_VIDEOCALL_CANCEL :0 :0 :nil]; } //MARK: 响铃的 MP3 - (void)playRing:(NSString *)name { [self stopRing]; AVAudioSession *audioSession = [AVAudioSession sharedInstance]; [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil]; [audioSession setActive:YES error:nil]; NSURL *path = [[NSBundle mainBundle] URLForResource:name withExtension:@"mp3"]; audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:path error:nil]; audioPlayer.numberOfLoops = -1; [audioPlayer play]; } - (void)stopRing { if (audioPlayer) { [audioPlayer stop]; audioPlayer = nil; } } @end