You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

585 lines
18 KiB

//
// BRManager.m
// tongxin
//
// Created by ecell on 2020/11/18.
// Copyright © 2020 xTT. All rights reserved.
//
#import "BRManager.h"
#import <AnyChatCoreSDK/AnyChatCoreSDK.h>
#import "BRVideoCallView.h"
#import <LSTPopView.h>
#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 () <AnyChatNotifyMessageDelegate, AnyChatVideoCallDelegate>
{
AnyChatPlatform *theAnyChat;
AVAudioPlayer *audioPlayer;
}
@property (strong, nonatomic) LSTPopView *popView;
@end
static BRManager* _manager;
static bool _isLogining;
static NSString* _nick;
static NSNumber* _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:(NSNumber *)bairuiId nick:(NSString *) nick {
_bairuiId = bairuiId;
_nick = nick;
[self getSign:@{@"userid": [bairuiId stringValue], @"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.video_id;
videoVC.device = self.device;
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:@"wait_duration"];//wait_duration
[dic setValue:@(self.brModel.distinguishability_width) forKey:@"distinguishability_width"];
[dic setValue:@(self.brModel.distinguishability_heiger) forKey:@"distinguishability_heiger"];
[dic setValue:self.brModel.video_id forKey:@"video_id"];
[UserDefaults setValue:[NSString stringWithFormat:@"%@&%@&%@&%@&%@",@(total),self.brModel.video_id,@(self.brModel.distinguishability_width),@(self.brModel.distinguishability_heiger),@(0)] forKey:VideoTimeAndIDAndWHRecordKey];
[cUser postVideoCallTimeParame:[dic copy] deviceModel:self.device success:^(id responseObject) {
xLog(@"上传视频时间成功");
//MARK: 上传完视频时间后删除存储的 Key
[UserDefaults removeObjectForKey:VideoTimeAndIDAndWHRecordKey];
} failure:^{
xLog(@"上传视频时间失败,重试一次");
}];
}
}
}
// 通话类型 0:视频 1:语音
-(void)doVideoAnswer:(int)dwUserId :(NSString *)lpUserStr {
_callType = 0;
if ([@"audio" isEqualToString:lpUserStr]) {
_callType = 1;
}
WEAKSELF
//声网和菊风共用一个
[cUser getVideoInfoWithDeviceImei:[NSString stringWithFormat:@"br-%d", dwUserId] CallType:@(_callType).intValue Success:^(id responseObject) {
weakSelf.brModel = [BairuiModel mj_objectWithKeyValues:responseObject];
weakSelf.brModel.call_type = _callType;
[weakSelf doVideoAnswerCall:dwUserId];
} failure:^{
}];
}
- (void)doVideoAnswerCall:(int)dwUserId {
[self playRing:@"ring"];
WEAKSELF
_device = [cUser getDeviceWithImei:_brModel.imei];
_brModel.device_username = [NSString stringWithFormat:@"%d", dwUserId];
if(_popView) {
return;
}
UINib *nib = [UINib nibWithNibName:@"BRVideoCallView" bundle:nil];
BRVideoCallView *view = [nib instantiateWithOwner:nil options:nil].firstObject;
view.nick.text = _device.name;
[view.headImg setImageWithURL:[NSURL URLWithString:_device.avator] 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:(User *)user userId:(int)dwUserId callback:(CancelBlock)callback {
[self playRing:@"tones"];
WEAKSELF
UINib *nib = [UINib nibWithNibName:@"BRVideoCallView" bundle:nil];
BRVideoCallView *view = [nib instantiateWithOwner:nil options:nil].firstObject;
view.nick.text = user.name;
[view.headImg setImageWithURL:[NSURL URLWithString:user.avator] 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