// // LCOnMonitorViewController.m // LCOnDemo // // Created by 陈嘉乐 on 2021/4/26. // #import "LCOnMonitorViewController.h" #import #import #import "LCUtlis.h" #import "LCApiKit.h" #import @interface LCOnMonitorViewController () @property (nonatomic,assign) BOOL playing; @property (nonatomic,assign) BOOL isInterrupt; @property (nonatomic,assign) BOOL isSpeaking; @property (nonatomic,strong) UIImage *snapImage; //截图 @property (nonatomic, strong) UIButton *backButton; // @property (nonatomic, strong) UILabel *titleUILabel; // @property (nonatomic, strong) UIView *centerView; //内容背景View @property (nonatomic, strong) UIView *videoView; @property (nonatomic, strong) UIButton *screenshotImgBtn; // @property (nonatomic, strong) UIButton *screenshotTextBtn; // @property (nonatomic, strong) UIButton *unlockImgBtn; // @property (nonatomic, strong) UIButton *unlockTextBtn; // @property (nonatomic,strong) dispatch_source_t openDoorTimer; @property (nonatomic, assign) int openDoorTimeout; /// 播放器 @property (nonatomic, strong) LCOpenSDK_PlayWindow *playWindow; @end @implementation LCOnMonitorViewController { BOOL isAccessAudio; BOOL isAccessVideo; BOOL isBackGround; BOOL iSVideoNotDetermined; BOOL iSAudioNotDetermined; NSString * tipStr; NSString * okStr; NSString * saveToTheAlbumsStr; NSString * operationFailedStr; NSString * screenshotStr; NSString * unlockStr; NSString * endOfMonitoringStr; NSString * unlockSuccessfullyStr; NSString * LCSdkToken; NSString * LCHostApi; CGFloat Height66; bool isShowErrorAlert; // int _openDoorTimeout; } - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = UIColor.whiteColor; Height66 = GetRealWidth(66); [self initLlanguage]; [self initTopBarView]; [self initCentetView]; [self initData]; [self initESVideo]; [self StartMonitoring]; // //暂时不支持开锁功能 // [self setUnlock:NO]; //注册开锁成功监听 [self addOpenSuccessAction]; // Do any additional setup after loading the view. } -(void)initLlanguage{ NSString *languageName = [[[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"] objectAtIndex:0]; // 简体中文 if ([languageName rangeOfString:@"zh-Hans"].location != NSNotFound) { tipStr = @"提示"; okStr = @"确认"; saveToTheAlbumsStr = @"已保存至手机相册."; operationFailedStr = @"操作失败"; screenshotStr = @"截图"; unlockStr = @"开锁"; endOfMonitoringStr = @"监视结束"; unlockSuccessfullyStr = @"开锁成功"; }else{ tipStr = @"Prompt"; okStr = @"OK"; saveToTheAlbumsStr = @"Saved to the albums."; operationFailedStr = @"Operation failed."; screenshotStr = @"Screenshot"; unlockStr = @"Unlock"; endOfMonitoringStr = @"End of monitoring"; unlockSuccessfullyStr = @"Unlock successfully"; } } //顶部View - (void)initTopBarView { UIView *TopView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, APP_TOP_BAR_HEIGHT)]; TopView.backgroundColor = HEXCOLORA(0xF7F7F7,1.0); [TopView addSubview:self.backButton]; [TopView addSubview:self.titleUILabel]; // [TopView addSubview:self.moreButton]; [self.view addSubview:TopView]; TopView.layer.shadowColor = [UIColor colorWithRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:0.25].CGColor; TopView.layer.shadowOffset = CGSizeMake(0,0.5); TopView.layer.shadowOpacity = 1; TopView.layer.shadowRadius = 0; } - (UIButton *)backButton{ if (_backButton == nil) { _backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, APP_STATUS_BAR_HEIGHT, 44, 44)]; [_backButton setImage:[UIImage imageNamed:@"ic_esvideo_on_back"] forState:UIControlStateNormal]; _backButton.imageEdgeInsets = UIEdgeInsetsMake(12,12,12,12); [_backButton.imageView setContentMode:UIViewContentModeScaleAspectFit]; [_backButton addTarget:self action:@selector(backAction) forControlEvents:UIControlEventTouchUpInside]; } return _backButton; } -(void)backAction{ [self.navigationController popViewControllerAnimated:true]; // [self dismissViewControllerAnimated:YES completion:NULL]; } -(UILabel *)titleUILabel{ if (_titleUILabel == Nil) { _titleUILabel = [[UILabel alloc] initWithFrame:CGRectMake(90, APP_STATUS_BAR_HEIGHT, self.view.frame.size.width - 180, 44)]; _titleUILabel.font = [UIFont fontWithName:APP_UIFont_BOLD size:18.0]; _titleUILabel.textColor = TextColor; _titleUILabel.text = @""; _titleUILabel.textAlignment = NSTextAlignmentCenter; } return _titleUILabel; } - (void)initCentetView { [self.view addSubview:self.centerView]; // [self.centerView addSubview:self.collectButton]; // [self.centerView addSubview:self.homeView]; [self.centerView addSubview:self.videoView]; [self.centerView addSubview:self.screenshotImgBtn]; [self.centerView addSubview:self.screenshotTextBtn]; [self.centerView addSubview:self.unlockImgBtn]; [self.centerView addSubview:self.unlockTextBtn]; } - (UIView *)centerView{ if (_centerView == nil) { _centerView = [[UIButton alloc] initWithFrame:CGRectMake(0, APP_TOP_BAR_HEIGHT, APP_SCREEN_WIDTH, APP_VISIBLE_HEIGHT)]; _centerView.backgroundColor = UIColor.whiteColor; // [self setRadiusWithView:_centerView]; } return _centerView; } -(void)setRadiusWithView:(UIView *)mView{ //顶部圆角 UIRectCorner corners = UIRectCornerTopLeft | UIRectCornerTopRight; if (@available(iOS 11.0, *)) { mView.layer.cornerRadius = 20; mView.layer.maskedCorners = (CACornerMask)corners; }else{ UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:mView.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(20,20)]; //创建 layer CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; maskLayer.frame = mView.bounds; //赋值 maskLayer.path = maskPath.CGPath; mView.layer.mask = maskLayer; } } -(UIView *)videoView{ if (_videoView == Nil) { _videoView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, GetRealWidth((210)))]; _videoView.backgroundColor = UIColor.lightGrayColor; _videoView.layer.shadowColor = [UIColor colorWithRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:0.25].CGColor; _videoView.layer.shadowOffset = CGSizeMake(0,0.5); _videoView.layer.shadowOpacity = 1; _videoView.layer.shadowRadius = 0; } return _videoView; } #pragma 截图图标按钮 - (UIButton *)screenshotImgBtn{ if (_screenshotImgBtn == nil) { _screenshotImgBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, Height66, Height66)]; [_screenshotImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_on_takephoto_unselect"] forState:UIControlStateNormal]; // [_screenshotImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_on_takephoto_select"] forState:UIControlStateSelected]; [_screenshotImgBtn.imageView setContentMode:UIViewContentModeScaleAspectFit]; [_screenshotImgBtn addTarget:self action:@selector(screenshotAction) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside]; [_screenshotImgBtn addTarget:self action:@selector(screenshotDownAction) forControlEvents:UIControlEventTouchDown]; _screenshotImgBtn.adjustsImageWhenHighlighted = NO; _screenshotImgBtn.center = CGPointMake(APP_SCREEN_WIDTH/4, GetRealWidth(276) + Height66/2); } return _screenshotImgBtn; } -(void)screenshotDownAction{ [_screenshotImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_on_takephoto_select"] forState:UIControlStateNormal]; [_screenshotTextBtn setTitleColor:TextSelectColor forState:UIControlStateNormal]; } -(void)screenshotAction{ [_screenshotImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_on_takephoto_unselect"] forState:UIControlStateNormal]; [_screenshotTextBtn setTitleColor:TextColor forState:UIControlStateNormal]; //截图 if(self.playWindow){ [self saveThumbImage]; } } #pragma 截图文字按钮 - (UIButton *)screenshotTextBtn{ if (_screenshotTextBtn == nil) { _screenshotTextBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, GetRealWidth(100), GetRealWidth(20))]; [_screenshotTextBtn setTitle:@"截图" forState:UIControlStateNormal]; _screenshotTextBtn.titleLabel.textAlignment = NSTextAlignmentCenter; _screenshotTextBtn.titleLabel.font = [UIFont fontWithName:APP_UIFont size:14.0]; [_screenshotTextBtn setTitleColor:TextColor forState:UIControlStateNormal]; // [_screenshotTextBtn setTitleColor:TextSelectColor forState:UIControlStateSelected]; [_screenshotTextBtn addTarget:self action:@selector(screenshotAction) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside]; [_screenshotTextBtn addTarget:self action:@selector(screenshotDownAction) forControlEvents:UIControlEventTouchDown]; _screenshotTextBtn.adjustsImageWhenHighlighted = NO; _screenshotTextBtn.center = CGPointMake(_screenshotImgBtn.center.x, GetRealWidth(364)); } return _screenshotTextBtn; } - (UIButton *)unlockImgBtn{ if (_unlockImgBtn == nil) { _unlockImgBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, Height66, Height66)]; [_unlockImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_on_unlock_unselect"] forState:UIControlStateNormal]; // [_unlockImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_on_unlock_select"] forState:UIControlStateSelected]; [_unlockImgBtn.imageView setContentMode:UIViewContentModeScaleAspectFit]; [_unlockImgBtn addTarget:self action:@selector(unlockAction) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside]; [_unlockImgBtn addTarget:self action:@selector(unlockDownAction) forControlEvents:UIControlEventTouchDown]; _unlockImgBtn.adjustsImageWhenHighlighted = NO; _unlockImgBtn.center = CGPointMake((APP_SCREEN_WIDTH / 4) * 3, GetRealWidth(276) + Height66/2); } return _unlockImgBtn; } -(void)unlockDownAction{ [_unlockImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_on_unlock_select"] forState:UIControlStateNormal]; [_unlockTextBtn setTitleColor:TextSelectColor forState:UIControlStateNormal]; } -(void)unlockAction{ [_unlockImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_on_unlock_unselect"] forState:UIControlStateNormal]; [_unlockTextBtn setTitleColor:TextColor forState:UIControlStateNormal]; //开锁 if(self.mLCCallDelegate != NULL){ [self.mLCCallDelegate onUnlockAction]; } } - (UIButton *)unlockTextBtn{ if (_unlockTextBtn == nil) { _unlockTextBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, GetRealWidth(100), GetRealWidth(20))]; [_unlockTextBtn setTitle:@"开锁" forState:UIControlStateNormal]; _unlockTextBtn.titleLabel.font = [UIFont fontWithName:APP_UIFont size:14.0]; _unlockTextBtn.titleLabel.textAlignment = NSTextAlignmentCenter; // _unlockTextBtn.titleLabel.textColor = TextColor; [_unlockTextBtn setTitleColor:[UIColor lightGrayColor] forState:UIControlStateDisabled]; [_unlockTextBtn setTitleColor:TextColor forState:UIControlStateNormal]; // [_unlockTextBtn setTitleColor:TextSelectColor forState:UIControlStateSelected]; [_unlockTextBtn addTarget:self action:@selector(unlockAction) forControlEvents:UIControlEventTouchUpInside]; [_unlockTextBtn addTarget:self action:@selector(unlockDownAction) forControlEvents:UIControlEventTouchDown]; _unlockTextBtn.adjustsImageWhenHighlighted = NO; _unlockTextBtn.center = CGPointMake(_unlockImgBtn.center.x, GetRealWidth(364)); } return _unlockTextBtn; } #pragma 开锁成功 -(void)setOpenDoorSuccess{ [self setUnlock:NO]; _openDoorTimeout = 0; [self startOpenDoorCountdown]; [self showUIAlertView:unlockSuccessfullyStr]; // // 开锁成功回调 // if(self.mESCallDelegate != NULL){ // [self.mESCallDelegate onUnlockAction]; // } } -(void)setUnlock:(BOOL)ISEnable{ [_unlockImgBtn setEnabled:ISEnable]; [_unlockTextBtn setEnabled:ISEnable]; } /** 开启倒计时 */ - (void)startOpenDoorCountdown { if (_openDoorTimeout > 20) { return; } _openDoorTimeout = 0; // GCD定时器 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); _openDoorTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); dispatch_source_set_timer(_openDoorTimer, dispatch_walltime(NULL, 0), 1.0 * NSEC_PER_SEC, 0); //每秒执行 dispatch_source_set_event_handler(_openDoorTimer, ^{ WEAKSELF_AT if(weakSelf_AT.openDoorTimeout >= 20 ){// 计时结束 // 关闭定时器 dispatch_source_cancel(weakSelf_AT.openDoorTimer); dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf_AT setUnlock:YES]; }); }else{// 计时中 weakSelf_AT.openDoorTimeout++; } }); // 开启定时器 dispatch_resume(_openDoorTimer); } #pragma SDK可视对讲 功能部分 -(void)initESVideo{ [self.centerView addSubview:[self.playWindow getWindowView]]; } -(void)initData{ [_screenshotTextBtn setTitle:screenshotStr forState:UIControlStateNormal]; [_unlockTextBtn setTitle:unlockStr forState:UIControlStateNormal]; _titleUILabel.text = [[LCApiKit sharedInstance] currentDeviceName]; // [_collectButton setSelected:_isCollect]; } //- (void)initSDKLog { // LCOpenSDK_LogInfo *info = [LCOpenSDK_LogInfo new]; // info.levelType = LogLevelTypeDebug; // [[LCOpenSDK_Log shareInstance] setLogInfo:info]; //} ///播放窗口懒加载 - (LCOpenSDK_PlayWindow *)playWindow { if (!_playWindow) { /** 1. 初始化播放窗口信息,包括位置大小以及索引 */ _playWindow = [[LCOpenSDK_PlayWindow alloc] initPlayWindow:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, GetRealWidth(210)) Index:0]; /** 2. 设置播放窗口背景色 */ [_playWindow setSurfaceBGColor:[UIColor blackColor]]; /** 3. 添加播放窗口到父视图 */ // [self.view addSubview:[m_play getWindowView]]; /** 4. 设置监听对象,可监听播放结果回调 */ [_playWindow setWindowListener:(id)self]; } return _playWindow; } //- (void)onResignActive{ // if (self.playWindow) { // [self.playWindow stopRtspReal:YES]; // // self.videoManager.isPlay = NO; // [self.playWindow stopAudio]; // } //} /** 暂停播放 */ - (void)stopPlay { if(self.playWindow){ [self.playWindow stopRtspReal:NO]; [self.playWindow stopAudio]; } } - (void)startPlay { if(self.playWindow == NULL) return; [self.playWindow stopRtspReal:NO]; [self.playWindow stopAudio]; /** 1. 初始化实时预览播放参数对象 */ LCOpenSDK_ParamReal *paramReal = [[LCOpenSDK_ParamReal alloc] init]; /** 2. 设置token,token根据AppId和AppSecret调用乐橙云开放平台获取 */ paramReal.accessToken = [[LCApiKit sharedInstance] lcSdkToken]; /** 3. 设置设备序列号 */ paramReal.deviceID = [[LCApiKit sharedInstance] currentDeviceId]; /** 4. 设置设备通道,对于单通道设备为0, 对于NVR等多通道设备为具体通道号 */ paramReal.channel = 0; /** 5. 设置码流模式,支持主码流和子码流 */ paramReal.defiMode = DEFINITION_MODE_HG; /** 6. 设置密钥,如果为用户自定义密钥为具体密钥, 非用户自定密钥可为设备序列号*/ paramReal.psk = [[LCApiKit sharedInstance] currentPsk]; /** 7. 设置播放密钥,非必传,传了会提升拉流速度 */ paramReal.playToken = [[LCApiKit sharedInstance] currentDevicePlayToken];; /** 8. 是否走拉流优化,YES会提升拉流速度,建议传YES即可 */ paramReal.isOpt = YES; /** 8. 开始播放 */ [_playWindow playRtspReal:paramReal]; } /** * 视频播放状态回调 * * @param code 错误码(根据type而定) * @param type 0, RTSP * 1, HLS * 99, OPENAPI * @param index 播放窗口索引值 */ /** 1. 播放结果回调,可根据错误码进行不同处理 */ - (void)onPlayerResult:(NSString*)code Type:(NSInteger)type Index:(NSInteger)index { // play WEAKSELF_AT(self); NSLog(@"LIVE_PLAY-CODE:%@,TYPE:%ld", code, type); //是否已经弹窗过 if(isShowErrorAlert) return;; dispatch_async(dispatch_get_main_queue(), ^{ if (99 == type) { if ([code isEqualToString:@"-1000"]) { //"网络请求失败 (%ld)" [weakSelf_AT showUIAlertViewWithBack:[NSString stringWithFormat:@"%@(%@)",self->endOfMonitoringStr, code]]; } else if (![code isEqualToString:@"0"]) { //"网络请求失败 (%ld)" [weakSelf_AT showUIAlertViewWithBack:[NSString stringWithFormat:@"%@(%@)",self->endOfMonitoringStr, code]]; } else { //成功 } } if (type == 5) { if ([code integerValue] != 0 && [code integerValue] != STATE_DHHTTP_OK) { [weakSelf_AT showUIAlertViewWithBack:[NSString stringWithFormat:@"%@(%@)",self->endOfMonitoringStr, code]]; } } if (type == 0) { if ([RTSP_Result_String(STATE_RTSP_DESCRIBE_READY) isEqualToString:code]) { // dispatch_async(dispatch_get_main_queue(), ^{ // }); return; } if ([RTSP_Result_String(STATE_RTSP_PLAY_READY) isEqualToString:code]) { // dispatch_async(dispatch_get_main_queue(), ^{ // }); return; } //提示失败 [weakSelf_AT showUIAlertViewWithBack:[NSString stringWithFormat:@"%@(%@)",self->endOfMonitoringStr, code]]; } }); return; } /** 2. 播放开始回调 */ - (void)onPlayBegan:(NSInteger)index { dispatch_async(dispatch_get_main_queue(), ^{ // self.videoManager.playStatus = 1001; // [self saveThumbImage]; // [self hideVideoLoadImage]; }); } /** 开始监控 */ -(void)StartMonitoring{ if (self.playWindow) { [self startPlay]; } } -(NSString *)getCurrentdateInterval { NSDate *datenow = [NSDate date]; NSString *timeSp = [NSString stringWithFormat:@"%ld", (long)([datenow timeIntervalSince1970]*1000)]; return timeSp; } -(void)showUIAlertView:(NSString *)mes { UIAlertController *alertController = [UIAlertController alertControllerWithTitle:tipStr message:mes preferredStyle:UIAlertControllerStyleAlert]; [alertController addAction:[UIAlertAction actionWithTitle:okStr style:UIAlertActionStyleCancel handler:nil]]; [self presentViewController:alertController animated:YES completion:nil]; } /// -(void)showUIAlertViewWithBack:(NSString *)mes { isShowErrorAlert = true; UIAlertController *alertController = [UIAlertController alertControllerWithTitle:tipStr message:mes preferredStyle:UIAlertControllerStyleAlert]; [alertController addAction:[UIAlertAction actionWithTitle:okStr style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [self backAction]; }]]; [self presentViewController:alertController animated:YES completion:nil]; } #pragma viewDidAppear -(void)viewDidAppear:(BOOL)animated{ //这个方法请根据App的具体情况调用 //在viewDidLoad中 调用requestAccessForAVMediaType: 是为了节约初始化的时间 //在viewDidAppear中调用requestAccessForAVMediaType: 是为了弹出提示打开权限的Alert //测试的时候发现如下情况:如果只把授权方法放到ViewDidAppear方法中处理,如果没有授权在初始化采集器时会失败。同样AlertView会因为View没有didLoad而导致present不出来 // if (!isAccessVideo || !isAccessAudio) { // [self requestAccessForAVMedia]; // } // if (!isAccessAudio) { // [self requestAccessForAVMedia]; // } } -(void)setIsInterrupt:(BOOL)isInterrupt{ // if (_es) { // _es.isInterrupt = isInterrupt; // } } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; } -(void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; [self stopPlay]; //防止用户不按挂断,或者不等收到对方的挂断,点击返回按钮。 // if(_es){ // [_es onHangup]; // [_es onStopCapture]; // [_es stopTalk]; // // _es.delegate = nil; // ESVideo.shareInstance.snapImageCallback = nil; // // _es.showView.removeFromSuperview; // } // [_es freeSubClass]; } -(void)dealloc{ NSLog(@"==============dealloc 1"); [[NSNotificationCenter defaultCenter] removeObserver:self]; NSLog(@"==============dealloc 2"); // [_es freeSubClass]; // NSLog(@"==============dealloc 3"); if(_openDoorTimer){ dispatch_source_cancel(_openDoorTimer); _openDoorTimer = nil; // OK } NSLog(@"==============dealloc 3"); } //#pragma mark ESVideoPhoneDelegate ////视频通话的状态代理事件,phoneEvent为返回的消息里面包含event状态与与event相关的数据 //-(void)getPhoneEvent_UI:(NSString *)phoneEvent{ // NSLog(@"==============ESVideoPhoneDelegate事件%@", phoneEvent); // NSArray *strArray = [phoneEvent componentsSeparatedByString:@"\r\n"]; // NSArray *eventArray = [strArray.firstObject componentsSeparatedByString:@"="]; // NSString *phoneEventStr = eventArray.lastObject; // // if([phoneEventStr isEqual:@"EVT_Ringing"]){ // // // [_mCallOrAccept setTitle:@"接听" forState:UIControlStateNormal]; // }else if([phoneEventStr isEqual:@"EVT_StartStream"]){ // // } else if([phoneEventStr isEqual:@"EVT_StopStream"]){ // // [_mCallOrAccept setTitle:@"反呼" forState:UIControlStateNormal]; // }else if([phoneEventStr isEqual:@"EVT_Connected"]){ // [self speaker:nil]; // // [_mCallOrAccept setTitle:@"通话中..." forState:UIControlStateNormal]; // }else if([phoneEventStr isEqual:@"EVT_MonitorConnected"]){ // _es.showView.hidden = NO; // [self speaker:nil]; // // [_mCallOrAccept setTitle:@"通话中..." forState:UIControlStateNormal]; // }else if([phoneEventStr isEqual:@"EVT_HangUp"]){ // // // // [CBToast showToastAction:endOfMonitoringStr]; // [self showUIAlertViewWithBack:endOfMonitoringStr]; // // [self backAction]; // // // // // [_mCallOrAccept setTitle:@"反呼" forState:UIControlStateNormal]; // }else if([phoneEventStr isEqual:@"EVT_P2POnlineStatusChanged"]){ // //EVT_P2PStarted(p2p初始化OK,可以连接),EVT_P2POnlineStatusChangedonline=1 // //p2p初始化成功,手机端目前没有这个回调了 // //_mCallOrAccept.enabled = YES; // //_monitorBtn.enabled = YES; // }else if([phoneEventStr isEqual:@"EVT_RECV_CUSTOM_DATA"]){ // //开门的结果从这里返回 // NSString *baseStr = [strArray[1] substringFromIndex:5]; // NSData *data = [[NSData alloc]initWithBase64EncodedString:baseStr options:NSDataBase64DecodingIgnoreUnknownCharacters]; // NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; // NSInteger status = [[dic valueForKey:@"status"]integerValue]; // if(status && status == 1){ // NSLog(@"开门成功"); // // // [self setOpenDoorSuccess]; // }else{ // NSLog(@"开门失败"); // } // } //} // //-(void)getAErrorForESVideoPhone:(NSString *)errorStr type:(NSUInteger)errortype{ // NSLog(@"==============ErrorForESVideo错误%@", errorStr); // //没有授权 // if (errortype == LMPVideoCaptureErrorNotAuthorized) { // NSLog(@"错误%@", errorStr); // } //} //#pragma mark AudioSession与Notifications处理 // //- (void) addObservers //{ // // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name: UIKeyboardWillChangeFrameNotification object: nil]; // // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sessionRuntimeError:) name:AVCaptureSessionRuntimeErrorNotification object:nil]; // // //isAccessVideo,如果AVCaptureSession没有new出来不会收到通知 // if (isAccessVideo) { // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sessionWasInterrupted:) name:AVCaptureSessionWasInterruptedNotification object:nil]; // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sessionInterruptionEnded:) name:AVCaptureSessionInterruptionEndedNotification object:nil]; // }else{ // //object:为nil 可能不会触发通知 // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterruption:) // name:AVAudioSessionInterruptionNotification object:[AVAudioSession // sharedInstance]]; // } // // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChangeListenerCallback:) name:AVAudioSessionRouteChangeNotification object:nil]; // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterForeground:) name:UIApplicationDidBecomeActiveNotification object:nil]; // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; //} // //- (void) sessionRuntimeError:(NSNotification*)notification //{ // NSError* error = notification.userInfo[AVCaptureSessionErrorKey]; // NSLog(@"Capture session runtime error: %@", error); // // // If media services were reset, and the last start succeeded, restart the session. // if (error.code == AVErrorMediaServicesWereReset) { // [_es onStopCapture]; // [_es stopTalk]; // } //} // //- (void)handleInterruption:(NSNotification *)notification //{ // NSUInteger interruptionType = [[[notification userInfo] // objectForKey:AVAudioSessionInterruptionTypeKey] unsignedIntegerValue]; // // if (AVAudioSessionInterruptionTypeBegan == interruptionType) // { // if (isBackGround) { // return; // } // [_es stopTalk]; // } // else if (AVAudioSessionInterruptionTypeEnded == interruptionType) // { // if (self.isInterrupt == NO) { // return; // }else{ // //直接在进入前台那个通知里面实现,实际上进入前台的方法会在这个方法前面调用,效果更好 // [self InterruptionEndedAVAudioSessionSetActiveYES]; // } // } //} // ////AVAudioPlayer 类和 AVAudioRecorder 类,当发生中断时,系统会自动暂停播放或录制 //- (void) sessionWasInterrupted:(NSNotification*)notification //{ // if (_playing == YES) { // self.isInterrupt = YES; // //AVCaptureSessionInterruptionReason // if (@available(iOS 9.0, *)) { // NSInteger reason = [notification.userInfo[AVCaptureSessionInterruptionReasonKey] integerValue]; //电话中断是1 // NSLog(@"Capture session was interrupted with reason %ld", (long)reason); // // //音频硬件暂时不可用而造成的中断,例如,电话或警报。 // if (reason == AVCaptureSessionInterruptionReasonAudioDeviceInUseByAnotherClient || // reason == AVCaptureSessionInterruptionReasonVideoDeviceInUseByAnotherClient) { // NSLog(@"AVCaptureSessionInterruptionReasonVideoDeviceInUseByAnotherClient"); // // //VAudioPlayer 类和 AVAudioRecorder 类,当发生中断时,系统会自动暂停播放或录制 // //Audio Queue Services, I/O audio unit // [_es onStopCapture]; // [_es stopTalk]; // /* // NSError *error = nil; // [[AVAudioSession sharedInstance] setActive:NO error:&error]; // if (error) { // NSLog(@"sessionWasInterruptedSetActiveNO error:%@", error); // } // */ // }else if (reason == AVCaptureSessionInterruptionReasonVideoDeviceNotAvailableInBackground){ // NSLog(@"AVCaptureSessionInterruptionReasonVideoDeviceNotAvailableInBackground"); // //如果是电话中断,不会走进入后台的通知,进入后台再切换到前台这里是不用处理的 // if (isBackGround) { // return; // } // [_es onStopCapture]; // [_es stopTalk]; // } // //多个应用程序资源争用质量下降。只有当应用程序占据全屏时,会话才能运行。 // else if (reason == AVCaptureSessionInterruptionReasonVideoDeviceNotAvailableWithMultipleForegroundApps) { // NSLog(@"AVCaptureSessionInterruptionReasonVideoDeviceNotAvailableWithMultipleForegroundApps"); // // Fade-in a label to inform the user that the camera is unavailable. // }else if (@available(iOS 11.1, *)) { // if (reason == AVCaptureSessionInterruptionReasonVideoDeviceNotAvailableDueToSystemPressure){ // NSLog(@"AVCaptureSessionInterruptionReasonVideoDeviceNotAvailableDueToSystemPressure"); // } // } else { // // Fallback on earlier versions // } // } else { // if (isBackGround) { // return; // } // [_es onStopCapture]; // [_es stopTalk]; // } // } //} // ////这个通知可能会获取不到, //- (void) sessionInterruptionEnded:(NSNotification*)notification //{ // // NSInteger reason = [notification.userInfo[AVCaptureSessionInterruptionReasonKey] integerValue]; // NSLog(@"Capture session interruption ended"); // if (self.isInterrupt == NO) { // return; // }else{ // //直接在进入前台那个通知里面实现,实际上进入前台的方法会在这个方法前面调用,效果更好 // [self InterruptionEndedAVAudioSessionSetActiveYES]; // } // //} // //-(void)InterruptionEndedAVAudioSessionSetActiveYES{ // if (isBackGround) { // return; // } // if (self.isInterrupt == YES) { // [_es onStartCapture]; // [_es startTalk]; // self.isInterrupt = NO; // } //} // - (void)speaker:(UIButton *)sender { // [_es stopTalk]; // // NSString *result = nil; // // //听筒状态 插耳塞后拔掉后恢复到默认设置 // // if (sender == nil) { // // result = [_sessionHelper speaker:NO]; // // }else{ // // if(!_isSpeaking){ // // result = [_sessionHelper speaker:YES]; // // _isSpeaking = YES; // // }else{ // // result = [_sessionHelper speaker:NO]; // // _isSpeaking = NO; // // } // // } // // if (result) { // // [sender setTitle:result forState:UIControlStateNormal]; // // [_es startTalk]; // // } // // if(!_isSpeaking){ //// result = [_sessionHelper speaker:YES]; // [_es resetAudioCaptureIsSpeak:YES]; // _isSpeaking = YES; // }else{ //// result = [_sessionHelper speaker:NO]; // [_es resetAudioCaptureIsSpeak:NO]; // _isSpeaking = NO; // } // if (result) { // // [sender setTitle:result forState:UIControlStateNormal]; // [_es startTalk]; // } } //- (void)audioRouteChangeListenerCallback:(NSNotification*)notification //{ // // NSDictionary *interuptionDict = notification.userInfo; // NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue]; // switch (routeChangeReason) { // case AVAudioSessionRouteChangeReasonNewDeviceAvailable: // //NSLog(@"AVAudioSessionRouteChangeReasonNewDeviceAvailable"); // //免提状态下耳机插入没有采集,同意切换到默认状态 // NSLog(@"耳机插入"); // [self speaker:nil]; // break; // case AVAudioSessionRouteChangeReasonOldDeviceUnavailable: // //NSLog(@"AVAudioSessionRouteChangeReasonOldDeviceUnavailable"); // NSLog(@"耳机拔出"); // [self speaker:nil]; // // break; // case AVAudioSessionRouteChangeReasonCategoryChange: // // called at start - also when other audio wants to play // //NSLog(@"AVAudioSessionRouteChangeReasonCategoryChange"); // break; // } //} /* 需要注意的是,有一个中断开始消息不一定会有一个中断结束消息,这就意味着中断结束的回调里的处理逻辑可能会没有被执行到。 所以需要关注当切到前台运行状态时,是不是需要重新激活你的 Audio Session。 */ - (void)willEnterForeground:(NSNotification*)notification{ NSLog(@"willEnterForeground"); // //初次启动会走这个通知(根页面),这时候是没有进入后台的 // if (isBackGround) { // return; // } // // [self InterruptionEndedAVAudioSessionSetActiveYES]; // // // 这里是考虑到用户没有授权,之后通过AlertAction跳转到设置页面授权后再回到APP时做的重新检测 // //跳转到设置页面,授权后返回页面,继续初始化采集器 // if(!isAccessAudio){ // [self requestAccessForAVMediaType:AVMediaTypeAudio]; // if (isAccessAudio) { // [_es initAudioCaptureSession]; // } // } // // if (isAccessAudio && isAccessVideo) { // return; // } // if (isAccessVideo && !isAccessAudio) { // [self requestAccessForAVMediaType:AVMediaTypeAudio]; // if (isAccessAudio) { // [_es initAudioCaptureSession]; // } // }else if (!isAccessVideo && isAccessAudio){ //// [self requestAccessForAVMediaType:AVMediaTypeVideo]; //// if (isAccessVideo) { //// [_es initVideoCaptureSession]; //// } // // }else if (!isAccessVideo && !isAccessAudio){ // [self requestAccessForAVMediaType:AVMediaTypeAudio]; //// [self requestAccessForAVMediaType:AVMediaTypeVideo]; // if (isAccessAudio) { // [_es initAudioCaptureSession]; // } //// if (isAccessVideo) { //// [_es initVideoCaptureSession]; //// } // } } - (void)willEnterBackground:(NSNotification *)notification { isBackGround = YES; } ////授权Alert //-(void)requestAccessForAVMedia{ // if (!isAccessAudio) { // [self requestAccessForAVMediaType:AVMediaTypeAudio]; // } // // if (!isAccessVideo) { // //// [self requestAccessForAVMediaType:AVMediaTypeVideo]; // // } // if (!iSAudioNotDetermined && iSVideoNotDetermined){ // [self creatAlertViewWith:@"授权请求" message:@"麦克风没有授权,请在设置中开启权限,否则将影响通讯功能。" cancel:@"确定"]; // }else if(iSAudioNotDetermined && !iSVideoNotDetermined){ // [self creatAlertViewWith:@"授权请求" message:@"相机没有授权,请在设置中开启权限,否则将影响通讯功能。" cancel:@"确定"]; // }else if(!iSAudioNotDetermined && !iSVideoNotDetermined){ // [self creatAlertViewWith:@"授权请求" message:@"麦克风与相机授权,请在设置中开启权限,否则将影响通讯功能。" cancel:@"确定"]; // } //} // //-(void)requestAccessForAVMediaType:(AVMediaType)type{ // if (type == AVMediaTypeVideo) { // isAccessVideo = YES; // iSVideoNotDetermined = YES; // }else{ // isAccessAudio = YES; // iSAudioNotDetermined = YES; // } // switch ([AVCaptureDevice authorizationStatusForMediaType:type]) // { // case AVAuthorizationStatusAuthorized: // { // break; // } // case AVAuthorizationStatusNotDetermined: // { // dispatch_suspend(dispatch_get_main_queue()); // [AVCaptureDevice requestAccessForMediaType:type completionHandler:^(BOOL granted) { // if (!granted) { // if (type == AVMediaTypeVideo) { // self->isAccessVideo = NO; // }else{ // self->isAccessAudio = NO; // } // } // dispatch_resume(dispatch_get_main_queue()); // }]; // break; // } // default: // { // if (type == AVMediaTypeVideo) { // isAccessVideo = NO; // iSVideoNotDetermined = NO; // }else{ // isAccessAudio = NO; // iSAudioNotDetermined = NO; // } // break; // } // } //} // //-(void)creatAlertViewWith:(NSString *)title message:(NSString *) msg cancel:(NSString *)cancelMsg{ // UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert]; // [alertController addAction:[UIAlertAction actionWithTitle:cancelMsg style:UIAlertActionStyleCancel handler:nil]]; // [alertController addAction:[UIAlertAction actionWithTitle:@"设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { // [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]; // }]]; // [self presentViewController:alertController animated:YES completion:nil]; //} #pragma 保存图片到相册 - (void)saveImageToPhotosAlbum:(UIImage *)savedImage { PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus]; if (status == PHAuthorizationStatusNotDetermined) { [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { if(status == PHAuthorizationStatusAuthorized) { UIImageWriteToSavedPhotosAlbum(savedImage, self, @selector(imageSavedToPhotosAlbum:didFinishSavingWithError:contextInfo:), NULL); } }]; } else { if (status == PHAuthorizationStatusAuthorized) { UIImageWriteToSavedPhotosAlbum(savedImage, self, @selector(imageSavedToPhotosAlbum:didFinishSavingWithError:contextInfo:), NULL); } } } // 指定回调方法 - (void)imageSavedToPhotosAlbum:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo { NSString *message = nil; if (!error) { message = saveToTheAlbumsStr; } else { message = operationFailedStr; } [self showUIAlertView:message]; } /** */ - (void)saveThumbImage { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); NSString *libraryDirectory = [paths objectAtIndex:0]; NSString *myDirectory = [libraryDirectory stringByAppendingPathComponent:@"ON+"]; NSString *picDirectory = [myDirectory stringByAppendingPathComponent:@"picture"]; NSDateFormatter *dataFormat = [[NSDateFormatter alloc] init]; [dataFormat setDateFormat:@"yyyyMMddHHmmss"]; NSString *strDate = [dataFormat stringFromDate:[NSDate date]]; NSString *datePath = [picDirectory stringByAppendingPathComponent:strDate]; NSString *picPath = [datePath stringByAppendingString:@".jpg"]; NSLog(@"test jpg name[%@]\n", picPath); NSFileManager *fileManage = [NSFileManager defaultManager]; NSError *pErr; BOOL isDir; if (NO == [fileManage fileExistsAtPath:myDirectory isDirectory:&isDir]) { [fileManage createDirectoryAtPath:myDirectory withIntermediateDirectories:YES attributes:nil error:&pErr]; } if (NO == [fileManage fileExistsAtPath:picDirectory isDirectory:&isDir]) { [fileManage createDirectoryAtPath:picDirectory withIntermediateDirectories:YES attributes:nil error:&pErr]; } [self.playWindow snapShot:picPath]; UIImage *image = [UIImage imageWithContentsOfFile:picPath]; [self saveImageToPhotosAlbum:image]; } - (void)addOpenSuccessAction { [[NSNotificationCenter defaultCenter] removeObserver:self name:LCCallDelegateOpenDoorSuccess object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setOpenDoorSuccess) name:LCCallDelegateOpenDoorSuccess object:nil]; } @end