// // ViewController.m // VideoTest // // Created by APPLE on 2019/5/29. // Copyright © 2019 APPLE. All rights reserved. // #import "PlayerViewController.h" #import "PlayerViewController+TouchPointXD.h" #import "PlayerViewController+AdjustBtnFrame.h" #import "PlayerViewController+AppDelegate.h" #import "PlayerViewController+otherDelegate.h" #import "AFNetworkReachabilityManager.h" #import #import #import #import #import #import "FLAnimatedImage.h" #import #import "BGTool.h" #import "AppDelegate.h" #import #import //#import #import #import "ShortcutManager.h" #import "RCCommandHelp.h" #import "UIView+View.h" #import "SafeForKey.h" #import "CloudPhoneAPI.h" #import "MySetViewController.h" #import "PhoneTimeInfoModel.h" #import "connectDeviceManager.h" #import "ComontAlretViewController.h" typedef enum : NSUInteger { BITRATE_EXTREME_SPEED = 2,//极速 // BITRATE_HIGH_SPEED = 843000,//高速 BITRATE_AUTO = 6,//自动 // BITRATE_STANDARD_CLEARING = 2,//wwan标清 // BITRATE_HD = 3,//wwan高清 BITRATE_WIFI_STANDARD_CLEARING = 3, //wifi标清 BITRATE_WIFI_HD = 4, //wifi高清 } BITRATE_TYPE; //当手机采用wifi时不做码率调整,当手机采用流量时,高清采用2052000,标清采用1652000调整(默认) ///*测试*/ //#include "socket.h" CGFloat w_h_rate; PlayerViewController * _Nullable mySelf; BOOL isLan; //PlayerViewController *mySelf; int portConnect; NSString *ipConnect; @interface PlayerViewController () { // __block int _ihandle; int rate;/*0:极速 1:高速 2:高清 3:标清 4:d自动*/ NSUInteger rateForAuto; BOOL showWattingViewImageView; RCPCMPlayer *pcmPlayer; NSInteger gpsOnOff; BOOL canRate; CIContext *videoContext; NSInteger reConnectAccount;/*记录重连次数*/ BOOL isInPan;/*标记是否有手指在活动*/ int socketFortest; UIView *loadingWithTipsView; NSInteger netWorkStates;/*0很差 1较差 2流畅*/ BOOL outputVolumeKVO;/*标记声音监听通知*/ NSDate *rootSetTime; UITextField *hidenTextField; NSString *hidenTextFieldOldStr; PhoneTimeInfoDataModel *phoneTimeInfoDataModel; /*弹窗提示重启*/ ComontAlretViewController *logoutAlertVC; /*弹窗提示链接失败 网络或者云机*/ ComontAlretViewController *linkFailAlretVC; NSTimer *forceStartTimer;//请知重启timer } @property (nonatomic, strong, nullable) RCVideoRecoderManager *recoderManager; @property (nonatomic, strong, nullable) RCAudioRecoderMamager *audioRecoderMamager; //@property (nonatomic, strong) RCLiveSteamManager *liveStreamManager; //@property (nonatomic, strong) RCCommandChannelManager *commandChannelManager;//指令通道 //@property (nonatomic, strong) RCCommandChannelManager *businessCommandChannelManager;//业务通道 //需不需要显示音量条 @property (nonatomic, assign) BOOL isNeedShowVoiceBar; //切换云手机 保存切换过的云手机数组, 返回的时刷新对应的云机websorket封面 @property (nonatomic, strong) NSMutableArray *switchCloudPhoneArray; @property (nonatomic, copy) NSString *screenShotFileName; @property (nonatomic, copy) NSTimer *timer; // 定时器-控制按钮 /**30s后 渲染时间戳无更新 自动断开链接*/ @property (nonatomic, assign) NSInteger concentTime; // 拉流数据 渲染更新时间戳 /**定时器计数*/ @property (nonatomic, assign) NSInteger currentTime; /**是否是收入进入云手机*/ @property (nonatomic, assign) BOOL isFirstEnterPhone; @property (nonatomic, strong) NSTimer *checkThridConnectTimer; // 检查瑞云那边连接完成没 @property (nonatomic, assign) NSInteger checkThridConnectNum;// //音频和图片是否可以刷新 @property (nonatomic, assign) BOOL canShowImgAndVoiceType; @property (nonatomic, copy) NSString*LogoutTimerStr;//单点登出时间 @property (nonatomic, assign) BOOL needShowLogoutDelayType;//是否是延时显示单点登出 @property (nonatomic, assign) BOOL isRebootIngType;//是否为重启中 @property (nonatomic, assign) BOOL isResetingType;//是否为恢复出厂中 @end @implementation PlayerViewController @synthesize internetVideoPort; @synthesize ip; @synthesize canControl; @synthesize deviceId; @synthesize vpnStatus; @synthesize internetHttp; @synthesize rbdNotification; - (void)viewDidLoad { [super viewDidLoad]; if (@available(iOS 11.0, *)) { // 兼容低版本ios [self setNeedsUpdateOfHomeIndicatorAutoHidden]; } canControl = YES; _canShowImgAndVoiceType = NO; //[self opencommandChannelManagerrc_openURL]; //[self openbusinessCommandChannelManagerrc_openURL]; portConnect = [self->internetVideoPort intValue]; ipConnect = self->ip; isLan = NO; globalBlock(^{ // 初始化成功后连接 @synchronized (self) { if ([self initVideoServer]) { [self connectVideoServer]; } } }); outputVolumeKVO = NO; rbdNotification = 0; // 初始化 self.isNeedRecyclResource = YES; self.isFirstEnterPhone = YES; [self initData]; self.toolBar.hidden = YES; self.navigationBar.hidden = YES; [self drawView]; [self showNewIndicator]; mySelf = self; haveBack = NO; [self startCheckThridRuiYunTimerFun]; } #pragma mark 启动检测瑞云的timer - (void)startCheckThridRuiYunTimerFun { if(_checkThridConnectTimer ){ [_checkThridConnectTimer invalidate]; } _checkThridConnectNum = 0; _checkThridConnectTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(checkThridRuiYunFun) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:_checkThridConnectTimer forMode:NSRunLoopCommonModes]; } #pragma mark 检测融云链接是否完成 - (void)checkThridRuiYunFun{ _checkThridConnectNum += 1; if(_checkThridConnectNum == 30 && [[connectDeviceManager shareInstance] curConnectDeviceState] <= 3 ){ [self showNetErrorAlertFun:11]; // [_checkThridConnectTimer invalidate]; // return; } //HLog(@"局域网是否能ping通:%d",[connectDeviceManager shareInstance].DeviceThirdIdMod.data.isPingOk); HLog(@"瑞云连接状态:%d",[[connectDeviceManager shareInstance] curConnectDeviceState]); //第一次进 先输入密码才能连接 if([connectDeviceManager shareInstance].isFirstInputPwdDone){ if([connectDeviceManager shareInstance].DeviceThirdIdMod.data.isPingOk){ ip = [connectDeviceManager shareInstance].DeviceThirdIdMod.data.ip; internetVideoPort = @"9100"; [self didCanConnectServerFun]; } else{ if([[connectDeviceManager shareInstance] curConnectDeviceState] == DeviceConnectDeciceOk){ ip = @"127.0.0.1"; internetVideoPort = [[connectDeviceManager shareInstance] tcpPortStr]; [self didCanConnectServerFun]; } } } } #pragma mark 走局域网或者瑞云SDK链接OK - (void)didCanConnectServerFun{ [_checkThridConnectTimer invalidate]; //做版本检测 [self checkVersionFun]; [self connectVideoServer]; [self opencommandChannelManagerrc_openURL]; // _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerChange) userInfo:nil repeats:YES]; // [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes]; } - (void)initData { isInPan = NO; reConnectAccount = 0; netWorkStates = 0; canRate = NO; rate = -1; isLan = NO; // _ihandle = -1; [hidenTextField resignFirstResponder]; hidenTextField.text = @""; hidenTextFieldOldStr = nil; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; // 屏幕常亮 [UIApplication sharedApplication].idleTimerDisabled = YES; [[UIApplication sharedApplication] setStatusBarHidden:YES]; [self setTimerCountDown]; [self setShowImgAndVoiceTypeFun:YES]; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; if (mPlayerView.controlBtn) { [self.navigationController.view bringSubviewToFront:mPlayerView.controlBtn]; } } - (void)viewWillDisappear:(BOOL)animated { // 退出控制器 回收资源 [self recyclResource]; AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate; // app.allowAutoRotate = NO; [super viewWillDisappear:animated]; [self setShowImgAndVoiceTypeFun:NO]; } // 退出控制器 回收资源 - (void)recyclResource { // 移除Alert if (self.presentedViewController) { [self.presentedViewController dismissViewControllerAnimated:YES completion:nil]; } [mPlayerView.controlBtn removeFromSuperview]; if ([[[UIApplication sharedApplication] keyWindow] viewWithTag:1235]) { [[[[UIApplication sharedApplication] keyWindow] viewWithTag:1235] removeFromSuperview]; } // 销毁定时器 [self cancelTimer]; [self enablePanRightBack]; // 播放器内部页面跳转-不能回收的资源 if (self.isNeedRecyclResource) { // 屏幕常亮 [UIApplication sharedApplication].idleTimerDisabled = NO; [[UIApplication sharedApplication] setStatusBarHidden:NO]; if (USEAAC) { if (aacPlayer) { [aacPlayer stop]; aacPlayer = nil; } } else { if (pcmPlayer) { [pcmPlayer stop]; pcmPlayer = nil; } } [self toStopRecoder]; [self toStopAudioRecoder]; [self removeNSNotification]; //清空WebSocket连接 [self.commandChannelManager rc_close]; [self.businessCommandChannelManager rc_close]; globalBlock(^{ [self.liveStreamManager rc_release]; }); } } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate; // app.allowAutoRotate = YES; [[UIApplication sharedApplication] setStatusBarHidden:YES]; [self noEnablePanRightBack]; [self.navigationController.view addSubview:mPlayerView.controlBtn]; [self.navigationController.view bringSubviewToFront:mPlayerView.controlBtn]; if (self.isNeedRecyclResource) { self.liveStreamManager = [[RCLiveSteamManager alloc] init]; self.liveStreamManager.delegate = self; //[self opencommandChannelManagerrc_openURL]; //[self openbusinessCommandChannelManagerrc_openURL]; portConnect = [internetVideoPort intValue]; ipConnect = ip; isLan = NO; globalBlock(^{ // 初始化成功后连接 @synchronized (self) { if ([self initVideoServer]) { [self connectVideoServer]; } } }); [self addNSNotification]; } self.isNeedRecyclResource = YES; } - (void)opencommandChannelManagerrc_openURL { if(self.commandChannelManager){ [self.commandChannelManager rc_close]; self.commandChannelManager = nil; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self opencommandChannelManagerrc_openURL]; }); return; } KWeakSelf //初始化指令通道 self.commandChannelManager = [[RCCommandChannelManager alloc] init]; NSString *instructionsChannelUrl = [NSString stringWithFormat:@"ws://%@:%@/businessChannel",ip,internetVideoPort]; if([connectDeviceManager shareInstance].DeviceThirdIdMod.data.isPingOk){ instructionsChannelUrl = [NSString stringWithFormat:@"ws://%@:%@/businessChannel",ip,@"9300"]; } if (instructionsChannelUrl && instructionsChannelUrl.length > 0) { //当都有值才可连接 HLog(@"WebSocket11111指令通道连接开始11111 url = %@ ",instructionsChannelUrl); [self.commandChannelManager rc_openURL:instructionsChannelUrl connected:^{ HLog(@"WebSocket11111指令通道连接成功11111 url = %@ ",instructionsChannelUrl); if (weakSelf.commandChannelManager.rc_socketStatus == RCSocketCloudPhoneStatusConnected){ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [weakSelf handlAllMsgAfterDidLinkFun]; //设置分辨率 // NSString *commondStr = @"{\"data\":{\"height\":1920,\"width\":1080,\"dpi\":480},\"type\":\"setPhoneSize\"}"; // [weakSelf send_data:commondStr]; // /*获取自己的用户名(电话号码)*/ // NSString *selfUseName = nil; // NSDictionary *dict111 = [[UseAccountManage shareInstance] getLoginInfo]; // if ([[dict111 allKeys] containsObject:@"userName"]) { // selfUseName = [dict111 valueForKey:@"userName"]; // /*查询是否有设备在远程控制*/ // [self.commandChannelManager rc_sendData:[RCCommandHelp askControllcommandWithUseName:selfUseName]]; // } // if (USELOCALKEYBOARD){ // /*开启输入法透传*/ // NSString *dataStr = [RCCommandHelp commandOpenLoaclKeyboad]; // [self.commandChannelManager rc_sendData:dataStr]; // }else{ // /*关闭输入法透传*/ // NSString *dataStr = [RCCommandHelp commandCloseLoaclKeyboad]; // [self.commandChannelManager rc_sendData:dataStr]; // } }); } } receive:^(id message, FLSocketCloudPhoneReceiveType type) { if([message isKindOfClass:[NSData class]] && [message length] == 0){ return; } HLog(@"webSocket指令通道接收消息:------------------\n%@",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]; if(!dataDict){ return; } if(![dataDict isKindOfClass:[NSDictionary class]]){ //[__NSCFString allKeys] unrecognized selector sent to ins return; } NSString *messageType = dataDict[@"type"]; if ([messageType isEqualToString:@"cutting"]) { //[[iToast makeText:@"复制成功"] show]; } else if ([messageType isEqualToString:@"forwardMsg"]){/*转发*/ /*获取指令类型*/ NSString *code = nil; if ([[dataDict allKeys] containsObject:@"data"]) { NSDictionary *data = dataDict[@"data"]; if([data isKindOfClass:[NSString class]]){ NSString * dataStr = (NSString*)data; if([dataStr isEqualToString:@"offline_notification"]){ HLog(@"被别人挤下线了"); [weakSelf LogoutByOtherFun]; } return; } else if ([data isKindOfClass:[NSDictionary class]] && [[data allKeys] containsObject:@"code"]) { code = [data objectForKey:@"code"]; if (![code isKindOfClass:[NSString class]]) { code = [NSString stringWithFormat:@"%ld",[code integerValue]]; } } } /*获取用户名*/ NSString *useName = nil; if ([[dataDict allKeys] containsObject:@"data"]) { NSDictionary *data = dataDict[@"data"]; if ([[data allKeys] containsObject:@"userName"]) { useName = [data objectForKey:@"userName"]; } } /*无控制权提示*/ //- (void)tipsNoDeviceContrWithPhoneIndex:(NSInteger)phoneIndex /*提醒拿回控制权*/ //- (void)tipsGetBackDeviceContrWithPhoneIndex:(NSInteger)phoneIndex /*提醒控制权被拿回*/ //- (void)tipsMainUserGetDeviceAuthBack // if ([code isEqualToString:@"3000"]) {/*有人询问控制权情况*/ // if (self->deviceModel.authPhone==0 && self->deviceModel.phoneAuthStatus == 0){ // return;/*自己的云手机且未授权直接返回*/ // } // // if (![useName isEqualToString:selfUseName]){ // /*根据实际情况进行相关回复*/ // [self.commandChannelManager rc_sendData:[RCCommandHelp faceBackControllcommandWithUseName:selfUseName haveControl:self->canControl]]; // } // }else if ([code isEqualToString:@"4000"]){/*有在控制*/ // if (self->deviceModel.authPhone==0 && self->deviceModel.phoneAuthStatus == 0){ // return;/*自己的云手机且未授权直接返回*/ // } // // if (self->deviceModel.authPhone==0) {/*是自己的设备时候要询问是否夺回控制权*/ // if (![useName isEqualToString:selfUseName]) { // /*弹窗询问是否夺回控制权*/ // [self tipsGetBackDeviceContrWithPhoneIndex:self->deviceModel]; // } // }else if (![useName isEqualToString:selfUseName]) { // if (self->canControl == YES) { // [self tipsNoDeviceContrWithPhoneIndex:self->deviceModel]; // } // self->canControl = NO; // if (!self->canControl&&self->controlView){ // [self->controlView diasbleControltPhoneView]; // }else if (self->controlView){ // [self->controlView enableControltPhoneView]; // } // } // }else if ([code isEqualToString:@"4100"]){/*未控制*/ // /*不用处理默认可以控制*/ // }else if ([code isEqualToString:@"5000"]){/*夺回控制权*/ // if (self->deviceModel.authPhone==0 && self->deviceModel.phoneAuthStatus == 0){ // return;/*自己的云手机且未授权直接返回*/ // } // // if ([useName isEqualToString:selfUseName]){ // return; // } // // if (self->deviceModel.authPhone!=0) {/*不是自己的设备时候要进行关闭控制权*/ // if (self->canControl == YES) { // /*弹窗提示控制权已经被夺回*/ // [self tipsMainUserGetDeviceAuthBack]; // } // self->canControl = NO; // if (!self->canControl&&self->controlView){ // [self->controlView diasbleControltPhoneView]; // }else if (self->controlView){ // [self->controlView enableControltPhoneView]; // } // } // }else if ([code isEqualToString:@"phoneSizeChange"]){/*分辨率改变*/ if ([[dataDict allKeys] containsObject:@"data"]) { NSDictionary *data = dataDict[@"data"]; if ([[data allKeys] containsObject:@"width"]) { ksharedAppDelegate.couldPhone_W_PHONE = [[data objectForKey:@"width"] integerValue]; } if ([[data allKeys] containsObject:@"height"]) { ksharedAppDelegate.couldPhone_H_PHONE = [[data objectForKey:@"height"] integerValue]; } if (ksharedAppDelegate.couldPhone_W_PHONE > ksharedAppDelegate.couldPhone_H_PHONE) { CGFloat temp = ksharedAppDelegate.couldPhone_W_PHONE; ksharedAppDelegate.couldPhone_W_PHONE = ksharedAppDelegate.couldPhone_H_PHONE; ksharedAppDelegate.couldPhone_H_PHONE = temp; } } } } else if ([messageType isEqualToString:@"getPhoneSize"] || [messageType isEqualToString:@"setPhoneSize"]){ NSString *sn = nil; if ([[dataDict allKeys] containsObject:@"data"]) { NSDictionary *data = dataDict[@"data"]; if ([[data allKeys] containsObject:@"status"]) { NSInteger status = [[data objectForKey:@"status"] integerValue]; if (status == 0) {/*不是当前设备直接返回*/ if ([[data allKeys] containsObject:@"width"]) { ksharedAppDelegate.couldPhone_W_PHONE = [[data objectForKey:@"width"] integerValue]; } if ([[data allKeys] containsObject:@"height"]) { ksharedAppDelegate.couldPhone_H_PHONE = [[data objectForKey:@"height"] integerValue]; } if (ksharedAppDelegate.couldPhone_W_PHONE > ksharedAppDelegate.couldPhone_H_PHONE) { CGFloat temp = ksharedAppDelegate.couldPhone_W_PHONE; ksharedAppDelegate.couldPhone_W_PHONE = ksharedAppDelegate.couldPhone_H_PHONE; ksharedAppDelegate.couldPhone_H_PHONE = temp; } } } } // { // "type":"getPhoneSize", --接口类型 // "data":{ // "sn":"RK_XXX", --安卓卡SN // "status":"0", --状态:0:成功 1:失败 // "msg":"success", --请求状态:success 成功 failed 失败 // "width":xxx, // "height":xxx, // "dpi":yyy --屏幕密度 // } // } } else if ([messageType isEqualToString:@"sync_wifi"]){ [weakSelf sync_wifiBackHandleFun]; } else if ([messageType isEqualToString:@"reProduceText"]){ if ([[dataDict allKeys] containsObject:@"data"]) { NSDictionary *data = dataDict[@"data"]; if ([[data allKeys] containsObject:@"text"]) { NSString *pasteboardStr = [data objectForKey:@"text"]; UIPasteboard* pasteboard = [UIPasteboard generalPasteboard]; pasteboard.string = pasteboardStr; } } } else if ([messageType isEqualToString:@"downAdnInstallRep"]){ if ([[dataDict allKeys] containsObject:@"data"]) { NSDictionary *data = dataDict[@"data"]; if ([[data allKeys] containsObject:@"status"]) { NSString *status = [data objectForKey:@"status"]; if ([status isEqualToString:@"1"]) { mainBlock(^{ // [[iToast makeText:@"App下载完成"] show]; }); }else if ([status isEqualToString:@"0"]){ mainBlock(^{ //[[iToast makeText:@"App下载中"] show]; }); } } } } else if ([messageType isEqualToString:@"shakeit"]){ HLog(@"\n-----摇一摇成功------"); }else if ([messageType isEqualToString:@"keyboardFeedbackBean"]){/*调起键盘*/ [weakSelf keyboardFeedbackBeanFun]; }else if ([messageType isEqualToString:@"FileRandomReady"]){/*申请文件上传得到答复*/ [weakSelf applyUploadFileServiceResponseFun:dataDict]; } else if ([messageType isEqualToString:@"uploadFileRandomRet"]){/*文件上传得到答复*/ [weakSelf upLoadFileFunServiceResponseFun:dataDict]; } else if ([messageType isEqualToString:@"getBaseInfo"]){/*获取云机的基本信息*/ [weakSelf getCouldPhoneBaseInfoResponseFun:dataDict]; } else if ([messageType isEqualToString:@"getSysInfo"]){/*获取云机的系统信息*/ [weakSelf getCouldPhoneSysInfoResponseFun:dataDict]; } else if ([messageType isEqualToString:@"TvStatus"]){/*获取TV投屏信息*/ [weakSelf getCouldPhoneTvStatusResponseFun:dataDict]; } else if ([messageType isEqualToString:@"reboot"]){/*重启*/ [weakSelf stopForceStartTimerFun]; } } failure:^(NSError *error) { [self showNetErrorAlertFun:2]; }]; } } #pragma mark wifi handle - (void)sync_wifiBackHandleFun { [self.commandChannelManager rc_sendData:[RCCommandHelp noSyncWifiBack]]; [[iToast makeText:NSLocalizedString(@"player_Tip_ios_no_wifi_Sync",nil)] show]; } - (void)keyboardFeedbackBeanFun { [self->hidenTextField becomeFirstResponder]; // [self->hidenTextField setText:@"1234"]; [self->hidenTextField setEnabled:YES]; } - (void)textDidChange:(UITextField *)textField{ if (textField.markedTextRange == nil) { /*新内容 完全包含前面的内容 就是删除*/ NSRange newInOld = [hidenTextFieldOldStr rangeOfString:textField.text]; if (newInOld.location == 0 && newInOld.length == textField.text.length){/*删除*/ NSString *dataStr = [RCCommandHelp commandKeyboadInputStr:nil]; [self.businessCommandChannelManager rc_sendData:dataStr]; /*删除以后在输入框前面新增一个字符*/ NSString *tempStr = textField.text; if (tempStr.length > 0){ }else{ tempStr = @" "; } textField.text = tempStr; }else{ /*新增*/ NSRange oldInNew = [textField.text rangeOfString:hidenTextFieldOldStr]; if (oldInNew.location == 0 && oldInNew.length == hidenTextFieldOldStr.length){/*新增*/ NSString *addStr = [textField.text substringWithRange:(NSMakeRange(hidenTextFieldOldStr.length, textField.text.length - hidenTextFieldOldStr.length))]; NSLog(@"键盘透传--@@@@新增内容:%@",addStr); NSString *dataStr = [RCCommandHelp commandKeyboadInputStr:addStr]; [self.businessCommandChannelManager rc_sendData:dataStr]; }else{/*部分覆盖*/ /*覆盖分为两部分 1、覆盖的内容更长 2、覆盖的内容更短*/ /*删除不同的部分 加上变化的部分*/ /*后面不同内容的长度*/ NSInteger sameLength = 0; if (hidenTextFieldOldStr.length < textField.text.length){ sameLength = [self sameStrLengthSmallStr:hidenTextFieldOldStr longStr:textField.text]; }else{ sameLength = [self sameStrLengthSmallStr:textField.text longStr:hidenTextFieldOldStr]; } /*需要删除的长度*/ NSInteger needDeleteLength = hidenTextFieldOldStr.length - sameLength; for (NSInteger nFori = 0; nFori < needDeleteLength; nFori++) { NSString *dataStr = [RCCommandHelp commandKeyboadInputStr:nil]; [self.businessCommandChannelManager rc_sendData:dataStr]; } /*需要增加的内容*/ NSInteger needLength = textField.text.length - sameLength; NSString *addStr = [textField.text substringWithRange:(NSMakeRange(sameLength, needLength))]; NSString *dataStr = [RCCommandHelp commandKeyboadInputStr:addStr]; [self.businessCommandChannelManager rc_sendData:dataStr]; } } hidenTextFieldOldStr = textField.text; } } - (NSInteger)sameStrLengthSmallStr:(NSString *)litStr longStr:(NSString *)longStr{ NSInteger samenumber = 0; for (NSInteger nFori = 1; nFori < litStr.length+1; nFori++) { NSString *temp0 = [litStr substringToIndex:nFori]; NSString *temp1 = [longStr substringToIndex:nFori]; if (![temp0 isEqualToString:temp1]){ break; } samenumber++; } return samenumber; } #pragma mark - UI相关 - (void)drawView { hidenTextField = [[UITextField alloc] initWithFrame:(CGRectMake(0, 0, 0, 0))]; hidenTextField.delegate = self; [hidenTextField addTarget:self action:@selector(textDidChange:) forControlEvents:UIControlEventEditingChanged]; [self.view addSubview:hidenTextField]; [self.view setBackgroundColor:[UIColor whiteColor]]; mPlayerView = [[PlayerView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_W, SCREEN_H)]; //mPlayerView.buyVipType = self.buyVipType; [mPlayerView initPoMas_makeWithImageRate:YES isUsageMode:NO]; [mPlayerView setBackgroundColor:[UIColor blackColor]]; mPlayerView.delegate = self; deviceShareStates = 2; [self.view addSubview:mPlayerView]; [mPlayerView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(0); make.right.mas_equalTo(0); make.top.mas_equalTo(0); make.bottom.mas_equalTo(0); }]; [self reSetPlayerViewFloatBtnFrame]; if (isLan)/*直接g或者变为横屏*/ { [mPlayerView setLanMas_makeWithImageRate:ksharedAppDelegate.couldPhone_W_PHONE/ksharedAppDelegate.couldPhone_H_PHONE isOpenVirtual:YES isUsageMode:NO]; } else { [mPlayerView setPoMas_makeWithImageRate:ksharedAppDelegate.couldPhone_W_PHONE/ksharedAppDelegate.couldPhone_H_PHONE isOpenVirtual:YES isUsageMode:NO]; } } /** * @brief 漂浮按钮位置初始化 * * */ - (void)reSetPlayerViewFloatBtnFrame { // [[[UIApplication sharedApplication] keyWindow] addSubview:mPlayerView.controlBtn]; [self.navigationController.view addSubview:mPlayerView.controlBtn]; [self.navigationController.view bringSubviewToFront:mPlayerView.controlBtn]; NSDictionary *dict = nil; CGFloat h_w_controlBtn = 60.f; if (dict) { CGFloat pointx = [[dict objectForKey:@"pointx"] floatValue]; CGFloat pointy = [[dict objectForKey:@"pointy"] floatValue]; if (mPlayerView.width > mPlayerView.height){ if (pointx < 30) { pointx = 30; } else if (pointx > mPlayerView.width - h_w_controlBtn - 10.f) { pointx = mPlayerView.width - h_w_controlBtn - 10.f; } if (pointy < 10) { pointy = 10; } else if (pointy > mPlayerView.height - h_w_controlBtn - 10.f) { pointy = mPlayerView.height - h_w_controlBtn - 10.f; } }else{ if (pointx < 10) { pointx = 10; } else if (pointx > mPlayerView.width - h_w_controlBtn - 10.f) { pointx = mPlayerView.width - h_w_controlBtn - 10.f; } if (pointy < 10) { pointy = 10; } else if (pointy > mPlayerView.height - h_w_controlBtn - 10.f) { pointy = mPlayerView.height - h_w_controlBtn - 10.f; } } // BOOL hidden = [[dict objectForKey:@"hidden"] boolValue]; [mPlayerView.controlBtn setFrame:CGRectMake(pointx, pointy, h_w_controlBtn, h_w_controlBtn)]; } else { /*区分横竖屏*/ if (mPlayerView.width > mPlayerView.height){ [mPlayerView.controlBtn setFrame:CGRectMake((mPlayerView.width - h_w_controlBtn)/2.f, mPlayerView.height - 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)]; //默认居左 [mPlayerView.controlBtn setFrame:CGRectMake( h_w_controlBtn + 10.f, (SCREEN_H - h_w_controlBtn)/2.f, h_w_controlBtn, h_w_controlBtn)]; } [mPlayerView.controlBtn setHidden:NO]; } HLog(@"云手机推流界面 控制按钮中点%@",NSStringFromCGPoint(mPlayerView.controlBtn.center)); } #pragma mark - 手势权限控制处理 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{ return NO; //YES:允许右滑返回 NO:禁止右滑返回 } - (void)enablePanRightBack { if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) { self.navigationController.interactivePopGestureRecognizer.enabled = YES; } if ([self.tabBarController.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) { self.tabBarController.navigationController.interactivePopGestureRecognizer.enabled = YES; } } - (void)noEnablePanRightBack { if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) { self.navigationController.interactivePopGestureRecognizer.enabled = NO; } if ([self.tabBarController.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) { self.tabBarController.navigationController.interactivePopGestureRecognizer.enabled = NO; } } #pragma mark - RCLiveSteamManagerDelegate - (void)liveStreamManagerOutPut:(RCLiveSteamManager *)manager didOutPutVideoPixelBuffer:(CVPixelBufferRef)pixelBuffer { if(!_canShowImgAndVoiceType){ return; } if (!mySelf || mySelf->haveBack) { return; } if (!pixelBuffer) { return; } [mySelf updateAutoRateAndNetWorkStates];//更新网络标识 以及自动码率 if (mySelf&&!(mySelf->haveBack)) { mySelf->reConnectAccount = 0; @autoreleasepool { if (!mySelf) { return ; } CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBuffer]; if (mySelf->saveCIImage) { mySelf->saveCIImage = nil; } mySelf->saveCIImage = ciImage; if (!mySelf->videoContext) mySelf->videoContext = [CIContext contextWithOptions:nil]; if (USEOPENGL) { if (ciImage) { [mySelf showImageOpenglWithCIImage:ciImage];/*使用Opengl渲染*/ mySelf.concentTime = [iTools getNowTimeStamp]; mySelf.isConnectSuccess = YES; } } else { if (ciImage) { [mySelf showImageUIImageViewWithCIImage:ciImage pixelBufferRef:pixelBuffer];/*使用UIImageView渲染*/ mySelf.concentTime = [iTools getNowTimeStamp]; mySelf.isConnectSuccess = YES; } } if (mySelf&&!mySelf->haveBack && mySelf->wattingView) { mainBlock(^{ [mySelf removeNewIndicator]; }); } } } } - (void)liveStreamManagerOutPut:(RCLiveSteamManager *)manager didOutPutAudioData:(NSData *)pcmData { @autoreleasepool { if(!_canShowImgAndVoiceType){ return; } if (mySelf&&!(mySelf->haveBack)){ [mySelf->connectLock lock]; if (!mySelf->pcmPlayer){ mySelf->pcmPlayer = [[RCPCMPlayer alloc] initWithAudioBufferSize:4096 mSampleRate:44100 mChannelsPerFrame:2]; mySelf.isNeedShowVoiceBar = NO; [mySelf->pcmPlayer start]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ mySelf.isNeedShowVoiceBar = YES; }); } if (pcmData){ mySelf.isNeedShowVoiceBar = NO; [mySelf->pcmPlayer play:pcmData]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ mySelf.isNeedShowVoiceBar = YES; }); } [mySelf->connectLock unlock]; } } } - (void)liveStreamManager:(RCLiveSteamManager *)manager connectState:(ConnectState)state { HLog(@"\n------状态回调---state = %d--", state); //[[VclCrash sharedInstance] writeContent:[NSString stringWithFormat:@"_connectDisconnect连接返回句柄 = %d--state--=%d-",ihandle,state]]; switch (state){ case 0:/*连接已释放*/{ } break; case 1:/*正在连接*/{ } break; case 2:/*连接成功*/{ HLog(@"\n-----_%s------SSSSSSSSSSS连接成功",__FUNCTION__); if (self.isFirstEnterPhone) { self.isFirstEnterPhone = NO; } //重启后重连 出来的 if(_isRebootIngType && !forceStartTimer){ mainBlock(^{ [[iToast makeText:NSLocalizedString(@"player_link_reboot_suc_Tips",nil)] show]; }); _isRebootIngType = NO; } //重启后重连 出来的 if(_isResetingType){ mainBlock(^{ [[iToast makeText:NSLocalizedString(@"my_set_no_Restore_Factorying_tips",nil)] show]; }); _isResetingType = NO; } // 报链接失败 后面又连接上了 if(linkFailAlretVC){ mainBlock(^{ [self->linkFailAlretVC dismissViewControllerAnimated:YES completion:^{ }]; self->linkFailAlretVC = nil; }); } } break; case 3:/*正在渲染*/{ } break; case 4:/*正在关闭*/{ } break; case 5:/*已关闭*/{ } break; case 6:{ mainBlock(^{ [self showNewIndicator]; [self tryAgain]; }); } break; case ConnectStateVerifyErr:{ HLog(@"\n------token异常----重新超分-----"); /*鉴权失败 进行超分操作*/ /*先清除当前的token*/ // NSDictionary *dictLogin = [[UseAccountManage shareInstance] getLoginInfo]; // if (dictLogin && [[dictLogin allKeys] containsObject:@"userName"]) // { // /*判断数据库中有没有对应phoneid*/ // NSString* username = [dictLogin objectForKey:@"userName"]; // NSString * bg_tableName = P2PModelList_bg_tableName(username); // //先显示本地缓存数据 // NSArray* finfAlls = [PhoneP2PListModel bg_findAll:bg_tableName]; // if (finfAlls && finfAlls.count >0) { // PhoneP2PListModel *listMod = finfAlls[0]; // for (PhoneP2PModel *p2pModel in listMod.data) { // if (p2pModel.phoneId == self.deviceModel.phoneId){ // [listMod.data removeObject:p2pModel]; // [listMod bg_cover]; // break; // } // } // } // } } break; default: break; } } - (void)openVideForLiveStreamManager:(AVCaptureDevicePosition)position needPost:(BOOL)needPost { if (mySelf&&!(mySelf->haveBack)) { if (mySelf->canControl) { [mySelf toStopRecoder]; HLog(@"\n-----打开视频透传 后置摄像头-------"); [mySelf toStartRecoderWithAVCaptureDevicePosition:(position)]; // if (needPost) { // // 云机摄像头使用上报 // [mySelf postCloudCamera]; // } } } } - (void)liveStreamManager:(RCLiveSteamManager *)manager didReceiveEvent:(EventState)event { EventState state = event; if (0 == state)/*横屏*/ { if (USELOCALKEYBOARD){ isLan = YES; /*横屏处理*/ [self setDeviceOrientation:(UIDeviceOrientationLandscapeLeft)]; HLog(@"\n---000000--横屏--000000-----"); }else{ /*横屏处理*/ isLan = NO; [self setDeviceOrientation:(UIDeviceOrientationPortrait)]; HLog(@"\n---000000--横屏--000000-----"); } mySelf->mPlayerView.isLan = YES; HLog(@"\n---000000--横屏--000000-----"); } else if (1 == state)/*竖屏*/ { isLan = NO; mySelf->mPlayerView.isLan = NO; /*横屏处理*/ [self setDeviceOrientation:(UIDeviceOrientationPortrait)]; } else if (2 == state)/*打开音频透传*/ { if (mySelf&&!(mySelf->haveBack)) { if (mySelf->canControl) { HLog(@"\n-----打开视频透传-------"); [mySelf toStartAudioRecoder]; } } } else if (3 == state)/*关闭音频透传*/ { [mySelf toStopAudioRecoder]; } else if (4 == state)/*打开视频透传*/ { [self openVideForLiveStreamManager:AVCaptureDevicePositionBack needPost:YES]; } else if (5 == state)/*关闭视频透传*/ { [mySelf toStopRecoder]; } else if (7 == state)/*打开视频透传--前置摄像头*/ { [self openVideForLiveStreamManager:AVCaptureDevicePositionFront needPost:YES]; } else if (EventStateTurnOnVideoDontNeedToServer == state)/*打开视频透传*/ { [self openVideForLiveStreamManager:AVCaptureDevicePositionBack needPost:NO]; } else if (EventStateTurnOnVideoFrontDontNeedToServer == state)/*打开视频透传--前置摄像头*/ { [self openVideForLiveStreamManager:AVCaptureDevicePositionFront needPost:NO]; } else if (EventStateTurnOnVideoDontNeedToServer == state)/*打开视频透传*/ { [self openVideForLiveStreamManager:AVCaptureDevicePositionBack needPost:NO]; } else if (EventStateTurnOnVideoFrontDontNeedToServer == state)/*打开视频透传--前置摄像头*/ { [self openVideForLiveStreamManager:AVCaptureDevicePositionFront needPost:NO]; } } - (void)liveStreamManager:(RCLiveSteamManager *)manager didReceiveMessage:(NSString *)message { } - (void)liveStreamManager:(RCLiveSteamManager *)manager didReceiNetEstimator:(NetEstimator)estimator{ } - (void)liveStreamManager:(RCLiveSteamManager *)manager didReceiveJitterDelay:(int)jitterDelayMs{ HLog(@"延时毫秒:%d",jitterDelayMs) } #pragma mark - 视频流回调 void connectStateCallBack (void *client, ConnectState state, void *context) { NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithInt:1],@"ihandle",[NSNumber numberWithInt:state],@"state" ,nil]; [[NSNotificationCenter defaultCenter] postNotificationName:NotNameByCONNECT_DISCONNECT object:dict]; } static int delayVideo = 0;/*当前最高延时*/ static int okdelayVideo = 0;/*当前连续延时较好帧数*/ static int baddelayVideo = 0;/*当前较坏延时帧数个数*/ static int havedelayVideoCount = 0;/*当前帧数个数*/ NSDate *lastVideoTome;/*上一帧数据时间*/ - (void)toStartRecoderWithAVCaptureDevicePosition:(AVCaptureDevicePosition)position { if (!self.recoderManager) { self.recoderManager = [[RCVideoRecoderManager alloc] initWithAVCaptureDevicePosition:position]; self.recoderManager.delegate = self; } if (!self.recoderManager.isRecoding) { [self.recoderManager startRecording]; } } - (void)toStopRecoder { if (self.recoderManager) { [self.recoderManager stopRecording]; self.recoderManager = nil; } } - (void)toStartAudioRecoder { if (!self.audioRecoderMamager) { self.audioRecoderMamager = [[RCAudioRecoderMamager alloc] init]; self.audioRecoderMamager.delegate = self; } if (!self.audioRecoderMamager.isRecoding) { [self.audioRecoderMamager startRecording]; } } - (void)toStopAudioRecoder { if (self.audioRecoderMamager) { [self.audioRecoderMamager stopRecording]; self.audioRecoderMamager = nil; } } /** * @brief 请求I帧数据 */ - (void)requestIFrame { [self.liveStreamManager rc_requestIDFrame]; } #pragma mark - 流媒体服务器 // 初始化 - (BOOL)initVideoServer { return YES; } // 连接 - (void)connectVideoServer { if (!mySelf || haveBack || !ip || !internetVideoPort){ return; } if (!connectLock) { connectLock = [[NSLock alloc] init]; } [connectLock lock]; delayVideo = 0; okdelayVideo = 0; havedelayVideoCount = 0; RCStateInt result = -1; NSString *tempIP = ip; HLog(@"__连接ip__%@,端口__%@",ip,internetVideoPort); // RCCloudPhoneConnectType ConnectType = RCCloudPhoneConnectType_websocket; RCCloudPhoneVideoQuality VideoQuality = RCCloudPhoneVideoQuality_Default;//RCCloudPhoneVideoQuality_High; if([connectDeviceManager shareInstance].DeviceThirdIdMod.data.isPingOk) { ConnectType = RCCloudPhoneConnectType_udp; VideoQuality = RCCloudPhoneVideoQuality_Default; } result = [self.liveStreamManager rc_openWithIp:ip port:internetVideoPort.intValue connectType:ConnectType videoQuality:VideoQuality verify:@"123456" streamAESKey:nil]; if ([tempIP isEqualToString:ip]) { if (result < 0) { [self tryAgain]; } else if (result == 12) { //[[iToast makeText:@"画面异常,请重新进入"] show]; HLog(@"画面异常,请重新进入"); } } HLog(@"______连接____ip = %@ port = %@",ip,internetVideoPort); HLog(@"__________连接1111111__________"); HLog(@"__________连接成功__________"); lastVideoTome = [NSDate date]; NSString *dataStr = [RCCommandHelp commandResolution500WithType:(NSUInteger)BITRATE_WIFI_HD]; [self.liveStreamManager rc_sendJsonData:[dataStr UTF8String]]; // // 20210305 因为安卓做了分辨率适应 而iOS不需要 所以现在指定接收码率 这个就不用修改对应触摸点的范围比例了 W_PHONE H_PHONE // // 发送数据 // if ([deviceModel.buyVipType isEqualToString:CloudPhoneTypeWuJiPro]) { // NSString *commondStr = @"{\"data\":{\"height\":1920,\"width\":1080},\"type\":\"setPhoneSize\"}"; // [self send_data:commondStr]; // } // // //记录推流开始时间 // NSString *connectedDataStr = [RCCommandHelp commandConnectedWithDeviceId:deviceId]; // [self send_data:connectedDataStr]; [connectLock unlock]; } // 断开连接 - (void)disconnectVideoServer { NSString *commondStr = [RCCommandHelp toStopControllerDevice500]; [self send_data:commondStr]; HLog(@"\n-----...commondStr = %@....",commondStr); [self.liveStreamManager rc_disconnect]; } - (void)send_data:(NSString *)dataStr { if (canControl) { KyoLog(@"\n-commandChannelManager---%ld--%@",self.commandChannelManager.rc_socketStatus,dataStr); [self.commandChannelManager rc_sendData:dataStr]; } } #pragma mark - PlayerViewDelegate---下方虚拟按键 - (void)mueBtnBePressed:(id)sender { HLog(@"__________%s__________",__func__); NSString *dataStr = [RCCommandHelp commandBackOrHomeVolum500WithKeyCode:187]; HLog(@"\n-----...dataStr = %@....",dataStr); [self send_data:dataStr]; } - (void)homeBtnBePressed:(id)sender { HLog(@"__________%s__________",__func__); NSString *dataStr = [RCCommandHelp commandBackOrHomeVolum500WithKeyCode:3]; HLog(@"\n-----...dataStr = %@....",dataStr); [self send_data:dataStr]; } - (void)backBtnBePressed:(id)sender { HLog(@"__________%s__________",__func__); NSString *dataStr = [RCCommandHelp commandBackOrHomeVolum500WithKeyCode:4]; HLog(@"\n-----...dataStr = %@....",dataStr); [self send_data:dataStr]; } - (void)useInfoBtnBePressed:(id)sender { HLog(@"云手机推流界面 控制按钮点击手势开始"); [[NSNotificationCenter defaultCenter] postNotificationName:PlayerViewControlBtnTouchBeganNotification object:nil userInfo:nil]; HLog(@"云手机推流界面 控制按钮点击手势结束"); [[NSNotificationCenter defaultCenter] postNotificationName:PlayerViewControlBtnTouchEndNotification object:nil userInfo:nil]; HLog(@"__________%s__________",__func__); [[UIApplication sharedApplication] setStatusBarHidden:NO]; MySetViewController *nextVC = [[MySetViewController alloc] init]; //nextVC.whetherPhoneStatus = phoneTimeInfoDataModel.data.whetherPhoneStatus; [self.navigationController pushViewController:nextVC animated:YES]; self.isNeedRecyclResource = NO; KWeakSelf #pragma mark 重启盒子 //{"type":"reboot"} nextVC.needToReboot = ^{ [weakSelf needToRebootFun]; }; #pragma mark TV投屏 nextVC.needToTVP2P = ^{ NSString *commondStr = @"{\"type\":\"wakeupTV\"}"; [weakSelf send_data:commondStr]; }; #pragma mark 关闭TV投屏 nextVC.closeTVP2P = ^{ NSString *commondStr = @"{\"type\":\"TvOff\"}"; [weakSelf send_data:commondStr]; }; #pragma mark 恢复出厂盒子 nextVC.needToReset = ^{ [weakSelf needToResetFun]; }; #pragma mark 恢复出厂盒子 ok nextVC.needToResetAndOk = ^{ [weakSelf startCheckThridRuiYunTimerFun]; }; #pragma mark 获取云机剩余空间 nextVC.getBaseInfo = ^{ NSString *commondStr = @"{\"type\":\"getBaseInfo\"}"; [weakSelf send_data:commondStr]; }; #pragma mark 获取云机版本信息 nextVC.getSysInfo = ^{ NSString *commondStr = @"{\"type\":\"getSysInfo\"}"; [weakSelf send_data:commondStr]; }; #pragma mark 获取TV投屏状态 nextVC.getTvStatus = ^{ NSString *commondStr = @"{\"type\":\"TvStatus\"}"; [weakSelf send_data:commondStr]; }; } - (void)needToRebootFun { NSString *commondStr = @"{\"type\":\"reboot\"}"; [self send_data:commondStr]; [self startForceStartTimerFun]; //最后一帧 没显示正在重启问题 _canShowImgAndVoiceType = YES; _isRebootIngType = YES; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(30 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self reconnectDevice]; }); } - (void)needToResetFun { NSString *commondStr = @"{\"type\":\"reset\"}"; [self send_data:commondStr]; //最后一帧 没显示正在重启问题 //self->_canShowImgAndVoiceType = YES; _isResetingType = YES; } #pragma mark 启动timer 秒后检查是否软件重启成功 - (void)startForceStartTimerFun { if(forceStartTimer){ [forceStartTimer invalidate]; forceStartTimer = nil; } forceStartTimer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(gotoUpdateForceStartFun) userInfo:nil repeats:NO]; [[NSRunLoop currentRunLoop] addTimer:forceStartTimer forMode:NSRunLoopCommonModes]; } - (void)gotoUpdateForceStartFun { [self updateForceStartFun]; KWeakSelf dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(30 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [weakSelf reconnectDevice]; }); } - (void)stopForceStartTimerFun { if(forceStartTimer){ [forceStartTimer invalidate]; forceStartTimer = nil; } } #pragma mark 盒子链接成功后需要处理的各种各样事情 - (void)handlAllMsgAfterDidLinkFun { //获取云机尺寸 兼容 720*1080 &1080*1920 不同分辨率的展示和触控 NSString *getPhoneSizeStr = [RCCommandHelp getPhoneSizecommand]; [self send_data:getPhoneSizeStr]; //判断是否为需要改机 BOOL isNeedRandomChangeParams = [HWDataManager getBoolWithKey:Const_need_random_Change_Params]; if(isNeedRandomChangeParams) { NSString *commondStr = @"{\"type\":\"randomChangeParams\"}"; [self send_data:commondStr]; [HWDataManager setBoolWithKey:Const_need_random_Change_Params value:NO]; } [self fristConnectNeedGiveAMsgFun]; // 报链接失败 后面又连接上了 if(linkFailAlretVC && linkFailAlretVC.view.tag == 2){ mainBlock(^{ [self->linkFailAlretVC dismissViewControllerAnimated:YES completion:^{ }]; self->linkFailAlretVC = nil; }); } } #pragma mark 盒子第一次连接成功 给ws发送信息 单点登录 把其他账号挤下去 - (void)fristConnectNeedGiveAMsgFun{ if([self isPlayerViewIsTopVCFun]){ //等下再发 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self fristConnectNeedGiveAMsgFun]; }); return; } if(!_didSendfristMsg || _isLoginAgainType){ NSString *commondStr = @"{\"type\":\"forwardMsg\",\"data\":\"offline_notification\"}"; [self send_data:commondStr]; _didSendfristMsg = true; _isLoginAgainType = false; [self getPreferredLanguage]; //test code //[self LogoutByOtherFun]; } } #pragma mark 语言和市区 同步云机 -(void)getPreferredLanguage {//{"data":{"language":"zh-CN","timeZone":"Etc/GMT+8"},"type":"setLanguages"} // iOS 获取设备当前语言的代码 NSString *preferredLanguage = [[[NSBundle mainBundle] preferredLocalizations] firstObject]; HLog(@"当前语言:%@", preferredLanguage); //en-US 英文 ja-JP 日文 NSArray *arLanguages = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"]; NSLog(@"arLanguages:%@",arLanguages); ///获取设备当前地区的代码和APP语言环境 NSString *languageCode = [NSLocale preferredLanguages][0]; //目前支持 中文(简体 繁体) 英文 日语 if([languageCode rangeOfString:preferredLanguage].location != NSNotFound){ preferredLanguage = languageCode; } else{ preferredLanguage = @"en-US"; } NSString*gmtStr = [self UTCOffset]; HLog(@"%@",gmtStr); // //获取名字,如“GMT+08:00 NSString *commondStr = [NSString stringWithFormat:@"{\"type\":\"setLanguages\",\"data\":{\"language\":\"%@\",\"timeZone\":\"%@\"}}",preferredLanguage,gmtStr]; [self send_data:commondStr]; } -(NSString *)UTCOffset { NSTimeZone *localTZ = [NSTimeZone localTimeZone]; float offset = localTZ.secondsFromGMT/3600.0; if(offset > 0){ return [NSString stringWithFormat:@"Etc/GMT+%g",offset]; } return [NSString stringWithFormat:@"Etc/GMT%g",offset]; } #pragma mark 单点登录被挤下线弹框 - (void)LogoutByOtherFun { // [self disconnectVideoServer]; _canShowImgAndVoiceType = NO; //yyyy-MM-dd HH:mm:ss NSString*dateStr = [iTools getNowTimeString2]; if(dateStr && dateStr.length == 19){ dateStr = [dateStr substringWithRange:NSMakeRange(11, 5)]; } if(!_needShowLogoutDelayType){ _LogoutTimerStr = [[NSString alloc] initWithFormat:@"%@%@%@",NSLocalizedString(@"single_sign_on_Tips_one",nil),dateStr,NSLocalizedString(@"single_sign_on_Tips_two",nil)]; } if(_isPwdVCShow){ _needShowLogoutDelayType = YES; return; } _needShowLogoutDelayType = NO; NSString * loginAgainStr = NSLocalizedString(@"single_sign_on_login_again",nil); BOOL isOkBtnHighlight = YES; if(![connectDeviceManager shareInstance].DeviceThirdIdMod.data.isPrivacyMode){ loginAgainStr = @""; isOkBtnHighlight = NO; } /*弹窗提示重启*/ logoutAlertVC = [[ComontAlretViewController alloc] initWithTiTle:NSLocalizedString(@"single_sign_on_Tips_logout",nil) msg:_LogoutTimerStr imageStr:nil cancelTitle:NSLocalizedString(@"single_sign_on_exit",nil) okTitle:loginAgainStr isOkBtnHighlight:isOkBtnHighlight didClickOk:^{ } didClickCancel:^{ }]; logoutAlertVC.modalPresentationStyle = UIModalPresentationCustom; logoutAlertVC.delegate = self; [self presentViewController:logoutAlertVC animated:YES completion:^{ self->logoutAlertVC.view.superview.backgroundColor = [UIColor clearColor]; }]; _isLoginAgainType = YES; } #pragma mark 设置是否可以播放音频和视频 -(void)setShowPwdVCTypeFun { _isPwdVCShow = YES; } -(void)setShowImgAndVoiceTypeFun { _isPwdVCShow = NO; if(logoutAlertVC){ [logoutAlertVC dismissViewControllerAnimated:NO completion:^{ self->logoutAlertVC = nil; }]; } [self setShowImgAndVoiceTypeFun:YES]; if(_needShowLogoutDelayType){ [self LogoutByOtherFun]; } } #pragma mark 判断是否为密码界面登 函数意思写反了 ~~~~ - (BOOL)isPlayerViewIsTopVCFun { UIViewController*topVc = self.navigationController.viewControllers.lastObject; if(_isPwdVCShow || ![topVc isKindOfClass:[PlayerViewController class]]){ return YES; } return NO; } -(void)setShowImgAndVoiceTypeFun:(bool)isCan { if(isCan){//判断当前是否为最前面 才能播放 if([self isPlayerViewIsTopVCFun]){ return; } _canShowImgAndVoiceType = isCan; if(_isLoginAgainType ){ [self tryAgain]; [self fristConnectNeedGiveAMsgFun]; } } else{ _canShowImgAndVoiceType = isCan; } } #pragma mark - 显示秘钥 后续忘记密码要 -(void)showSecretkeyFun { mPlayerView.controlBtn.hidden = YES; playerShowSecretkeyView *view = [[playerShowSecretkeyView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_W, SCREEN_H)]; [self.view addSubview:view]; [self.view bringSubviewToFront:view]; KWeakSelf view.didCloseSecretKeyViewTip = ^{ self->mPlayerView.controlBtn.hidden = NO; [weakSelf showControlBtnTipFun]; }; } #pragma mark 显示首次浮标引导操作提示 - (void)showControlBtnTipFun{ BOOL didShowControlBtnTip = [HWDataManager getBoolWithKey:Const_did_Show_playView_controlBtn_Tip]; if(!didShowControlBtnTip && !_PlayerControlButTipV){ mPlayerView.controlBtn.hidden = YES; _PlayerControlButTipV = [[PlayerControlButTipView alloc] init]; _PlayerControlButTipV.backgroundColor = [UIColor hwColor:@"000000" alpha:0.6]; [self.view addSubview:_PlayerControlButTipV]; [self.view bringSubviewToFront:_PlayerControlButTipV]; [_PlayerControlButTipV mas_makeConstraints:^(MASConstraintMaker *make) { make.right.mas_equalTo(0); make.top.mas_equalTo(0.f); make.left.mas_equalTo(0.f); make.bottom.mas_equalTo(0.f); }]; KWeakSelf _PlayerControlButTipV.didKnowPlayerControlButTip = ^{ [weakSelf setMPlayerViewControlBtnHiddenBy:NO]; }; } } - (void)setMPlayerViewControlBtnHiddenBy:(BOOL)isHide { mPlayerView.controlBtn.hidden = isHide; } #pragma mark - PlayerControlViewDelegate---控制器按键 //- (void)stopShareBtnBePressed:(id)sender //{ // HLog(@"__________%s__________",__func__); // /*关闭分享成功后调用*/ // CloudPhoneModel *deviceDcit = [[UseAccountManage shareInstance].cloudPhoneListModel.diskInfo objectAtIndex:phoneIndex]; // NSString *userCardId = @""; // userCardId = [NSString stringWithFormat:@"%ld",deviceDcit.phoneId]; // // NSString *username = deviceDcit.username; // // if (0 == deviceShareStates || deviceShareStates == 3)/*分享中*/ // { // /*暂停分享*/ // NSString *reqsturl = [NSString stringWithFormat:SuspendScreenShareAPI,userCardId,username]; // [[UseAccountManage shareInstance] CommonGetWithCallBackCode:reqsturl Parameters:nil success:^(id _Nonnull responseObject) { // SuperModel *mod = [[SuperModel alloc] initWithDictionary:responseObject error:nil]; // [self removeNewIndicator]; // NSString *showStr = nil; // showStr = mod.msg; // if (mod.status && mod.status.integerValue == 0) // { // deviceDcit.screenShareStatus = 1; // self->deviceShareStates = 1; // [self->controlView pauseShareView]; // /*刷新视图 更新设备列表*/ // deviceDcit.screenShareStatus = self->deviceShareStates; // } // else // { // if (mod.msg == nil || [mod.msg isEqualToString:@""]) // { // showStr = @"暂停分享失败"; // } // [[iToast makeText:showStr] show]; // } // } // failure:^(NSError * _Nonnull error) { // [[iToast makeText:@"暂停分享失败"] show]; // [self removeNewIndicator]; // }]; // } // else if (1 == deviceShareStates)/*暂停分享*/ // { // /*开启分享*/ // NSString *reqsturl = [NSString stringWithFormat:StartAgainScreenShareAPI,userCardId,username]; // [[UseAccountManage shareInstance] CommonGetWithCallBackCode:reqsturl Parameters:nil success:^(id _Nonnull responseObject) { // SuperModel *mod = [[SuperModel alloc] initWithDictionary:responseObject error:nil]; // [self removeNewIndicator]; // NSString *showStr = nil; // showStr = mod.msg; // if (mod.status && mod.status.integerValue == 0) // { // self->deviceShareStates = 3; // deviceDcit.screenShareStatus = self->deviceShareStates; // [self->controlView shareingShareView]; // } // else // { // if (mod.msg == nil || [mod.msg isEqualToString:@""]) // { // showStr = @"开启分享失败"; // } // [[iToast makeText:showStr] show]; // } // } // failure:^(NSError * _Nonnull error) { // [[iToast makeText:@"开启分享失败"] show]; // [self removeNewIndicator]; // }]; // } //} - (void)showAlertToWaitForTrial:(NSInteger)mins { NSString *tipsStr = [NSString stringWithFormat:@"由于系统资源繁忙\n请在%ld分钟后再次进入云手机", mins]; NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:tipsStr attributes: @{NSFontAttributeName: [UIFont systemFontOfSize:16],NSForegroundColorAttributeName: HWCFD1D4Color}]; UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"知道了" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { }]; [sureAction setValue:HW3B7FFFColor forKey:@"titleTextColor"];//iOS8.3 [self showAlertWithTitle:nil message:string tilteAlignment:NSTextAlignmentCenter messageAlignment:NSTextAlignmentCenter sureAction:sureAction cancelAction:nil]; } #pragma mark - 新的手势回调委托 - (void)playerShowImageViewtouchesStr:(NSString *)commondStr { if (canControl) { [self send_data:commondStr]; } } -(void)initAlertWithTitle:(NSString *_Nullable)title message:(NSString *)message sureActionBlock:(sureActionBlock)sureActionBlock { UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { sureActionBlock(alertController); }]; [alertController addAction:cancelAction]; // 弹窗边框 UIView *subview = alertController.view.subviews.firstObject; UIView *alertContentView = subview.subviews.firstObject; alertContentView.layer.cornerRadius = 10; // alertContentView.layer.masksToBounds = YES; alertContentView.layer.shadowColor = [UIColor colorWithRed:30/255.0 green:32/255.0 blue:34/255.0 alpha:1.0].CGColor; alertContentView.layer.shadowOffset = CGSizeMake(0,0); alertContentView.layer.shadowOpacity = 1; alertContentView.layer.shadowRadius = 7; // 弹窗背景颜色 if (@available(iOS 13.0, *)) { alertController.overrideUserInterfaceStyle = UIUserInterfaceStyleDark; } UIViewController *currentVC = [[ShortcutManager shareInstance] findCurrentShowingViewController]; [currentVC presentViewController:alertController animated:YES completion:nil]; // [self presentViewController:alertController animated:YES completion:nil]; } #pragma - mark - 监听网络变化 - (void)networkStateChange:(NSNotification *)notification { /*处理*/ switch ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus) { case AFNetworkReachabilityStatusUnknown:/*网络状态未知*/ { ; } break; case AFNetworkReachabilityStatusNotReachable:/*网络不可用*/ { //[[iToast makeText:@"网络异常,请稍后重试!"] show]; // if (_ihandle > 0) // { [self disconnectVideoServer]; // } [self showNetErrorAlertFun:12]; } break; case AFNetworkReachabilityStatusReachableViaWWAN:/*流量*/ { mainBlock(^{ [self showNewIndicator]; }); [self tryAgain]; } break; case AFNetworkReachabilityStatusReachableViaWiFi:/*WiFi*/ { mainBlock(^{ [self showNewIndicator]; }); [self tryAgain]; } break; default: break; } } #pragma mark 网络异常弹框 -(void)showNetErrorAlertFun:(NSInteger)type { if(linkFailAlretVC){ return; } //重启后重连 出来的 if(_isRebootIngType){ if(![self isPlayerViewIsTopVCFun]){ [[iToast makeText:NSLocalizedString(@"player_link_rebooting_Tips",nil)] show]; } return; } if(_isResetingType){ if(![self isPlayerViewIsTopVCFun]){ [[iToast makeText:NSLocalizedString(@"my_set_no_Restore_Factorying_tips",nil)] show]; } return; } if([self isPlayerViewIsTopVCFun]){ //等下再发 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self showNetErrorAlertFun:type]; }); return; } //未连接成功过 if(_isFirstEnterPhone && type == 5){ type = 1; } NSString *linkErrTip = NSLocalizedString(@"player_link_fail_couldPhone_Tips",nil); if([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable){ linkErrTip = NSLocalizedString(@"player_link_fail_phone_Tips",nil); } linkErrTip = [[NSString alloc] initWithFormat:@"[%ld]%@",type,linkErrTip]; KWeakSelf linkFailAlretVC= [[ComontAlretViewController alloc] initWithTiTle:NSLocalizedString(@"player_link_fail_title",nil) msg:linkErrTip imageStr:nil cancelTitle:NSLocalizedString(@"single_sign_on_exit",nil) okTitle:NSLocalizedString(@"player_link_fail_tryAgain",nil) isOkBtnHighlight:YES didClickOk:^{ [weakSelf tryAgainInLinkFailFun]; } didClickCancel:^{ exit(0); }]; linkFailAlretVC.modalPresentationStyle = UIModalPresentationCustom; [self presentViewController:linkFailAlretVC animated:YES completion:^{ self->linkFailAlretVC.view.superview.backgroundColor = [UIColor clearColor]; }]; linkFailAlretVC.view.tag = type; } - (void)tryAgainInLinkFailFun { if([[connectDeviceManager shareInstance] curConnectDeviceState] <= 3) { //瑞云发起重连 NSString *snStr = [connectDeviceManager shareInstance].DeviceThirdIdMod.data.sn; if(snStr){ _checkThridConnectNum = 1; [[connectDeviceManager shareInstance] getThridMsgBySN:snStr needReconnect:YES didNetEnd:^(bool didSuc) { }]; } return; } [self showNewIndicator]; reConnectAccount = 0; [self tryAgain]; linkFailAlretVC = nil; } BOOL inReconnect = NO; - (void)tryAgain { reConnectAccount++; HLog(@"yyyyyyyyyyyyy 重连次数 %ld ",reConnectAccount); //20231017 修改后台3分钟再次进入 不断转圈圈问题 if (reConnectAccount >0 && reConnectAccount == 50 ) { mainBlock(^{ if (self.isFirstEnterPhone) { self.isFirstEnterPhone = NO; } //重启后重连 出来的 不显示 if(!self->_isRebootIngType && !self->_isResetingType && ![self isPlayerViewIsTopVCFun]){ /*链接失败*/ //[[iToast makeText:NSLocalizedString(@"player_link_fail_tip",nil)] show]; [self showNetErrorAlertFun:5]; } }); return; } [self reconnectDevice]; } - (void)reconnectDevice{ globalBlock(^{ @synchronized (self) { inReconnect = YES; [self disconnectVideoServer]; if ([self initVideoServer]) { [self connectVideoServer]; } } }); } #pragma mark -- /*视频码率按钮文字、索引、指令 之间相互转换*/ - (NSUInteger)resolutionBtnIndexToTypeWithIndex:(NSInteger)index { NSInteger type = BITRATE_EXTREME_SPEED/*BITRATE_STANDARD_CLEARING*/; AFNetworkReachabilityStatus netStatus = [AFNetworkReachabilityManager sharedManager].networkReachabilityStatus; if (netWorkStates == AFNetworkReachabilityStatusReachableViaWiFi) { type = BITRATE_WIFI_STANDARD_CLEARING; } switch (index) { case 2:/*极速*/ type = BITRATE_EXTREME_SPEED; break; // case 1:/*高速*/ // type = BITRATE_HIGH_SPEED; // break; case 0:/*高清*/ if (netStatus == AFNetworkReachabilityStatusReachableViaWiFi) { type = BITRATE_WIFI_HD; } else { type = BITRATE_WIFI_STANDARD_CLEARING/*BITRATE_HD*/; } break; case 1:/*标清*/ if (netStatus == AFNetworkReachabilityStatusReachableViaWiFi) { type = BITRATE_WIFI_STANDARD_CLEARING; } else { type = BITRATE_EXTREME_SPEED/*BITRATE_STANDARD_CLEARING*/; } break; case 3:/*自动*/ type = BITRATE_AUTO; break; default: break; } return type; } - (NSInteger)resolutionBtnTypeToIndexWithType:(NSInteger)type { NSInteger index = 2; switch (type) { case BITRATE_EXTREME_SPEED: index = 2; break; // case BITRATE_HIGH_SPEED: // index = 1; // break; case BITRATE_WIFI_STANDARD_CLEARING/*BITRATE_HD*/: index = 0; break; // case BITRATE_EXTREME_SPEED/*BITRATE_STANDARD_CLEARING*/: // index = 1; // break; case BITRATE_AUTO: index = 3; break; default: index = 2; break; } return index; } - (NSString *)resolutionBtnIndexToStringWithType:(NSInteger)index { NSString *qualitySelectBtnString = @"标清"; switch (index) { case 2: qualitySelectBtnString = @"极速"; break; // case 1: // qualitySelectBtnString = @"高速"; // break; case 0: qualitySelectBtnString = @"高清"; break; case 1: qualitySelectBtnString = @"标清"; break; case 4: qualitySelectBtnString = @"自动"; break; default: break; } return qualitySelectBtnString; } #pragma mark -- /*通知添加与移除*/ - (void)addNSNotification { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkStateChange:) name:NetWorkChangeNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(connectDisconnect:) name:NotNameByCONNECT_DISCONNECT object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification 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(volumeChanged:) name:AVSystemController_SystemVolumeDidChangeNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(extensionRBDGetRbdDeviceNotification:) name:GetRbdDeviceNotification object:nil]; outputVolumeKVO = YES; [[AVAudioSession sharedInstance] addObserver:self forKeyPath:@"outputVolume" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:(void *)[AVAudioSession sharedInstance]]; // 控制按钮收拾开始、结束 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerViewControlBtnTouchBegan) name:PlayerViewControlBtnTouchBeganNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerViewControlBtnTouchEnd) name:PlayerViewControlBtnTouchEndNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setShowImgAndVoiceTypeFun) name:ShowImgAndVoiceNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setShowPwdVCTypeFun) name:ShowPwdVCNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(beginGotoUploadFileFun:) name:uploadFileBeginNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(suspendUploadFileFun:) name:uploadFileSuspendNotification object:nil]; } - (void)removeNSNotification { [[NSNotificationCenter defaultCenter] removeObserver:self name:NetWorkChangeNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:NotNameByCONNECT_DISCONNECT object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillTerminateNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:uploadFileBeginNotification object:nil]; if (outputVolumeKVO) { [[AVAudioSession sharedInstance] removeObserver:self forKeyPath:@"outputVolume" context:(void *)[AVAudioSession sharedInstance]]; outputVolumeKVO = NO; } [[NSNotificationCenter defaultCenter] removeObserver:self]; } #pragma mark -- 音视频数据透传回调 static double firstTime; static double lastTime; static int couneeee = 0; - (void)videoOutPutH264Data:(void *)h264Data dataLenth:(NSInteger)lenth { if (couneeee == 0) { firstTime = [[NSDate date] timeIntervalSince1970]; } couneeee++; [self.liveStreamManager rc_sendTransportData:(const char *)h264Data length:(int)lenth dataType:VirtualDataTypeVideo]; if (couneeee == 100) { lastTime = [[NSDate date] timeIntervalSince1970]; HLog(@"\nvideoOutPutH264DataTime --%f",lastTime - firstTime); } } - (void)audioOutPutData:(void *)audioData dataLenth:(NSInteger)lenth { [self.liveStreamManager rc_sendTransportData:(const char *)audioData length:(int)lenth dataType:VirtualDataTypeAudio]; } -(NSString *)hexStringWithData:(NSData *)data { const unsigned char* dataBuffer = (const unsigned char*)[data bytes]; if(!dataBuffer){ return nil; } NSUInteger dataLength = [data length]; NSMutableString* hexString = [NSMutableString stringWithCapacity:(dataLength * 2)]; for(int i = 0; i < dataLength; i++){ [hexString appendString:[NSString stringWithFormat:@"%02lx", (unsigned long)dataBuffer[i]]]; } NSString* result = [NSString stringWithString:hexString]; return result; } - (NSArray *)getAllIvar:(id)object { NSMutableArray *array = [NSMutableArray array]; unsigned int count; Ivar *ivars = class_copyIvarList([object class], &count); for (int i = 0; i < count; i++) { Ivar ivar = ivars[i]; const char *keyChar = ivar_getName(ivar); NSString *keyStr = [NSString stringWithCString:keyChar encoding:NSUTF8StringEncoding]; @try { id valueStr = [object valueForKey:keyStr]; NSDictionary *dic = nil; if (valueStr) { dic = @{keyStr : valueStr}; } else { dic = @{keyStr : @"值为nil"}; } [array addObject:dic]; } @catch (NSException *exception) {} } return [array copy]; } //系统声音改变 #pragma -mark 系统声音改变 -(void)volumeChanged:(NSNotification *)notification { if (!self.isNeedShowVoiceBar) { // 不需要展示音量工具条 return; } // /*音量开关打开时 允许发送指令 否则直接返回*/ // NSDictionary *loginDict = [[UseAccountManage shareInstance] getLoginInfo]; // NSString *account = [loginDict objectForKey:@"account"]; // NSString *key = [account stringByAppendingString:Const_Volume_Info_Dict]; // // NSDictionary *volumeDict = [[NSUserDefaults standardUserDefaults] objectForKey:key]; // // NSString *volumeStr = [volumeDict safeStringForKey:deviceId]; // // if (!volumeStr || ![volumeStr isEqualToString:@"1"]){ // return; // } // // float volume = [[[notification userInfo] objectForKey:@"AVSystemController_AudioVolumeNotificationParameter"] floatValue]; // HLog(@"FlyElephant-系统音量:%f", volume); // // if (volume == 0) // { // NSString *dataStr = [RCCommandHelp commandBackOrHomeVolum500WithKeyCode:25]; // // [self send_data:dataStr]; // } // else if (volume == 1) // { // NSString *dataStr = [RCCommandHelp commandBackOrHomeVolum500WithKeyCode:24]; // // [self send_data:dataStr]; // } } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if(context == (__bridge void *)[AVAudioSession sharedInstance]) { // /*音量开关打开时 允许发送指令 否则直接返回*/ // NSDictionary *loginDict = [[UseAccountManage shareInstance] getLoginInfo]; // NSString *account = [loginDict objectForKey:@"account"]; // NSString *key = [account stringByAppendingString:Const_Volume_Info_Dict]; // // NSDictionary *volumeDict = [[NSUserDefaults standardUserDefaults] objectForKey:key]; // // NSString *volumeStr = [volumeDict safeStringForKey:deviceId]; // // if (!volumeStr || ![volumeStr isEqualToString:@"1"]){ // return; // } // // float newValue = [[change objectForKey:@"new"] floatValue]; // float oldValue = [[change objectForKey:@"old"] floatValue]; // // if (newValue > oldValue) // { // HLog(@"\n-----音量增加"); // NSString *dataStr = [RCCommandHelp commandBackOrHomeVolum500WithKeyCode:24]; // // [self send_data:dataStr]; // } // else // { // HLog(@"\n-----音量降低"); // NSString *dataStr = [RCCommandHelp commandBackOrHomeVolum500WithKeyCode:25]; // // [self send_data:dataStr]; // } } } #pragma mark----------------------------------------------------------------------------------------------- #pragma mark - 画面渲染、画面调整相关 #pragma mark - 更新网络标识 以及自动码率 - (void)updateAutoRateAndNetWorkStates { int audio_time = 0; NSDate *nowTime = [NSDate date]; NSString *nowTimeStr = [NSString stringWithFormat:@"%f", (double)[nowTime timeIntervalSince1970]]; NSString *lastTimeStr = [NSString stringWithFormat:@"%f", (double)[lastVideoTome timeIntervalSince1970]]; audio_time = ([nowTimeStr doubleValue] - [lastTimeStr doubleValue]) * 1000; lastVideoTome = nowTime; static int frameCount = 200; if (0 == frameCount) { frameCount = 200; if (audio_time > 500 && !haveBack && self->netWorkStates != 0) { self->netWorkStates = 0; mainBlock(^{ [self->mPlayerView.controlBtn setBackgroundImage:[UIImage imageNamed:@"you_icon"] forState:(UIControlStateNormal)]; }); } else if (audio_time > 100 && !haveBack && self->netWorkStates != 1) { self->netWorkStates = 1; mainBlock(^{ [self->mPlayerView.controlBtn setBackgroundImage:[UIImage imageNamed:@"you_icon"] forState:(UIControlStateNormal)]; }); } else if (!haveBack && self->netWorkStates != 2) { self->netWorkStates = 2; mainBlock(^{ [self->mPlayerView.controlBtn setBackgroundImage:[UIImage imageNamed:@"you_icon"] forState:(UIControlStateNormal)]; }); } } else { frameCount--; } if (delayVideo < audio_time) { delayVideo = audio_time; } if (delayVideo < 80) { okdelayVideo++; } else { okdelayVideo = 0; } if (delayVideo > 120) { baddelayVideo++; } havedelayVideoCount++; if (havedelayVideoCount % 1000 == 0) { baddelayVideo = 0; } if (!haveBack && self->rate == 3) { if (baddelayVideo > 10) { /*降低码率*/ if (self->rateForAuto == BITRATE_WIFI_STANDARD_CLEARING/*BITRATE_HD*/ || self->rateForAuto == BITRATE_WIFI_HD) { if (self->rateForAuto == BITRATE_WIFI_STANDARD_CLEARING/*BITRATE_HD*/) { self->rateForAuto = BITRATE_EXTREME_SPEED/*BITRATE_STANDARD_CLEARING*/; } else { self->rateForAuto = BITRATE_WIFI_STANDARD_CLEARING; } } else if (self->rateForAuto == BITRATE_EXTREME_SPEED/*BITRATE_STANDARD_CLEARING*/ || self->rateForAuto == BITRATE_WIFI_STANDARD_CLEARING) { self->rateForAuto = BITRATE_EXTREME_SPEED; } // else if (mySelf->rateForAuto == BITRATE_HIGH_SPEED) // { // mySelf->rateForAuto = BITRATE_EXTREME_SPEED; // NSString *dataStr = [RCCommandHelp commondResolution500WithType:mySelf->rateForAuto]; // int result = send_data(mySelf->_ihandle, [dataStr UTF8String], (int)dataStr.length, 10.f); // } NSString *dataStr = [RCCommandHelp commandResolution500WithType:self->rateForAuto]; // send_data(mySelf->_ihandle, [dataStr UTF8String], (int)dataStr.length, 10.f); [self.liveStreamManager rc_sendJsonData:[dataStr UTF8String]]; baddelayVideo = 0; } if (okdelayVideo > 1000) { /*上升码率*/ if (self->rateForAuto == BITRATE_EXTREME_SPEED/*BITRATE_STANDARD_CLEARING*/ || self->rateForAuto == BITRATE_WIFI_STANDARD_CLEARING) { if (self->rateForAuto == BITRATE_EXTREME_SPEED/*BITRATE_STANDARD_CLEARING*/) { self->rateForAuto = BITRATE_WIFI_STANDARD_CLEARING/*BITRATE_HD*/; } else { self->rateForAuto = BITRATE_WIFI_HD; } } // else if (mySelf->rateForAuto == BITRATE_HIGH_SPEED) // { // mySelf->rateForAuto = BITRATE_EXTREME_SPEED/*BITRATE_STANDARD_CLEARING*/; // NSString *dataStr = [RCCommandHelp commondResolution500WithType:mySelf->rateForAuto]; // int result = send_data(mySelf->_ihandle, [dataStr UTF8String], (int)dataStr.length, 10.f); // } else if (self->rateForAuto == BITRATE_EXTREME_SPEED) { if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWiFi) { self->rateForAuto = BITRATE_WIFI_STANDARD_CLEARING; } else { self->rateForAuto = BITRATE_EXTREME_SPEED/*BITRATE_STANDARD_CLEARING*/; } } NSString *dataStr = [RCCommandHelp commandResolution500WithType:self->rateForAuto]; // send_data(mySelf->_ihandle, [dataStr UTF8String], (int)dataStr.length, 10.f); [self.liveStreamManager rc_sendJsonData:[dataStr UTF8String]]; okdelayVideo = 0; } } } #pragma mark - opengl渲染 - (void)showImageOpenglWithCIImage:(CIImage *)ciImage { if (USELOCALKEYBOARD){ ; }else{ CGFloat tempRate = ciImage.extent.size.width/ciImage.extent.size.height; if (w_h_rate != tempRate) { // ksharedAppDelegate.couldPhone_W_PHONE = ciImage.extent.size.width; // ksharedAppDelegate.couldPhone_H_PHONE = ciImage.extent.size.height; w_h_rate = tempRate; mainBlock(^{ [self updatePlayViewRate:tempRate]; }); } } [mPlayerView glkShowImage:ciImage]; } #pragma mark - UIImageView渲染 - (void)showImageUIImageViewWithCIImage:(CIImage *)ciImage pixelBufferRef:(CVPixelBufferRef)pixelBuff1 { CGImageRef videoImage = [videoContext createCGImage:ciImage fromRect:CGRectMake(0, 0, CVPixelBufferGetWidth(pixelBuff1), CVPixelBufferGetHeight(pixelBuff1))]; UIImage *image = [UIImage imageWithCGImage:videoImage]; CGFloat tempRate = image.size.width/image.size.height; mainBlock(^{ if (image) { if (USELOCALKEYBOARD){ ; }else{ if (w_h_rate != tempRate) { // ksharedAppDelegate.couldPhone_W_PHONE = ciImage.extent.size.width; // ksharedAppDelegate.couldPhone_H_PHONE = ciImage.extent.size.height; [self updatePlayViewRate:tempRate]; } } self->mPlayerView.showImageView.image = image; } }); CGImageRelease(videoImage); } #pragma mark -- /*画面布局调整*/ - (void)updatePlayViewRate:(CGFloat)tempRate { /*设置横竖屏*/ if (tempRate > 1) {/*横屏*/ [self setDeviceOrientation:(UIDeviceOrientationLandscapeRight)]; [mPlayerView setLanMas_makeWithImageRate:tempRate isOpenVirtual:YES isUsageMode:NO]; }else{/*竖屏*/ [self setDeviceOrientation:(UIDeviceOrientationPortrait)]; [mPlayerView setPoMas_makeWithImageRate:tempRate isOpenVirtual:YES isUsageMode:NO]; } } #pragma mark------------------------------------------------------------------------------------------------------------------ #pragma mark-提示 loading 相关 #pragma mark-添加带有文字loading - (void)addLoadingWithTipsView:(NSString *)tipsStr { if (loadingWithTipsView) { [loadingWithTipsView removeFromSuperview]; loadingWithTipsView = nil; } loadingWithTipsView = [self loadingViewWithTipsStr:tipsStr]; [self.view addSubview:loadingWithTipsView]; } - (void)removeLoadingWithTipsView { if (loadingWithTipsView) { [loadingWithTipsView removeFromSuperview]; loadingWithTipsView = nil; } } - (UIView *)loadingViewWithTipsStr:(NSString*)tipsStr { UIView *bgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_W, SCREEN_H)]; [bgView setBackgroundColor:RGBACOLOR(0, 0, 0, 0.5)]; FLAnimatedImage *image = [FLAnimatedImage animatedImageWithGIFData:[NSData dataWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"loadingWhiteGif" withExtension:@"gif"]]]; FLAnimatedImageView *upView = [[FLAnimatedImageView alloc] init]; [upView setFrame:CGRectMake((SCREEN_W - 65.f)/2.f, (SCREEN_H - 65.f)/2.f, 65.f, 65.f)]; [upView setContentMode:UIViewContentModeScaleAspectFill]; [upView setBackgroundColor:[ UIColor clearColor]]; upView.animatedImage = image; [bgView addSubview:upView]; /*标签文字*/ UILabel *tipsLabel = [[UILabel alloc] initWithFrame:CGRectMake((SCREEN_W - 100.f)/2.f, (SCREEN_H - 65.f)/2.f + 65.f + 10.f, 100.f*AUTOSCALE, 20.f)]; [tipsLabel setText:tipsStr]; [tipsLabel setBackgroundColor:[UIColor clearColor]]; [tipsLabel setTextColor:[UIColor whiteColor]]; [tipsLabel setFont:[UIFont systemFontOfSize:14.f]]; [tipsLabel setTextAlignment:(NSTextAlignmentCenter)]; [bgView addSubview:tipsLabel]; return bgView; } #pragma mark-添加loading -(void)showNewIndicator { dispatch_async(dispatch_get_main_queue(), ^{ if (self->wattingView == nil) { HLog(@"Tan +++++开"); self->wattingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; [self->wattingView setBackgroundColor:RGBACOLOR(0.f, 0.f, 0.f, 0.7)]; [self->wattingView.layer setCornerRadius:10.f]; self->wattingView.center = [[UIApplication sharedApplication] keyWindow].center;// 将wattingVideoImageindicator放于播放画面的中央位置 self->wattingView.hidden = NO; FLAnimatedImage *image = [FLAnimatedImage animatedImageWithGIFData:[NSData dataWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"loadingWhiteGif" withExtension:@"gif"]]]; FLAnimatedImageView *upView = [[FLAnimatedImageView alloc] init]; [upView setFrame:CGRectMake((100 - 65.f)/2.f, (100 - 65.f)/2.f, 65.f, 65.f)]; [upView setContentMode:UIViewContentModeScaleAspectFill]; [upView setBackgroundColor:[ UIColor clearColor]]; upView.animatedImage = image; [self->wattingView addSubview:upView]; [self->mPlayerView addSubview:self->wattingView]; } }); } -(void)removeNewIndicator { if (self->wattingView != nil) { [[self->wattingView viewWithTag:1111].layer removeAllAnimations]; self->wattingView.hidden = YES; [self->wattingView removeFromSuperview]; self->wattingView = nil; } } #pragma mark 定时器 - (void)setTimerCountDown { HLog(@"开启一个"); if (_timer) { // 取消定时器 [self cancelTimer]; } // 初始化值计时数据 self.adjustTime = 3; self.concentTime = [iTools getNowTimeStamp]; self.currentTime = 0; _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerChange) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes]; } - (void)cancelTimer { // 取消定时器 [_timer invalidate]; _timer = nil; } - (void)timerChange { self.currentTime++;// 0、定时器计数 [self extensionAdjustBtnFrameCheckAdjustTime];// 1、悬浮球3s后 自动靠边隐藏 [self checkConcentTime];// 3、30s之后 没有收到拉流数据 自动断开链接 } // 3、30s之后 没有收到拉流数据 自动断开链接 - (void)checkConcentTime { NSInteger now = [iTools getNowTimeStamp]; NSInteger timeDiff = now - self.concentTime; // 渲染时间与当前时间 时间差 if (self.concentTime == 0) { //云手机未连接成功 HLog(@"云手机未连接成功"); }else if (timeDiff >= 30) { // 30s 无渲染数据 if(!_needToDissconnectType && !_isLoginAgainType && [self isPlayerViewIsTopVCFun]){ HLog(@"云手机30s 无渲染数据 自动断开连接"); self.concentTime = [iTools getNowTimeStamp]; [self showNewIndicator]; [self tryAgain]; } /*弹窗提示*/ }else { // HLog(@"云手机渲染数据时间差:%zd", timeDiff); } } #pragma mark - 提示框 - (void)showAlertWithTitle:(NSAttributedString*_Nullable)atbTitle message:(NSAttributedString*_Nullable)atbmessage tilteAlignment:(NSTextAlignment)tilteAlignment messageAlignment:(NSTextAlignment)messageAlignment sureAction:(UIAlertAction*_Nullable)sureAction cancelAction:(UIAlertAction*_Nullable)cancelAction { // 当前控制器是UIAlertController 退出 UIViewController *currentVC = [[ShortcutManager shareInstance] findCurrentShowingViewController]; if ([currentVC isKindOfClass:[UIAlertController class]]) { //获得极致体验服务 请购买云手机(不退出 优先级最高) UIAlertController *alertVC = (UIAlertController *)currentVC; NSMutableAttributedString *attriMsg = [alertVC valueForKey:@"_attributedMessage"]; if ([attriMsg.string containsString:@"获得极致体验服务"]) { return; } HLog(@"%@",attriMsg.string); [currentVC dismissViewControllerAnimated:NO completion:nil]; } self.alertController = [UIAlertController alertControllerWithTitle:@"" message:@"" preferredStyle:UIAlertControllerStyleAlert]; if (atbTitle) { [self.alertController setValue:atbTitle forKey:@"_attributedTitle"]; } if (atbmessage) { [self.alertController setValue:atbmessage forKey:@"_attributedMessage"]; } UIView *subView1 = self.alertController.view.subviews[0]; if (subView1 && [subView1 subviews]) { UIView *subView2 = subView1.subviews[0]; if (subView2 && [subView2 subviews]) { UIView *subView3 = subView2.subviews[0]; if (subView3 && [subView3 subviews]) { UIView *subView4 = subView3.subviews[0]; if (subView4 && [subView4 subviews]) { UIView *subView5 = subView4.subviews[0]; if (subView5 && [[subView5 subviews] count] > 1) { for (UIView *msg in subView5.subviews) { if ([msg isKindOfClass:[UILabel class]]) { NSArray *trmp = [self getAllIvar:msg]; for (NSDictionary *dict in trmp) { if ([[dict allKeys] containsObject:@"_content"]) { NSAttributedString *dsfds = [dict objectForKey:@"_content"]; if ([atbTitle.string isEqualToString:dsfds.string]) { [(UILabel*)msg setTextAlignment:(tilteAlignment)]; } else if ([atbmessage.string isEqualToString:dsfds.string]) { if (((UILabel*)msg).numberOfLines == 0) { [(UILabel*)msg setTextAlignment:(messageAlignment)]; } else if (((UILabel*)msg).numberOfLines == 1) { [(UILabel*)msg setTextAlignment:NSTextAlignmentCenter]; } else { [(UILabel*)msg setTextAlignment:(NSTextAlignmentCenter)]; } } } } } } } } } } } if (sureAction) { [self.alertController addAction:sureAction]; } if (cancelAction) { [self.alertController addAction:cancelAction]; } // 弹窗边框 UIView *subview = self.alertController.view.subviews.firstObject; UIView *alertContentView = subview.subviews.firstObject; alertContentView.layer.cornerRadius = 10; // alertContentView.layer.masksToBounds = YES; alertContentView.layer.shadowColor = [UIColor colorWithRed:30/255.0 green:32/255.0 blue:34/255.0 alpha:1.0].CGColor; alertContentView.layer.shadowOffset = CGSizeMake(0,0); alertContentView.layer.shadowOpacity = 1; alertContentView.layer.shadowRadius = 7; // 弹窗背景颜色 if (@available(iOS 13.0, *)) { self.alertController.overrideUserInterfaceStyle = UIUserInterfaceStyleDark; } [self presentViewController:self.alertController animated:YES completion:nil]; } #pragma mark - 屏幕旋转相关 - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return UIInterfaceOrientationPortrait; } - (BOOL)shouldAutorotate { if (canRate)/*画面发现变化 状态变为YES*/ { canRate = NO;/*关键点 只能旋转一次*/ return YES; } //是否允许转屏 return NO;/*平时禁止*/ } - (UIInterfaceOrientationMask)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight; } #pragma mark -- /* 屏幕旋转通知接收函数*/ - (void)orientationChanged:(NSNotification *)notification { KyoLog(@"rotated"); } - (void)setDeviceOrientation:(UIDeviceOrientation)orientationPortrait { mainBlock(^{ UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; //isPortraitMode BOOL ScreenMode = ((UIDeviceOrientation)orientation == orientationPortrait); NSNumber *value = nil; if (ScreenMode) { } else { self.adjustTime = 3; if (orientationPortrait == UIDeviceOrientationLandscapeLeft){ [self->mPlayerView setLanMas_makeWithImageRate:16.0/9.0 isOpenVirtual:YES isUsageMode:NO]; // [self.basebgView mas_remakeConstraints:^(MASConstraintMaker *make) { // make.left.mas_equalTo(0); // make.right.mas_equalTo(0); // make.top.mas_equalTo(0); // make.bottom.mas_equalTo(0); // }]; /*悬浮按钮旋转*/ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self reSetPlayerViewFloatBtnFrame]; }); [self->mPlayerView.controlBtn setHidden:NO]; }else{ [self->mPlayerView setPoMas_makeWithImageRate:9.0/16.0 isOpenVirtual:YES isUsageMode:NO]; // [self.basebgView mas_remakeConstraints:^(MASConstraintMaker *make) { // make.left.mas_equalTo(0); // make.right.mas_equalTo(0); // make.top.mas_equalTo(0); // make.bottom.mas_equalTo(0); // }]; } self->canRate = YES;/*关键点 设置临时允许*/ value = [NSNumber numberWithInteger:orientationPortrait];//横竖屏值设置 [[UIDevice currentDevice] setValue:value forKey:@"orientation"];/*先将状态栏旋转(影响系统通知弹框方向)*/ [[NSNotificationCenter defaultCenter] postNotificationName:UIDeviceOrientationDidChangeNotification object:nil];/*发送通知*/ } }); } /*切换连接方式*/ - (void)connectTypeChange{ [self reconnectDevice]; } #pragma mark - UITextFieldDelegate 透传输入法委托 //- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{ // // /*长度为0时表示删除内容*/ // if (string.length > 0){ // NSString *replaceStr = [textField.text substringWithRange:range]; // HLog(@"\n000000要增加的文字:--%@-------",replaceStr); // replaceStr = [replaceStr stringByReplacingOccurrencesOfString:@" " withString:@""]; // HLog(@"\n111111要增加的文字:--%@-------",replaceStr); // for (NSInteger nFori = 0; nFori < replaceStr.length; nFori++) { // NSString *dataStr = [RCCommandHelp commandKeyboadInputStr:nil]; // [self.businessCommandChannelManager rc_sendData:dataStr]; // } // HLog(@"\n-----输入内容:--%@-------",string); // NSString *dataStr = [RCCommandHelp commandKeyboadInputStr:string]; // [self.businessCommandChannelManager rc_sendData:dataStr]; // } // else{ // HLog(@"\n-----删除:--%ld-------",range.length); // NSInteger needDeleteLength = range.length; // for (NSInteger nFori = 0; nFori < needDeleteLength; nFori++) { // NSString *dataStr = [RCCommandHelp commandKeyboadInputStr:nil]; // [self.businessCommandChannelManager rc_sendData:dataStr]; // // /*初始内容无法删除问题处理*/ // hidenTextField.text = @"1234"; // hidenTextFieldOldStr = @"1234"; // // /*如果两者内容差距较大 是否会有删除后出现两者内容不一样的情况*/ // if (![hidenTextField.text isEqualToString:hidenTextFieldOldStr]){ // /*两者不相等时需要做等值处理*/ // hidenTextFieldOldStr = hidenTextField.text; // } // } // } // // return YES; //} - (void)textFieldDidEndEditing:(UITextField *)textField{ HLog(@"\n-----输入法透传 1111111 关闭键盘-------"); NSString *dataStr = [RCCommandHelp commandClosePhoneKeyboad]; [self.businessCommandChannelManager rc_sendData:dataStr]; } -(BOOL)prefersHomeIndicatorAutoHidden { return YES; } @end