//
|
// LCOnMonitorViewController.m
|
// LCOnDemo
|
//
|
// Created by 陈嘉乐 on 2021/4/26.
|
//
|
|
#import "LCOnMonitorViewController.h"
|
#import <AVFoundation/AVFoundation.h>
|
#import <Photos/Photos.h>
|
#import "LCUtlis.h"
|
#import "LCApiKit.h"
|
#import <LCOpenSDKDynamic/LCOpenSDKDynamic.h>
|
|
@interface LCOnMonitorViewController ()<LCOpenSDK_EventListener>
|
|
@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 isBackGround;
|
|
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<LCOpenSDK_EventListener>)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, (long)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];
|
|
//1.暂停SDK相关播放
|
[self stopPlay];
|
//2.Delegate释放
|
self.mLCCallDelegate = nil;
|
//3.定时器释放
|
if(_openDoorTimer){
|
dispatch_source_cancel(_openDoorTimer);
|
_openDoorTimer = nil; // OK
|
}
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
}
|
|
-(void)dealloc{
|
NSLog(@"==============dealloc 1");
|
}
|
|
//#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
|