// // webRtcPlayerViewController.m // 双子星云手机 // // Created by xd h on 2024/9/2. // #import "webRtcPlayerViewController.h" #import "webRtcPlayerViewController+AdjustBtnFrame.h" #import "webRtcPlayerViewController+AdjustPlayerViewFrame.h" #import "webRtcPlayerViewController+AppDelegate.h" #import "playerSetView.h" @interface webRtcPlayerViewController () { BOOL outputVolumeKVO;/*标记声音监听通知*/ double lastTimestamp;/*最后一帧时间戳*/ NSNumber *lastBytesReceived;/*最后一帧数据量*/ //记录上次 线性增长接收包数 long lasPacketsReceived; //记录上次 总丢包数据 long lastAlllostData; //记录上次 丢包率 double prelostRate; double prelostTimestamp;//计算丢包率时间戳(X秒算一次) BOOL isExitType;//退出云机 NSInteger checkLinkTimerNumber;//0 --2 开始发起重连 NSInteger preDelayedMS;//记录上一次延时数据 控制controlBtn 的图片刷新 非必要 不刷新 NSInteger tryRelinkNum;//重连次数 } @property (nonatomic, copy) NSTimer *playerSecondTimer; // 定时器-控制按钮 @property (nonatomic, assign) RTCIceConnectionState linkState; @property (nonatomic, assign) BOOL didHandleRotation;//第一次处理旋转 @property (nonatomic, assign) BOOL didReportWebRtcOKType;//上报打洞是否成功 @property (nonatomic, assign) BOOL didReportWebRtcFailType;//上报打洞是否成功 @property (nonatomic, strong)playerSetView *playerSetV;//推流设置页 @property (nonatomic, strong)UILabel *testLostLabel;//测试验证丢包率的 @end @implementation webRtcPlayerViewController @synthesize controlBtn; @synthesize isLan; - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. [self.toolBar setHidden:YES]; [self.navigationBar setHidden:YES]; [self.navBarBGView setHidden:YES]; [self.view setBackgroundColor:[UIColor blackColor]]; _webRtcPlayerSessionId = [iTools getNowTimeStampString]; if([DFPlayer sharedPlayer].state == DFPlayerStateBuffering ||[DFPlayer sharedPlayer].state == DFPlayerStatePlaying){ _isCodeSuspendAudioType = YES; [[DFPlayer sharedPlayer] df_pause]; } prelostRate = 0.0; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; // 屏幕常亮 [UIApplication sharedApplication].idleTimerDisabled = YES; [[UIApplication sharedApplication] setStatusBarHidden:YES]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [self noEnablePanRightBack]; [self addKVOObserverFun]; //ksharedAppDelegate.supportScreenRotateType = YES; } - (void)viewDidDisappear:(BOOL)animated{ [super viewDidDisappear:animated]; [self HandleSomethingByExitVC]; } //- (BOOL)shouldAutorotate { // // 根据你的需求来决定是否允许自动旋转 // // 这里我们默认不允许,除非有特定的逻辑允许 // return NO; // 或者根据某个条件返回YES //} #pragma mark 退出事件处理 -(void)HandleSomethingByExitVC { [UIApplication sharedApplication].idleTimerDisabled = NO; [[UIApplication sharedApplication] setStatusBarHidden:NO]; isExitType = YES; if(_mediaStream){ [_mediaStream disconnect]; _mediaStream = nil; } [self enablePanRightBack]; [self removeKVOObserverFun]; ksharedAppDelegate.supportScreenRotateType = NO; ksharedAppDelegate.isPlayerScreenLandscapeType = NO; [self removeNewIndicator]; if(_playerSecondTimer){ [_playerSecondTimer invalidate]; _playerSecondTimer = nil; } _webRtcMsgMod = nil; if(_playerSetV){ [_playerSetV removeFromSuperview]; _playerSetV = nil; } } - (void)setWebRtcMsgMod:(webRtcMsgModel *)webRtcMsgMod { _webRtcMsgMod = webRtcMsgMod; [self beginWebRtcPlayFun]; } #pragma mark 开始拉流 - (void)beginWebRtcPlayFun { if(_mediaStream){ //[_mediaStream disconnect]; //[_mediaStream removeFromSuperview]; //_mediaStream = nil; } //2.客户端开始写日志 [ksharedAppDelegate.WebRtcLogger start]; _mediaStream = [[RTC_OBJC_TYPE(AMediaStream) alloc] initWithFrame:CGRectZero]; [_mediaStream setEventDelegate:self]; [self.view addSubview:_mediaStream]; HLog(@"_mediaStream:%@",_mediaStream) [_mediaStream mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(0.f); make.bottom.mas_equalTo(0.f); make.right.mas_equalTo(0.f); make.top.mas_equalTo(0.f); }]; //判断是否是全屏 BOOL fullscreenType = [HWDataManager getBoolWithKey:Consn_player_full_screen_show]; NSInteger curResolution = [HWDataManager getIntegerWithKey:Const_cloudPhone_cur_resolution]; CGFloat curWidth = 720.0; CGFloat curHeight = 1280.0; if(curResolution == 0 || curResolution == 1){ curWidth = 720.0; curHeight = 1280.0; } else{ curWidth = 1080.0; curHeight = 1920.0; } CGSize phoneSize = CGSizeMake(curWidth, curHeight); //云机分辨率被改成 720.0, 1280.0 // if(ksharedAppDelegate.couldPhone_W_PHONE == 720 && ksharedAppDelegate.couldPhone_H_PHONE == 1280) {//云机可能存在的分辨率 // phoneSize = CGSizeMake(720.0, 1280.0); // } if(fullscreenType){ phoneSize = [RCCommandHelp commondToSetFullScreenPhoneSizeBySize]; } [self linkWebRtcFunWithSize:phoneSize]; [self initBaseUIFun]; [self setTimerCountDown]; [self showNewIndicatorWithCanBack:YES canTouch:NO]; } #pragma mark 链接webrtc - (void)linkWebRtcFunWithSize:(CGSize)phoneSize { webrtcServerModel * webrtcServerMod = ksharedAppDelegate.bestWebrtcServerModel; //链接用 NSString *signallingUrl = [[NSString alloc] initWithFormat:@"%@:%@",webrtcServerMod.signallingIp,webrtcServerMod.signallingPort]; NSURL *url = [NSURL URLWithString:signallingUrl]; //ice用 NSString *iceUrl = [[NSString alloc] initWithFormat:@"%@:%@",webrtcServerMod.turnIp,webrtcServerMod.turnPort]; NSMutableDictionary *ice = [NSMutableDictionary new]; if(iceUrl){ [ice setValue:iceUrl forKey:@"CHINANET"]; [ice setValue:iceUrl forKey:@"CMNET"]; [ice setValue:iceUrl forKey:@"UNICOM"]; } NSString *roomName = _webRtcMsgMod.data.uniqueIdentifier; NSInteger cardDensity = 320;//480; //判断是否是全屏 BOOL fullscreenType = [HWDataManager getBoolWithKey:Consn_player_full_screen_show]; if(fullscreenType){ //cardDensity = 380; //cardDensity = 320; //cardDensity = 480; } //码率根据网络设置 wifi 8M 移动网络 4M ->改为 4M 2M NSInteger bitrate = 4*1024; if([AFNetworkReachabilityManager sharedManager].isReachableViaWWAN){ bitrate = 2*1024; } //1.盒子开始写20秒日志 //start 拉流前调用设置本次拉流记录推流端日志到指定文件与记录时间 秒 单位。 //filePathName = /sdcard/webrtc_box.log captureTime = 30s [_mediaStream setCardLogToFile:@"/sdcard/webrtc_box.log" captureTime:@"20"]; NSString *logstr = [[NSString alloc] initWithFormat:@"webRtcPlayer start link--%@",signallingUrl]; [cachesFileManager writeLogsWithMsg:logstr]; //2.客户端开始写日志 [ksharedAppDelegate.WebRtcLogger start]; NSString* curToken = @"vclusters"; BOOL isImageFor144Orlater = [HWDataManager getBoolWithKey:stringKeyAddSn(Const_image_version_for_new_token)]; if(isImageFor144Orlater || ksharedAppDelegate.isImageFor144Orlater) { curToken = @"mediakit"; } NSInteger result = [_mediaStream start:url ice:ice sn:roomName direct:0 fmt:1//1(h264) 5(h265) videoWidth:(NSInteger)phoneSize.width videoHeight:(NSInteger)phoneSize.height fps:30 bitrate:bitrate//3200//3000 cardWidth:(NSInteger)phoneSize.width//0//1080//0 cardHeight:(NSInteger)phoneSize.height//0//1920//0 cardDensity:cardDensity token:curToken]; HLog(@"result:%ld",result) [_mediaStream setShouldGetStats:YES]; //清晰度码率最大上限 流畅1800 标清2200 高清2800 跟上面的 bitrate是同一个意思 //[_mediaStream setMaxBitrate:@2800]; } #pragma mark 重连 - (void)relinkWebRtcFun { // if(_linkState == RTCIceConnectionStateConnected // || _linkState == RTCIceConnectionStateCompleted) // {//链接中 不处理重连事件 // HLog(@"链接中 不处理重连事件") // return; // } if(isExitType){ return; } HLog(@"发起重连 ......") [cachesFileManager writeLogsWithMsg:@"webRtcPlayer relinkWebRtcFun"]; KWeakSelf mainBlock(^{ [weakSelf showNewIndicatorWithCanBack:YES canTouch:NO]; NSInteger curResolution = [HWDataManager getIntegerWithKey:Const_cloudPhone_cur_resolution]; CGFloat curWidth = 720.0; CGFloat curHeight = 1280.0; if(curResolution == 0 || curResolution == 1){ curWidth = 720.0; curHeight = 1280.0; } else{ curWidth = 1080.0; curHeight = 1920.0; } //判断是否是全屏 BOOL fullscreenType = [HWDataManager getBoolWithKey:Consn_player_full_screen_show]; CGSize phoneSize = CGSizeMake(curWidth, curHeight); if(fullscreenType){ phoneSize = [RCCommandHelp commondToSetFullScreenPhoneSizeBySize]; } //客户端停止写日志 [ksharedAppDelegate.WebRtcLogger stop]; [weakSelf linkWebRtcFunWithSize:phoneSize]; }); } #pragma mark 重连 - (void)relinkWebRtcFunByBecomeActive{ //[self.mediaStream disconnect];// 断开会自动重连 防止多路流的清理 [self.mediaStream enterForeground]; [self resumeStream]; } #pragma mark 初始化其他UI - (void)initBaseUIFun { if(_bottomContrView){ [_bottomContrView removeFromSuperview]; _bottomContrView = nil; } _bottomContrView = [[webRtcPlayerBottomContrView alloc] init]; [self.view addSubview:_bottomContrView]; [self getPlayerBottomNavShowOrHidefun]; KWeakSelf _bottomContrView.didClickButtonFun = ^(NSInteger tag) { [weakSelf didClickBottomFunBy:tag]; }; /*控制按钮*/ if(controlBtn){ [controlBtn removeFromSuperview]; controlBtn = nil; } UIImage *driftBtnImage = [UIImage imageNamed:@"you_icon"]; controlBtn = [[UIButton alloc] init]; [controlBtn setBackgroundColor:[UIColor clearColor]]; [controlBtn setBackgroundImage:driftBtnImage forState:(UIControlStateNormal)]; [controlBtn addTarget:self action:@selector(controlBtnPressed:) forControlEvents:(UIControlEventTouchUpInside)]; [self.view addSubview:controlBtn]; //拖拽事件等 UIPanGestureRecognizer *gester = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(controlBtnPanGestureCallback:)]; [controlBtn addGestureRecognizer:gester]; //gester.delegate = self; [self initPointForControlBtnFun]; _testLostLabel = [[UILabel alloc] init]; _testLostLabel.textColor = [UIColor greenColor]; //_testLostLabel.textAlignment = NSTextAlignmentCenter; _testLostLabel.font = [UIFont systemFontOfSize:14.0]; _testLostLabel.numberOfLines = 0; [self.view addSubview:_testLostLabel]; [_testLostLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(20); make.right.mas_equalTo(-20); make.top.mas_equalTo(100.f); }]; } #pragma mark 设置 controlBtn 的初始位置 - (void)initPointForControlBtnFun { CGFloat h_w_controlBtn = 60.f; /*区分横竖屏*/ if (_mediaStream.hw_w > _mediaStream.hw_h){ [controlBtn setFrame:CGRectMake((_mediaStream.hw_w - h_w_controlBtn)/2.f, _mediaStream.hw_h - h_w_controlBtn - 20.f, h_w_controlBtn, h_w_controlBtn)]; }else{ //默认居右 //[mPlayerView.controlBtn setFrame:CGRectMake(mPlayerView.width - h_w_controlBtn - 20.f, (SCREEN_H - h_w_controlBtn)/2.f, h_w_controlBtn, h_w_controlBtn)]; //默认居左 [controlBtn setFrame:CGRectMake( h_w_controlBtn + 10.f, (SCREEN_H - h_w_controlBtn)/2.f, h_w_controlBtn, h_w_controlBtn)]; } } #pragma mark 定时器 - (void)setTimerCountDown { HLog(@"开启一个"); if (_playerSecondTimer) { // 取消定时器 [_playerSecondTimer invalidate]; _playerSecondTimer = nil; } // 初始化值计时数据 //self.adjustTime = 1; //self.concentTime = [iTools getNowTimeStamp]; _playerSecondTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(timerChange) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:_playerSecondTimer forMode:NSRunLoopCommonModes]; } #pragma mark 定时器响应事件 - (void)timerChange { [self extensionAdjustBtnFrameCheckAdjustTime];// 1、悬浮球3s后 自动靠边隐藏 //[self checkConcentTime];// 3、30s之后 没有收到拉流数据 自动断开链接 checkLinkTimerNumber ++; if(checkLinkTimerNumber == 3){ checkLinkTimerNumber = 0; if(_linkState != RTCIceConnectionStateConnected && _linkState != RTCIceConnectionStateCompleted){ if(!_didReportWebRtcFailType){//还没上报过通道链接情况 tryRelinkNum ++; if(tryRelinkNum == 2){ tryRelinkNum = 0; _didReportWebRtcFailType = YES; // globalBlock(^{ // [[addLogObject shareInstance] gotoAddLogFunBySuccess:^(NSString * _Nonnull key) { // [[webRtcManager shareManager] reportWebRtcRePoportTypeIsChannel:NO withStats:nil withSessionId:self->_webRtcPlayerSessionId withLogKey:key]; // }]; // }); //[self showLinkPhoneErrorFun]; //检测盒子心跳 [self checkBoxHeartbeatFun]; } } [self relinkWebRtcFun]; } } } #pragma mark 云机连接不上 - (void)showLinkPhoneErrorFun { //[[addLogObject shareInstance] gotoAddLogFun]; KWeakSelf [[errorAlertTool shareInstance] showNetErrorAlertFun:5 didClickBut:^(NSInteger tag) { if(tag == 1){ [weakSelf relinkWebRtcFun]; } else if(tag == 5){ [weakSelf exitCloudPhoneFun]; } }]; } #pragma mark 控制按钮点击事件 - (void)controlBtnPressed:(UIButton*)but { if(_playerSetV){ [ksharedAppDelegate.window addSubview:_playerSetV]; [_playerSetV mas_remakeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(0); make.right.mas_equalTo(0); make.top.mas_equalTo(0.f); make.bottom.mas_equalTo(0.f); }]; [_playerSetV setAllSwitchFun]; return; } _playerSetV = [[playerSetView alloc] init]; [ksharedAppDelegate.window addSubview:_playerSetV]; [_playerSetV mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(0); make.right.mas_equalTo(0); make.top.mas_equalTo(0.f); make.bottom.mas_equalTo(0.f); }]; KWeakSelf _playerSetV.didClickButtonFun = ^(NSInteger tag) { switch (tag) { case 1: {//设置分辨率 720 [weakSelf didClickSetResolution720Fun]; } break; case 2: {//设置分辨率 1080 [weakSelf didClickSetResolution1080Fun]; } break; case 200: {//截图 [weakSelf didClickshortCatFun]; } break; #pragma mark 重启盒子 case 202: { [weakSelf didClickRestartFun]; } break; case 100: {//退出云机 [weakSelf exitCloudPhoneFun]; } break; case 201: { BOOL fullscreenType = [HWDataManager getBoolWithKey:Consn_player_full_screen_show]; if(fullscreenType){ [weakSelf showOpenTVP2PFun]; } else{ [weakSelf openTvShowFun]; } } break; case 301: { weakSelf.controlBtn.userInteractionEnabled = NO; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ weakSelf.controlBtn.userInteractionEnabled = YES; }); [weakSelf showCloseTVP2PFun]; } break; default: break; } }; } #pragma mark 设置分辨率 720*1280 - (void)didClickSetResolution720Fun { CGFloat tempRate = 0.0; NSInteger cardDensity = 320;//480; CGSize size = CGSizeMake(720.0, 1280.0); if(isLan){ size = CGSizeMake(1280.0, 720.0); } [self setCardSize:(NSInteger)size.width cardHeight:(NSInteger)size.height cardDensity:cardDensity]; tempRate = size.width/size.height; if (tempRate > 1) {/*横屏*/ [self setLanMas_makeWithImageRate:tempRate]; }else{/*竖屏*/ [self setPoMas_makeWithImageRate:tempRate]; } } #pragma mark 设置分辨率 1080*1920 - (void)didClickSetResolution1080Fun { CGFloat tempRate = 0.0; NSInteger cardDensity = 320;//480; CGSize size = CGSizeMake(1080.0, 1920.0); if(isLan){ size = CGSizeMake(1920.0, 1080.0); } [self setCardSize:(NSInteger)size.width cardHeight:(NSInteger)size.height cardDensity:cardDensity]; tempRate = size.width/size.height; if (tempRate > 1) {/*横屏*/ [self setLanMas_makeWithImageRate:tempRate]; }else{/*竖屏*/ [self setPoMas_makeWithImageRate:tempRate]; } } #pragma mark 点击了截图 - (void)didClickshortCatFun { [[webRtcManager shareManager] screenshotInCloudPhoneFun]; } #pragma mark 点击了重启云机 - (void)didClickRestartFun { KWeakSelf /*弹窗提示重启*/ ComontAlretViewController *nextVC = [[ComontAlretViewController alloc] initWithTiTle:NSLocalizedString(@"my_set_no_restart_phone_tips",nil) msg:@"" imageStr:@"" cancelTitle:NSLocalizedString(@"other_cancel",nil) okTitle:NSLocalizedString(@"my_set_no_restart_phone_btn_ok",nil) isOkBtnHighlight:NO didClickOk:^{ [weakSelf needToRebootFun]; //提示语 [[iToast makeText:NSLocalizedString(@"player_link_rebooting_Tips",nil)] show]; } didClickCancel:^{ }]; nextVC.modalPresentationStyle = UIModalPresentationCustom; [self presentViewController:nextVC animated:YES completion:^{ nextVC.view.superview.backgroundColor = [UIColor clearColor]; }]; } #pragma mark p2p通道 重启云机 - (void)needToRebootFun { [cachesFileManager writeLogsWithMsg:@"webRtcPlayer click Reboot"]; [[webRtcManager shareManager] needToRebootFun]; [self startForceStartTimerFun]; [self pauseStream]; [webRtcManager shareManager].isRebootIngType = YES; [self showNewIndicatorWithCanBack:YES canTouch:NO]; } #pragma mark X 秒后检查是否软件重启成功 - (void)startForceStartTimerFun { KWeakSelf //1. 5秒后跟硬件发起硬重启 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [weakSelf updateForceStartFun]; }); //2. 20秒后尝试重连 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [weakSelf relinkWebRtcFun]; [[webRtcManager shareManager] relinkWebRtcFun]; }); } #pragma mark 需要强制重启 - (void)updateForceStartFun{ NSString* curSn = ksharedAppDelegate.DeviceThirdIdMod.data.changeSn; NSMutableDictionary *paraDict = [NSMutableDictionary dictionary]; [paraDict setValue:curSn forKey:@"sn"]; [paraDict setValue:[NSNumber numberWithBool:YES] forKey:@"isForceStart"]; [[netWorkManager shareInstance] CommonPostCallBackCode:updateForceStart Parameters:paraDict success:^(id _Nonnull responseObject) { SuperModel *model = [[SuperModel alloc] initWithDictionary:responseObject error:nil]; if (model.status == 0) { } else { } } failure:^(NSError * _Nonnull error) { HLog(@"%@", error); }]; } #pragma mark 退出云机 - (void)exitCloudPhoneFun { [cachesFileManager writeLogsWithMsg:@"webRtcPlayer click exitCloudPhone"]; //[self setShowImgAndVoiceTypeFun:NO]; if(isLan){//保证竖屏 [self player_rotateToInterfaceOrientation:UIInterfaceOrientationPortrait]; } [self.navigationController popViewControllerAnimated:YES]; ksharedAppDelegate.supportScreenRotateType = NO; [self HandleSomethingByExitVC]; if(_isCodeSuspendAudioType){ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [[DFPlayer sharedPlayer] df_play]; }); } } #pragma mark 显示关闭投屏提示语 - (void)showOpenTVP2PFun{ /*弹窗提示TV投屏*/ ComontAlretViewController *nextVC = [[ComontAlretViewController alloc] initWithTiTle:NSLocalizedString(@"File_upload_Record_clear_Tip_title",nil) msg:NSLocalizedString(@"cloudPhone_fullscreen_tvshow_tip",nil) imageStr:@"" cancelTitle:NSLocalizedString(@"other_cancel",nil) okTitle:NSLocalizedString(@"my_set_TVP2P_Open_sure",nil) isOkBtnHighlight:YES didClickOk:^{ [self openTvShowFun]; //关闭全屏屏 [HWDataManager setBoolWithKey:Consn_player_full_screen_show value:NO]; [self setPlayerFullScreenNotFun]; [self->_playerSetV handleResolutionUIFun]; } didClickCancel:^{ }]; nextVC.modalPresentationStyle = UIModalPresentationCustom; [self presentViewController:nextVC animated:YES completion:^{ nextVC.view.superview.backgroundColor = [UIColor clearColor]; }]; } #pragma mark 开始投屏 - (void)openTvShowFun { self.controlBtn.userInteractionEnabled = NO; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self->controlBtn.userInteractionEnabled = YES; }); [[webRtcManager shareManager] onTvFun]; [[iToast makeText:NSLocalizedString(@"cloudPhone_TV_show_tip",nil)] show]; //数据埋点 [[netWorkManager shareInstance] DataEmbeddingPointBy:3 withEventValue:@"Cloud_tv"]; } #pragma mark 显示关闭投屏提示语 - (void)showCloseTVP2PFun{ /*弹窗提示TV投屏*/ ComontAlretViewController *nextVC = [[ComontAlretViewController alloc] initWithTiTle:NSLocalizedString(@"my_set_no_close_TV_p2p_tip",nil) msg:@"" imageStr:@"" cancelTitle:NSLocalizedString(@"other_cancel",nil) okTitle:NSLocalizedString(@"my_set_TVP2P_Open_sure",nil) isOkBtnHighlight:YES didClickOk:^{ [self gotoCloseTVP2PFun]; } didClickCancel:^{ //HLog(@"2222"); }]; nextVC.modalPresentationStyle = UIModalPresentationCustom; [self presentViewController:nextVC animated:YES completion:^{ nextVC.view.superview.backgroundColor = [UIColor clearColor]; }]; } #pragma mark 确认开始TV投屏 -(void)gotoCloseTVP2PFun { [[webRtcManager shareManager] offTvFun]; } #pragma mark 挤下线功能 -(void)offlineOtherPhoneFun { NSString *curOaidStr = [RcGameWQKeyChain getOaidStringFun]; if(!curOaidStr){ curOaidStr = @""; } NSString *commondStr = [[NSString alloc] initWithFormat:@"{\"type\":\"login\",\"value\":\"%@\"}",curOaidStr]; [self send_dataInPlayer:commondStr]; } #pragma mark 单点登录被挤下线弹框 - (void)LogoutByOtherFun:(NSString*)oaid { if(logoutAlertVC){ return; } [cachesFileManager writeLogsWithMsg:@"webRtcPlayer LogoutByOtherFun"]; NSString *curOaidStr = [RcGameWQKeyChain getOaidStringFun]; if(oaid && oaid.length >0 && [oaid isEqualToString:curOaidStr]){ return; } //[self didReceiveLogoutMsgFun]; //yyyy-MM-dd HH:mm:ss NSString*dateStr = [iTools getNowTimeString2]; if(dateStr && dateStr.length == 19){ dateStr = [dateStr substringWithRange:NSMakeRange(11, 5)]; } NSString *LogoutTimerStr = [[NSString alloc] initWithFormat:@"%@%@%@",NSLocalizedString(@"single_sign_on_Tips_one",nil),dateStr,NSLocalizedString(@"single_sign_on_Tips_two",nil)]; NSString * loginAgainStr = NSLocalizedString(@"single_sign_on_login_again",nil); BOOL isOkBtnHighlight = YES; if(!ksharedAppDelegate.DeviceThirdIdMod.data.isPrivacyMode){ loginAgainStr = @""; isOkBtnHighlight = NO; } KWeakSelf if(ksharedAppDelegate.isDidShowPwdType){ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [weakSelf LogoutByOtherFun:oaid]; HLog(@"weakSelf LogoutByOtherFun") }); return; } //被挤下线 停止拉流 [self pauseStream]; if(isLan){//保证竖屏 [self player_rotateToInterfaceOrientation:UIInterfaceOrientationPortrait]; } //退出推流页 [self.navigationController popViewControllerAnimated:NO]; //与安卓保存一致 tabbar 退倒nas页 // [ksharedAppDelegate.mainTabBar setSelectedIndex:0]; [self HandleSomethingByExitVC]; /*弹窗提示重启*/ //KWeakSelf logoutAlertVC = [[ComontAlretViewController alloc] initWithTiTle:NSLocalizedString(@"single_sign_on_Tips_logout",nil) msg:LogoutTimerStr imageStr:@"" cancelTitle:NSLocalizedString(@"single_sign_on_exit",nil) okTitle:loginAgainStr isOkBtnHighlight:isOkBtnHighlight didClickOk:^{ self->logoutAlertVC = nil; [[NSNotificationCenter defaultCenter] postNotificationName:lockBypwdNotification object:nil]; } didClickCancel:^{ //exit(0);/*强制退出app*/ }]; logoutAlertVC.modalPresentationStyle = UIModalPresentationCustom; logoutAlertVC.view.backgroundColor = [UIColor blackColor]; [[iTools appRootViewController] presentViewController:logoutAlertVC animated:YES completion:^{ self->logoutAlertVC.view.superview.backgroundColor = [UIColor clearColor]; }]; } #pragma mark 底部按钮事件 - (void)didClickBottomFunBy:(NSInteger)tag { int keyType = 0; if(tag == 1){//task keyType = 187; } else if(tag == 2){//home keyType = 3; } else if(tag == 3){//back keyType = 4; } if(keyType > 0){ [self didClickKeyEventFunBy:keyType]; } } #pragma mark 按键事件 // home 3 back 4 task 187 volumeUp 24 volumeDown 25 - (void)didClickKeyEventFunBy:(int)keyType { [_mediaStream sendKey:keyType]; } #pragma mark 云机交互的消息发送 走P2P通道 -(void)send_data:(NSString*)commandStr { [[webRtcManager shareManager] send_data:commandStr]; } #pragma mark 云机交互的消息发送 走音视频推拉流通道 -(void)send_dataInPlayer:(NSString*)commandStr { [_mediaStream sendData:commandStr]; } #pragma mark -- /*底部导航栏开关通知*/ - (void)getPlayerBottomNavShowOrHidefun { BOOL haveShowBottonNavType = ![HWDataManager getBoolWithKey:Consn_player_Nav_hide]; if(haveShowBottonNavType){ _bottomContrView.hidden = NO; } else{ _bottomContrView.hidden = YES; } } #pragma mark -- /*全面屏开关通知*/ - (void)setPlayerFullScreenNotFun { BOOL fullscreenType = [HWDataManager getBoolWithKey:Consn_player_full_screen_show]; CGFloat tempRate = 0.0; NSInteger cardDensity = 320;//480; //重新设置分辨率 if(fullscreenType){ //cardDensity = 380;//480;//422;//380;//460; CGSize size = [RCCommandHelp commondToSetFullScreenPhoneSizeBySize]; if(isLan){ if(size.width < size.height){ size = CGSizeMake(size.height,size.width); } } [self setCardSize:size.width cardHeight:size.height cardDensity:cardDensity]; tempRate = (size.width *1.0)/(size.height *1.0); } else{ NSInteger curResolution = [HWDataManager getIntegerWithKey:Const_cloudPhone_cur_resolution]; CGFloat curWidth = 720.0; CGFloat curHeight = 1280.0; if(curResolution == 0 || curResolution == 1){ curWidth = 720.0; curHeight = 1280.0; } else{ curWidth = 1080.0; curHeight = 1920.0; } CGSize size = CGSizeMake(curWidth, curHeight); if(isLan){ size = CGSizeMake(curHeight, curWidth); } [self setCardSize:(NSInteger)size.width cardHeight:(NSInteger)size.height cardDensity:cardDensity]; tempRate = size.width/size.height; } //dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ if (tempRate > 1) {/*横屏*/ [self setLanMas_makeWithImageRate:tempRate]; }else{/*竖屏*/ [self setPoMas_makeWithImageRate:tempRate]; } // }); } #pragma mark -- /*推流中修改卡的分辨率*/ - (void)setCardSize:(NSInteger)cardWidth cardHeight:(NSInteger)cardHeight cardDensity:(NSInteger)cardDensit { if(isLan){ HLog(@"云机屏幕 设置 宽:%ld 高:%ld",cardHeight,cardWidth); [_mediaStream setCardSize:cardHeight cardHeight:cardWidth cardDensity:cardDensit]; [_mediaStream setVideoSize:cardHeight videoHeight:cardWidth frameRate:0]; } else{ HLog(@"云机屏幕 设置 宽:%ld 高:%ld",cardWidth,cardHeight); [_mediaStream setCardSize:cardWidth cardHeight:cardHeight cardDensity:cardDensit]; [_mediaStream setVideoSize:cardWidth videoHeight:cardHeight frameRate:0]; } } #pragma mark -- /*通知添加与移除*/ - (void)addKVOObserverFun { outputVolumeKVO = YES; [[AVAudioSession sharedInstance] addObserver:self forKeyPath:@"outputVolume" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:(void *)[AVAudioSession sharedInstance]]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getPlayerBottomNavShowOrHidefun) name:getPlayerBottomNavNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setPlayerFullScreenNotFun) name:setPlayerFullScreenNotification object:nil]; //监听系统 前后台事件 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:UIApplicationWillTerminateNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; //输入密码完成 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didInpuPwdOkFun) name:didInputPWDNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkStateChange:) name:NetWorkChangeNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(relinkWebRtcFun) name:didPingBestWebRtcIPRoomNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(exitCloudPhoneFun) name:needToPoPCloudPhoneVCNotification object:nil]; } - (void)removeKVOObserverFun { if (outputVolumeKVO) { [[AVAudioSession sharedInstance] removeObserver:self forKeyPath:@"outputVolume" context:(void *)[AVAudioSession sharedInstance]]; outputVolumeKVO = NO; } [[NSNotificationCenter defaultCenter] removeObserver:self]; } #pragma mark 系统音量键监听 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if(context == (__bridge void *)[AVAudioSession sharedInstance]) { /*音量开关打开时 允许发送指令 否则直接返回*/ float newValue = [[change objectForKey:@"new"] floatValue]; float oldValue = [[change objectForKey:@"old"] floatValue]; //HLog(@"音量 --old: %f ---new: %f",oldValue,newValue) if (newValue > oldValue) { HLog(@"\n-----音量增加"); [self didClickKeyEventFunBy:24]; } else { HLog(@"\n-----音量降低"); [self didClickKeyEventFunBy:25]; } } } #pragma - mark - 监听网络变化 - (void)networkStateChange:(NSNotification *)notification { /*处理*/ KWeakSelf switch ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus) { case AFNetworkReachabilityStatusUnknown:/*网络状态未知*/ { ; } break; case AFNetworkReachabilityStatusNotReachable:/*网络不可用*/ { } break; case AFNetworkReachabilityStatusReachableViaWWAN:/*流量*/ { mainBlock(^{ [weakSelf.mediaStream setMaxBitrate:[NSNumber numberWithInteger:2*1024]]; }); } break; case AFNetworkReachabilityStatusReachableViaWiFi:/*WiFi*/ { mainBlock(^{ [weakSelf.mediaStream setMaxBitrate:[NSNumber numberWithInteger:4*1024]]; }); } break; default: break; } } #pragma mark 监听到云机的宽高以及屏幕方向 - (void)handlUIAfterGetCloudPhoneVideoWidth:(int)videoWidth videoHeight:(int)videoHeight rotation:(int)rotation { HLog(@"云机屏幕 回调 宽:%d 高:%d 横竖屏:%d",videoWidth,videoHeight,rotation); CGFloat curRate = (CGFloat)videoWidth/(CGFloat)videoHeight; if(lastVideoWHRate == curRate){ return; } didAdjusBtnType = NO; if(rotation == 0){//竖屏 //切换到竖屏 isLan = NO; [self player_rotateToInterfaceOrientation:UIInterfaceOrientationPortrait]; [self setPoMas_makeWithImageRate:curRate]; } else if(rotation == 1){//横屏 //切换到横屏屏 isLan = YES; [self player_rotateToInterfaceOrientation:UIInterfaceOrientationLandscapeRight]; [self setLanMas_makeWithImageRate:curRate]; } _didHandleRotation = YES; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self extensionAdjustBtnFrameCheckAdjustTime]; }); } #pragma mark WebRTC 回调 MediaStreamClientEventsDelegate #pragma mark - 宽高变化 -(void)onFrameResolutionChangedFromPeerName:(NSString*)peerName videoWidth:(int)videoWidth videoHeight:(int)videoHeight rotation:(int)rotation { HLog(@"推拉流 onFrameResolutionChangedFromPeerName:%@---%d---%d--%d",peerName,videoWidth,videoHeight,rotation) [cachesFileManager writeLogsWithMsg:[[NSString alloc] initWithFormat:@"webRtcPlayer onFrameResolutionChangedFromPeerName:%@",peerName]]; HLog(@"ok _mediaStream:%@",_mediaStream) mainBlock(^{ [self handlUIAfterGetCloudPhoneVideoWidth:videoWidth videoHeight:videoHeight rotation:rotation]; }); } //code 0 成功 1失败 -(void)onAuthResultFromPeerName:(NSString*)peerName code:(int)code descriptions:(NSString*)descriptions { HLog(@"onAuthResultFromPeerName:%@---%d---%@",peerName,code,descriptions) [cachesFileManager writeLogsWithMsg:[[NSString alloc] initWithFormat:@"webRtcPlayer onAuthResultFromPeerName:%d--%@",code,descriptions]]; } #pragma mark 链接发生变化 -(void)onChangeConnectionStateFromPeerName:(NSString*)peerName didChangeIceConnectionState:(RTCIceConnectionState)state { HLog(@"推拉流 onChangeConnectionStateFromPeerName: state:%ld",state) [cachesFileManager writeLogsWithMsg:[[NSString alloc] initWithFormat:@"webRtcPlayer onChangeConnectionStateFromPeerName:%ld",state]]; _linkState = state; switch (state) { case RTCIceConnectionStateConnected:{ //链接成功 mainBlock(^{ [self removeNewIndicator]; //客户端停止写日志 [ksharedAppDelegate.WebRtcLogger stop]; }); //PC断可能开启键盘透传 每次进入先关闭 NSString *str = [RCCommandHelp commandCloseLoaclKeyboad]; [[webRtcManager shareManager] send_data:str]; } break; case RTCIceConnectionStateCompleted: //链接完成 break; case RTCIceConnectionStateFailed: case RTCIceConnectionStateDisconnected: case RTCIceConnectionStateClosed:{ if(!_didReportWebRtcFailType && state == RTCIceConnectionStateFailed){//还没上报过通道链接情况 _didReportWebRtcFailType = YES; // globalBlock(^{ // [[addLogObject shareInstance] gotoAddLogFunBySuccess:^(NSString * _Nonnull key) { // [[webRtcManager shareManager] reportWebRtcRePoportTypeIsChannel:NO withStats:nil withSessionId:self->_webRtcPlayerSessionId withLogKey:key]; // }]; // }); } //链接关闭 [self relinkWebRtcFun]; } break; default: break; } } - (void)dataChannelDidChangeFromPeerName:(NSString*)peerName State:(RTCDataChannelState)state; { HLog(@"推拉流 dataChannelDidChangeFromPeerName: state:%ld",state) [cachesFileManager writeLogsWithMsg:[[NSString alloc] initWithFormat:@"webRtcPlayer dataChannelDidChangeFromPeerName:%ld",state]]; switch (state) { case RTCDataChannelStateConnecting: { } break; case RTCDataChannelStateOpen: { //链接成功 [self offlineOtherPhoneFun]; } break; case RTCDataChannelStateClosing: { } break; case RTCDataChannelStateClosed: { //链接断开 [self relinkWebRtcFun]; } break; default: break; } } -(void)onChannelDataFromPeerName:(NSString*)peerName buffer:(RTC_OBJC_TYPE(RTCDataBuffer) *)buffer { //HLog(@"onIceConnectedFromPeerName:%@",buffer.data); if(buffer && buffer.data){ KWeakSelf mainBlock(^{ [weakSelf handleWebRtcMsgResponseBy:buffer.data]; }); } } -(void)didGetStats:(NSString*)peerName stats:(RTC_OBJC_TYPE(RTCStatisticsReport) *)stats { if(!_didReportWebRtcOKType){ [[webRtcManager shareManager] reportWebRtcRePoportTypeIsChannel:NO withStats:stats withSessionId:self->_webRtcPlayerSessionId withLogKey:@""]; _didReportWebRtcOKType = YES; _didReportWebRtcFailType = NO;//链接成功后 失败要重新上报 } //NSString *selectedCandidatePairId = nil; /*延时数据*/ NSNumber *currentRoundTripTime = nil; //线性增长接收包数 long packetsReceived = 0; //视频丢包数据 long videolostData = 0; //音频丢包数据 long audiolostData = 0; //总丢包数据 long alllostData = 0; //每秒帧数 ----界面展示的帧率 NSInteger framesPerSecond = 0; //计算传输速度 long preReceive = 0; KWeakSelf for (NSString *key in [stats.statistics allKeys]) { RTCStatistics *rtcStatistics = [stats.statistics objectForKey:key]; //HLog(@"hxd11111---->%@",rtcStatistics.type); if ([rtcStatistics.type isEqualToString:@"transport"]) { //HLog(@"传输数据---->%@",rtcStatistics.values); double timestamp = rtcStatistics.timestamp_us; NSNumber *bytesReceived = (NSNumber *)[rtcStatistics.values objectForKey:@"bytesReceived"]; NSNumber *packetsReceivedNumber = (NSNumber *)[rtcStatistics.values objectForKey:@"packetsReceived"]; packetsReceived = [packetsReceivedNumber longValue]; if (lastTimestamp > 0) { long diffReceive = [bytesReceived longValue] - [lastBytesReceived longValue]; double diffTime = timestamp - lastTimestamp; preReceive = (diffReceive / diffTime) * 1000000; }else{ lastTimestamp = timestamp; lastBytesReceived = bytesReceived; } //selectedCandidatePairId = (NSString *)[rtcStatistics.values objectForKey:@"selectedCandidatePairId"]; } /*丢包数据*/ if ([rtcStatistics.type isEqualToString:@"inbound-rtp"]) { NSString *kind = (NSString *)[rtcStatistics.values objectForKey:@"kind"]; if([kind isEqualToString:@"video"]){ NSNumber*videolostDataNumber = (NSNumber *)[rtcStatistics.values objectForKey:@"packetsLost"]; videolostData = [videolostDataNumber longValue]; HLog(@"丢包率 视频频%@",videolostDataNumber) NSNumber*framesPerSecondNumber = (NSNumber *)[rtcStatistics.values objectForKey:@"framesPerSecond"]; framesPerSecond = [framesPerSecondNumber integerValue]; } else if([kind isEqualToString:@"audio"]){ NSNumber*audiolostDataNumber = (NSNumber *)[rtcStatistics.values objectForKey:@"packetsLost"]; audiolostData = [audiolostDataNumber longValue]; HLog(@"丢包率 音频%@",audiolostDataNumber) } } for (NSString *keyin in [rtcStatistics.values allKeys]) { if ([keyin isEqualToString:@"currentRoundTripTime"]){ /*延时数据*/ currentRoundTripTime = (NSNumber*)[rtcStatistics.values objectForKey:@"currentRoundTripTime"]; //[self updateAutoRateAndNetWorkStatesWithDelatyMS:(NSInteger)currentRoundTripTime.floatValue*1000]; break; } } } //网络延迟, 丢包率,FPS,网速 分辨率 流量 //延时数据 NSInteger delayedMS = (NSInteger)(currentRoundTripTime.floatValue*1000); //计算上次报道到这一次的丢包率---------界面展示百分比丢包率 double curlostTimestamp = [iTools getNowTimeStamp]; if(prelostTimestamp == 0 || (curlostTimestamp - prelostTimestamp >= 3)){ long allPacketsReceived = packetsReceived - lasPacketsReceived; if(allPacketsReceived < 0){//异常处理 lastAlllostData = 0; lasPacketsReceived = 0; prelostRate = 0; } else{ alllostData = audiolostData + videolostData; double NsecondLostData = (alllostData - lastAlllostData) *1.0; double NsecondReceivedData = (allPacketsReceived + (alllostData - lastAlllostData)); if(NsecondReceivedData > 0){ double lostRate = (NsecondLostData / NsecondReceivedData) *100; //记录上一次丢包数 lastAlllostData = alllostData; //记录上一次接收包数 lasPacketsReceived = packetsReceived; prelostRate = lostRate; prelostTimestamp = curlostTimestamp; } //FPS // __block NSString*lostDataStr = [[NSString alloc] initWithFormat:@"总包数:%ld --总丢包数:%ld--3秒接受到包数:%ld---3秒丢包数:%ld---3秒丢包率:%0.2f%%",lasPacketsReceived,lastAlllostData,(NSInteger)NsecondReceivedData,(NSInteger)NsecondLostData,prelostRate]; // // webrtcServerModel * webrtcServerMod = ksharedAppDelegate.bestWebrtcServerModel; // NSMutableString *signallingUrl = [[NSMutableString alloc] initWithFormat:@"当前使用:%@:%@--\n%@:%@--%.0fms\n\n",webrtcServerMod.signallingIp,webrtcServerMod.signallingPort,webrtcServerMod.turnIp,webrtcServerMod.turnPort,webrtcServerMod.delayedms]; // // for (webrtcServerModel *model in ksharedAppDelegate.DeviceWebRtcMsgMod.data.webrtcServerList) { // NSString *curStr = [[NSMutableString alloc] initWithFormat:@"%@:%@--\n%@:%@--%.0fms\n",model.signallingIp,model.signallingPort,model.turnIp,model.turnPort,model.delayedms]; // // [signallingUrl appendString:curStr]; // } // // // // lostDataStr = [[NSString alloc] initWithFormat:@"%@\n%@",lostDataStr,signallingUrl]; // // mainBlock(^{ // self->_testLostLabel.text = lostDataStr; // }); } } //网速 传输数据速度 NSString *netDataSpeedStr = @""; if(preReceive/1024.0 > 1024){ netDataSpeedStr = [NSString stringWithFormat:@"%.01fMB/s",preReceive/1024.0/1024.0]; } else{ netDataSpeedStr = [NSString stringWithFormat:@"%ldKB/s",preReceive/1024]; } mainBlock(^{ if(weakSelf.playerSetV){ [weakSelf updateControlBtnBgImageWith:delayedMS]; [weakSelf.playerSetV setWebRctMsgBydelayed:delayedMS withPacketLoss:self->prelostRate withSpeed:netDataSpeedStr withFPS:@""]; } }); } - (void)connectionChange:(NSString*)peerName didChangeLocalCandidate:(RTC_OBJC_TYPE(RTCIceCandidate) *)local remoteCandidate:(RTC_OBJC_TYPE(RTCIceCandidate) *)remote lastReceivedMs:(int)lastDataReceivedMs changeReason:(NSString *)reason { //HLog(@"webRtc P2P didChangeLocalCandidate") [[webRtcManager shareManager] reportWebRtcRePoportTypeIsChannel:NO withLocal:local remoteCandidate:remote withSessionId:self.webRtcPlayerSessionId withLogKey:@""]; } #pragma mark 更新悬浮图标的颜色 - (void)updateControlBtnBgImageWith:(NSInteger)delayedMS{ if (delayedMS < 50) { if(preDelayedMS > 0 && preDelayedMS < 50){ return;//没有变化 不处理 } [controlBtn setBackgroundImage:[UIImage imageNamed:@"you_icon"] forState:(UIControlStateNormal)]; } else if (delayedMS < 100){ if(preDelayedMS > 50 && preDelayedMS < 100){ return;//没有变化 不处理 } [controlBtn setBackgroundImage:[UIImage imageNamed:@"you_yellow"] forState:(UIControlStateNormal)]; } else{ if( preDelayedMS > 100){ return;//没有变化 不处理 } [controlBtn setBackgroundImage:[UIImage imageNamed:@"you_red"] forState:(UIControlStateNormal)]; } preDelayedMS = delayedMS; } #pragma mark 收到的webrtc消息处理 - (void)handleWebRtcMsgResponseBy:(NSData*)message { if([message isKindOfClass:[NSMutableString class]] || [message isKindOfClass:[NSString class]]) { message = [(NSString *)message dataUsingEncoding:(NSUTF8StringEncoding)]; } NSError *error = nil; NSDictionary *dataDict = [NSJSONSerialization JSONObjectWithData:message options:NSJSONReadingMutableContainers error:&error]; HLog(@"webRtc 音视频推拉流 通道接收消息:------------------%@",dataDict); if(!dataDict){ //[weakSelf handleDownloadResponseFunBy:message]; return; } if(![dataDict isKindOfClass:[NSDictionary class]]){ //[__NSCFString allKeys] unrecognized selector sent to ins return; } if(![[dataDict allKeys] containsObject:@"type"]){ return; } NSString *messageType = dataDict[@"type"]; if ([messageType isEqualToString:@"login"]) { if([[dataDict allKeys] containsObject:@"value"]){ NSString *value = dataDict[@"value"]; [self LogoutByOtherFun:value]; } } } //延迟系统触摸事件 //- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures{ // return UIRectEdgeAll; //} #pragma mark 检测盒子的心跳情况 - (void)checkBoxHeartbeatFun { //2、点击系统升级弹框确定按钮后30分钟内不弹; NSNumber *preSecondNum = [HWDataManager getNumberWithKey:stringKeyAddSn(@"disenable_type1_BoxHeartbeat")]; if(preSecondNum){ long seconds = [iTools getNowTimeStamp]; if(seconds - preSecondNum.longValue <= 60*30){ return; } } //3、重启、恢复出厂设备、首次设置密码 3个情况下8分钟之内不弹 NSNumber *preSecondNum2 = [HWDataManager getNumberWithKey:stringKeyAddSn(@"disenable_type2_BoxHeartbeat")]; if(preSecondNum2){ long seconds = [iTools getNowTimeStamp]; if(seconds - preSecondNum2.longValue <= 60*8){ return; } } if(ksharedAppDelegate.didShowBoxHeartbeatAlertType ||[webRtcManager shareManager].isResetingType ||[webRtcManager shareManager].isRebootIngType || [ksharedAppDelegate didShowImageRenewViewFun]){ return; } //1.隐私模式密码界面 3秒检测一次是否输入完成密码了 if(ksharedAppDelegate.isDidShowPwdType){ KWeakSelf dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [weakSelf checkBoxHeartbeatFun]; }); return; } // [[BoxHeartbeatAlertTool shareInstance] showBoxHeartbeatAlertFun:1 didClickBut:^(NSInteger tag) { // // }]; if(ksharedAppDelegate.isWebSockLinkOKAginType && ksharedAppDelegate.cloudPhoneExtraFileListMod){ return; } NSMutableDictionary *paraDict = [NSMutableDictionary new]; KWeakSelf [[netWorkManager shareInstance] CommonGetWithCallBackCode:queryHeartbeat Parameters:paraDict success:^(id _Nonnull responseObject){ queryHeartbeatModel *heartbeatMod = [[queryHeartbeatModel alloc] initWithDictionary:responseObject error:nil]; if(heartbeatMod && heartbeatMod.data){ [weakSelf checkBoxHeartbeatToShowPopViewFunBy:heartbeatMod]; } } failure:^(NSError * _Nonnull error) { }]; } #pragma mark 根据盒子的心跳情况 显示异常谈了 - (void)checkBoxHeartbeatToShowPopViewFunBy:(queryHeartbeatModel*)heartbeatMod { if(!heartbeatMod || !heartbeatMod.data){ return; } if (//!heartbeatMod.data.frpStatus&& !heartbeatMod.data.hostAgentStatus &&!heartbeatMod.data.containerAgentStatus) {//全部异常 [[BoxHeartbeatAlertTool shareInstance] showBoxHeartbeatAlertFun:1 didClickBut:^(NSInteger tag) { }]; } else if (heartbeatMod.data.hostAgentStatus //&& !heartbeatMod.data.frpStatus && !heartbeatMod.data.containerAgentStatus) {//frp异常 [[BoxHeartbeatAlertTool shareInstance] showBoxHeartbeatAlertFun:2 didClickBut:^(NSInteger tag) { }]; } else{//原来的逻辑 [self showLinkPhoneErrorFun]; } } @end