// // ESvideoVideoIntercomViewController.m // ESVideoPhoneSDKDemo // // Created by é™ˆå˜‰ä¹ on 2020/5/11. // Copyright © 2020 eTouchSky. All rights reserved. // #import "ESvideoVideoIntercomViewController.h" #import "GDHDLUtlis.h" #import <AVFoundation/AVFoundation.h> #import <ESVideoPhoneSDk/ESVideoPhone.h> #import <ESVideoPhoneSDk/ESError.h> //#import "AudioSessionHelper.h" #import <Photos/Photos.h> #import <AudioToolbox/AudioToolbox.h> #import "ESVideo.h" @interface ESvideoVideoIntercomViewController ()<ESVideoPhoneDelegate> //@property (nonatomic,strong) AudioSessionHelper *sessionHelper; @property (nonatomic,strong) ESVideoPhone *es; @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) UIButton *moreButton; // @property (nonatomic, strong) UILabel *titleUILabel; // @property (nonatomic, strong) UIView *centerView; //内容背景View @property (nonatomic, strong) UILabel *topUILabel; //æ ‡é¢˜ @property (nonatomic, strong) UIButton *collectButton; //æ”¶è— @property (nonatomic, strong) UIView *videoView; @property (nonatomic, strong) UIView *homeView; @property (nonatomic, strong) UILabel *homeUILabel; //房间åå— @property (nonatomic, strong) UIView *unlockView; @property (nonatomic, strong) UIButton *screenshotImgBtn; //截图 @property (nonatomic, strong) UIButton *unlockImgBtn; //å¼€é” @property (nonatomic, strong) UIButton *hangUpImgBtn;//æŒ‚æ–æŒ‰é’® @property (nonatomic, strong) UIButton *hangUpTextBtn; @property (nonatomic, strong) UIButton *answerImgBtn;//æŽ¥å¬æŒ‰é’® @property (nonatomic, strong) UIButton *answerTextBtn; @property (nonatomic, strong) UIButton *calltimeBtn; //é€šè¯æ—¶é—´æŒ‰é’® //定时器 @property (nonatomic,strong) dispatch_source_t countdownTimer; @property (nonatomic,strong) dispatch_source_t openDoorTimer; @property (nonatomic, assign) int openDoorTimeout; @property (nonatomic, assign) int callTimeout; @end @implementation ESvideoVideoIntercomViewController{ BOOL isAccessAudio; BOOL isAccessVideo; BOOL isBackGround; BOOL iSVideoNotDetermined; BOOL iSAudioNotDetermined; NSString * tipStr; NSString * okStr; NSString * saveToTheAlbumsStr; NSString * operationFailedStr; NSString * refuseStr; NSString * answerStr; NSString * unlockSuccessfullyStr; NSString * callingStr; NSString * hangUpStr; // int openDoorTimeout; //全局å˜é‡ SystemSoundID sound; } - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = HEXCOLORA(0xF5F6FA, 1.0); [self initLlanguage]; [self initTopBarView]; [self initCentetView]; [self initData]; // [self setAnswerBtnEnable:NO]; [self initESVideo]; //开始å呼 [self StartReverseCall]; [self ShowCalltimeBtn:callingStr]; // 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 = @"æ“作失败"; refuseStr = @"æ‹’ç»"; answerStr = @"接å¬"; hangUpStr = @"挂æ–"; unlockSuccessfullyStr = @"开锿ˆåŠŸ"; callingStr = @"æ¥ç”µä¸..."; }else{ tipStr = @"Prompt"; okStr = @"OK"; saveToTheAlbumsStr = @"Saved to the albums."; operationFailedStr = @"Operation failed."; refuseStr = @"Refuse"; answerStr = @"Answer"; hangUpStr = @"Hang up"; unlockSuccessfullyStr = @"Unlock successfully"; callingStr = @"Incoming call"; } } - (void)initTopBarView { UIView *TopView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, APP_TOP_BAR_HEIGHT)]; TopView.backgroundColor = HEXCOLORA(0xF9F9F9,1.0); // [TopView addSubview:self.backButton]; // [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_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]; } - (UIButton *)moreButton{ if (_moreButton == nil) { _moreButton = [[UIButton alloc] initWithFrame:CGRectMake(APP_SCREEN_WIDTH - 64, APP_STATUS_BAR_HEIGHT, 44, 44)]; [_moreButton setImage:[UIImage imageNamed:@"ic_esvideo_more"] forState:UIControlStateNormal]; _moreButton.imageEdgeInsets = UIEdgeInsetsMake(12,12,12,12); [_moreButton.imageView setContentMode:UIViewContentModeScaleAspectFit]; [_moreButton addTarget:self action:@selector(moreAction) forControlEvents:UIControlEventTouchUpInside]; } return _moreButton; } -(void)moreAction{ } - (void)initCentetView { [self.view addSubview:self.centerView]; // [self.centerView addSubview:self.collectButton]; [self.centerView addSubview:self.homeView]; [self.centerView addSubview:self.unlockView]; [self.unlockView addSubview:self.screenshotImgBtn]; [self.unlockView addSubview:self.unlockImgBtn]; [self.centerView addSubview:self.hangUpImgBtn]; [self.centerView addSubview:self.hangUpTextBtn]; [self.centerView addSubview:self.answerImgBtn]; [self.centerView addSubview:self.answerTextBtn]; [self.centerView addSubview:self.calltimeBtn]; } - (UIView *)centerView{ if (_centerView == nil) { _centerView = [[UIButton alloc] initWithFrame:CGRectMake(0, APP_TOP_BAR_HEIGHT + 20, APP_SCREEN_WIDTH, APP_VISIBLE_HEIGHT-20)]; _centerView.backgroundColor = UIColor.whiteColor; [self setRadiusWithView:_centerView]; _topUILabel= [[UILabel alloc] initWithFrame:CGRectMake(80, GetRealHeight(20), APP_SCREEN_WIDTH-160, GetRealHeight(24))]; _topUILabel.font = [UIFont fontWithName:APP_UIFont_BOLD size:15.0]; _topUILabel.textColor = HEXCOLORA(0x333333, 1.0); _topUILabel.text = @"二次确认机"; _topUILabel.textAlignment = NSTextAlignmentCenter; [_centerView addSubview:self.topUILabel]; } 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; } } - (UIButton *)collectButton{ if (_collectButton == nil) { _collectButton = [[UIButton alloc] initWithFrame:CGRectMake(APP_SCREEN_WIDTH - 44, 20, 24, 24)]; [_collectButton setImage:[UIImage imageNamed:@"ic_esvideo_collect_select"] forState:UIControlStateSelected]; [_collectButton setImage:[UIImage imageNamed:@"ic_esvideo_collect_unselect"] forState:UIControlStateNormal]; // _collectButton.imageEdgeInsets = UIEdgeInsetsMake(12,12,12,12); [_collectButton.imageView setContentMode:UIViewContentModeScaleAspectFit]; [_collectButton addTarget:self action:@selector(collectAction) forControlEvents:UIControlEventTouchUpInside]; } return _collectButton; } -(void)collectAction{ [_collectButton setSelected:!_collectButton.isSelected]; _isCollect = _collectButton.isSelected; if(self.collectButtonCallBack != NULL){ self.collectButtonCallBack(_isCollect); } } - (UIView *)homeView{ if (_homeView == nil) { _homeView = [[UIView alloc] initWithFrame:CGRectMake(0, GetRealHeight(268), APP_SCREEN_WIDTH, GetRealHeight(36))]; _homeView.backgroundColor = HEXCOLORA(0x232323, 1.0); UIImageView *mUIImageView= [[UIImageView alloc] initWithFrame:CGRectMake(GetRealWidth(20), GetRealHeight(4), GetRealHeight(28), GetRealHeight(28))]; mUIImageView.image = [UIImage imageNamed:@"ic_esvideo_home"]; [mUIImageView setContentMode:UIViewContentModeScaleAspectFit]; [_homeView addSubview:mUIImageView]; [_homeView addSubview:self.homeUILabel]; } return _homeView; } - (UILabel *)homeUILabel{ if (_homeUILabel == nil) { _homeUILabel = [[UILabel alloc] initWithFrame:CGRectMake(GetRealWidth(52), 0, APP_SCREEN_WIDTH - GetRealWidth(100), _homeView.frame.size.height)]; _homeUILabel.font = [UIFont fontWithName:APP_UIFont size:12.0]; _homeUILabel.textColor = [UIColor whiteColor]; _homeUILabel.text = @"1æ ‹203"; } return _homeUILabel; } - (UIView *)unlockView{ if (_unlockView == nil) { _unlockView = [[UIView alloc] initWithFrame:CGRectMake(0, GetRealHeight(304), APP_SCREEN_WIDTH, GetRealHeight(48))]; _unlockView.backgroundColor = HEXCOLORA(0x232323, 1.0); _unlockView.layer.backgroundColor = [UIColor colorWithRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1.0].CGColor; _unlockView.layer.shadowColor = [UIColor colorWithRed:204/255.0 green:204/255.0 blue:204/255.0 alpha:0.4].CGColor; _unlockView.layer.shadowOffset = CGSizeMake(0,0.5); _unlockView.layer.shadowOpacity = 1; _unlockView.layer.shadowRadius = 0; } return _unlockView; } - (UIButton *)screenshotImgBtn{ if (_screenshotImgBtn == nil) { _screenshotImgBtn = [[UIButton alloc] initWithFrame:CGRectMake(GetRealWidth(65), GetRealHeight(6), GetRealHeight(36), GetRealHeight(36))]; [_screenshotImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_takephoto_unselect"] forState:UIControlStateNormal]; // [_screenshotImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_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; } return _screenshotImgBtn; } -(void)screenshotDownAction{ [_screenshotImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_takephoto_select"] forState:UIControlStateNormal]; } -(void)screenshotAction{ [_screenshotImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_takephoto_unselect"] forState:UIControlStateNormal]; //截图 if(_es){ [_es onSnap]; } } - (UIButton *)unlockImgBtn{ if (_unlockImgBtn == nil) { _unlockImgBtn = [[UIButton alloc] initWithFrame:CGRectMake(APP_CONTENT_WIDTH-GetRealWidth(65)-GetRealHeight(36), GetRealHeight(6), GetRealHeight(36), GetRealHeight(36))]; [_unlockImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_unlock_unselect"] forState:UIControlStateNormal]; // [_unlockImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_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; } return _unlockImgBtn; } -(void)unlockDownAction{ [_unlockImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_unlock_select"] forState:UIControlStateNormal]; } -(void)unlockAction{ [_unlockImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_unlock_unselect"] forState:UIControlStateNormal]; //å¼€é” if(_es){ [_es openTheDoorWithRoomid:_mESRoomID]; } } #pragma 挂æ–å’Œå¼€é” - (UIButton *)hangUpImgBtn{ if (_hangUpImgBtn == nil) { _hangUpImgBtn = [[UIButton alloc] initWithFrame:CGRectMake(GetRealWidth(54), GetRealHeight(448), GetRealHeight(58), GetRealHeight(58))]; [_hangUpImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_hangup"] forState:UIControlStateNormal]; // [_hangUpImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_hangup"] forState:UIControlStateSelected]; [_hangUpImgBtn.imageView setContentMode:UIViewContentModeScaleAspectFit]; [_hangUpImgBtn addTarget:self action:@selector(hangUpAction) forControlEvents:UIControlEventTouchUpInside]; } return _hangUpImgBtn; } //æŒ‚æ–æŒ‰é’®äº‹ä»¶ -(void)hangUpAction{ [self backAction]; } - (UIButton *)hangUpTextBtn{ if (_hangUpTextBtn == nil) { _hangUpTextBtn = [[UIButton alloc] initWithFrame:CGRectMake(33, 514, GetRealWidth(100), GetRealHeight(21))]; [_hangUpTextBtn setTitle:@"æ‹’ç»" forState:UIControlStateNormal]; _hangUpTextBtn.titleLabel.textAlignment = NSTextAlignmentCenter; _hangUpTextBtn.titleLabel.font = [UIFont fontWithName:APP_UIFont size:15.0]; [_hangUpTextBtn setTitleColor:TextColor forState:UIControlStateNormal]; [_hangUpTextBtn setTitleColor:TextSelectColor forState:UIControlStateSelected]; [_hangUpTextBtn addTarget:self action:@selector(screenshotAction) forControlEvents:UIControlEventTouchUpInside]; _hangUpTextBtn.center = CGPointMake(_hangUpImgBtn.center.x, GetRealHeight(525)); } return _hangUpTextBtn; } - (UIButton *)answerImgBtn{ if (_answerImgBtn == nil) { _answerImgBtn = [[UIButton alloc] initWithFrame:CGRectMake(APP_CONTENT_WIDTH-GetRealWidth(54)-GetRealHeight(58), GetRealHeight(448), GetRealHeight(58), GetRealHeight(58))]; [_answerImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_answer"] forState:UIControlStateNormal]; // [_answerImgBtn setImage:[UIImage imageNamed:@"ic_esvideo_answer"] forState:UIControlStateSelected]; [_answerImgBtn.imageView setContentMode:UIViewContentModeScaleAspectFit]; [_answerImgBtn addTarget:self action:@selector(answerIAction) forControlEvents:UIControlEventTouchUpInside]; } return _answerImgBtn; } -(void)answerIAction{ [self stopPlaySystemSound]; if(_es){ // [self stopPlaySystemSound]; [_es onAccept]; }else{ NSLog(@"ESåˆå§‹åŒ–失败"); } _answerImgBtn.hidden = YES; _answerTextBtn.hidden = YES; //æŒ‚æ–æŒ‰é’®ç§»åЍä¸é—´ // _hangUpImgBtn.frame = CGRectMake(159, 448, 58, 58); // _hangUpTextBtn.frame = CGRectMake(138, 514, 100, 21); _hangUpImgBtn.center = CGPointMake(APP_CONTENT_WIDTH/2, _hangUpImgBtn.center.y); _hangUpTextBtn.center = CGPointMake(APP_CONTENT_WIDTH/2, _hangUpTextBtn.center.y); [_hangUpTextBtn setTitle:hangUpStr forState:UIControlStateNormal]; //开始计时 _callTimeout = 0; [self startCountdown]; } -(void)setAnswerBtnEnable:(BOOL)ISEnable{ [_answerImgBtn setEnabled:ISEnable]; [_answerTextBtn setEnabled:ISEnable]; } - (UIButton *)answerTextBtn{ if (_answerTextBtn == nil) { _answerTextBtn = [[UIButton alloc] initWithFrame:CGRectMake(242, 514, GetRealWidth(100), GetRealHeight(21))]; [_answerTextBtn setTitle:@"接å¬" forState:UIControlStateNormal]; _answerTextBtn.titleLabel.font = [UIFont fontWithName:APP_UIFont size:15.0]; _answerTextBtn.titleLabel.textAlignment = NSTextAlignmentCenter; // _unlockTextBtn.titleLabel.textColor = TextColor; [_answerTextBtn setTitleColor:TextColor forState:UIControlStateNormal]; [_answerTextBtn setTitleColor:[UIColor lightGrayColor] forState:UIControlStateDisabled]; [_answerTextBtn setTitleColor:TextSelectColor forState:UIControlStateSelected]; [_answerTextBtn addTarget:self action:@selector(unlockAction) forControlEvents:UIControlEventTouchUpInside]; _answerTextBtn.center = CGPointMake(_answerImgBtn.center.x, GetRealHeight(525)); } return _answerTextBtn; } - (UIButton *)calltimeBtn{ if (_calltimeBtn == nil) { _calltimeBtn = [[UIButton alloc] initWithFrame:CGRectMake(242, GetRealHeight(382), GetRealWidth(100), GetRealHeight(30))]; _calltimeBtn.backgroundColor = HEXCOLORA(0x000000, 0.4); [_calltimeBtn setTitle:@"00:00" forState:UIControlStateNormal]; _calltimeBtn.titleLabel.font = [UIFont fontWithName:APP_UIFont size:14.0]; _calltimeBtn.titleLabel.textAlignment = NSTextAlignmentCenter; [_calltimeBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; _calltimeBtn.hidden = YES; _calltimeBtn.layer.cornerRadius = 15; _calltimeBtn.center = CGPointMake(APP_CONTENT_WIDTH/2, GetRealHeight(397)); } return _calltimeBtn; } -(void)ShowTime:(int)nowTime { if(_calltimeBtn.hidden) _calltimeBtn.hidden = NO; NSString *timeStr = [self timeFormatted:nowTime]; [self setCalltimeButtonText:timeStr isTime:YES]; } -(void)ShowCalltimeBtn:(NSString*) mesStr { if(_calltimeBtn.hidden) _calltimeBtn.hidden = NO; [self setCalltimeButtonText:mesStr isTime:NO]; } /* æ ¹æ®æ–‡å—调整按钮宽 */ -(void)setCalltimeButtonText:(NSString*) mesStr isTime:(BOOL)isTime { [_calltimeBtn setTitle:mesStr forState:UIControlStateNormal]; if(isTime){ _calltimeBtn.frame = CGRectMake(0, 0, GetRealWidth(80), GetRealHeight(30)); }else{ _calltimeBtn.frame = CGRectMake(0, 0, GetRealWidth(115), GetRealHeight(30)); } _calltimeBtn.center = CGPointMake(APP_SCREEN_WIDTH/2, GetRealHeight(397)); } - (NSString *)timeFormatted:(int)totalSeconds { int seconds = totalSeconds % 60; int minutes = (totalSeconds / 60); return [NSString stringWithFormat:@"%02d:%02d", minutes, seconds]; } - (int *)getTextWidth:(UIButton*) btn { int textWidth = 0; //  CGSize size = [btn.titleLabel.textsizeWithFont:[UIFontboldSystemFontOfSize:15]constrainedToSize:contentMaxSizes lineBreakMode:UILineBreakModeCharacterWrap]; // textWidth = (int)fontSize.Width; return textWidth; } /** å¼€å¯å€’计时 */ - (void)startCountdown { if (_callTimeout > 100) { return; } _callTimeout = 0; // GCD定时器 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); _countdownTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); dispatch_source_set_timer(_countdownTimer, dispatch_walltime(NULL, 0), 1.0 * NSEC_PER_SEC, 0); //æ¯ç§’执行 dispatch_source_set_event_handler(_countdownTimer, ^{ WEAKSELF_AT if(weakSelf_AT.callTimeout >= 100 ){// è®¡æ—¶ç»“æŸ // å…³é—定时器 dispatch_source_cancel(weakSelf_AT.countdownTimer); dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"è¶…æ—¶"); [weakSelf_AT backAction]; }); }else{// è®¡æ—¶ä¸ weakSelf_AT.callTimeout++; dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf_AT ShowTime:weakSelf_AT.callTimeout]; }); } }); // å¼€å¯å®šæ—¶å™¨ dispatch_resume(_countdownTimer); } #pragma 开锿ˆåŠŸ -(void)setOpenDoorSuccess{ [self setUnlock:NO]; _openDoorTimeout = 0; [self startOpenDoorCountdown]; [self showUIAlertView:unlockSuccessfullyStr]; } -(void)setUnlock:(BOOL)ISEnable{ [_unlockImgBtn 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{ _es = ESVideo.shareInstance.es; //åˆå§‹åŒ–䏿–,进入åŽå°çš„tag _playing = NO; _isSpeaking = NO; self.isInterrupt = NO; isBackGround = NO; [self requestAccessForAVMediaType:AVMediaTypeAudio]; if (isAccessAudio) { ImageCallback snapImageCallback = ^(UIImage *image){ //block是在分线程ä¸è°ƒç”¨çš„ï¼Œè¿™é‡Œè¦æ”¾åˆ°ä¸»çº¿ç¨‹ dispatch_async(dispatch_get_main_queue(), ^{ self->_snapImage = image; [self saveImageToPhotosAlbum:image]; }); }; //闍壿œºä¼šæœ‰è§†é¢‘的长宽高,是固定的(暂时还ä¸ç¡®å®šï¼‰ // _es = [[ESVideoPhone alloc]initESVideoPhoneWithFrame:CGRectMake(0, 57, APP_SCREEN_WIDTH, 211) delegate:self imagecallBack:snapImageCallback]; if (_es) { //判æ–视频渲染是å¦åˆå§‹åŒ–æˆåŠŸï¼Œå¦‚æžœå¤±è´¥ä¼šèµ°ESVideoPhoneDelegate方法 if (_es.showView) { ESVideo.shareInstance.snapImageCallback = snapImageCallback; _es.delegate = self; _es.showView.backgroundColor = [UIColor whiteColor]; [self.centerView addSubview:_es.showView]; _es.showView.hidden = YES; } }else{ NSLog(@"ESVideoPhone åˆå§‹åŒ–失败"); return; } // åˆå§‹åŒ–Audio采集Unit if(![_es initAudioCaptureSession]){ return; } }else{ //音频没有æƒé™å»ºè®®ä¸è¦å‘èµ·é€šè¯ return; } //åˆå§‹åŒ–视频采集Capture // [self requestAccessForAVMediaType:AVMediaTypeVideo]; // if (isAccessVideo) { // if(![_es initVideoCaptureSession]){ // NSLog(@"VideoCaptureSession åˆå§‹åŒ–失败"); // } // } // //åˆå§‹åŒ–AudioSession // _sessionHelper = [[AudioSessionHelper alloc]init]; // [_sessionHelper setAudioSession]; //æ·»åŠ è¿›å…¥åŽå°ï¼Œä¸æ–ç‰é€šçŸ¥ [self addObservers]; } -(void)initData{ _topUILabel.text = _deviceName; _homeUILabel.text = _roomName; [_hangUpTextBtn setTitle:refuseStr forState:UIControlStateNormal]; [_answerTextBtn setTitle:answerStr forState:UIControlStateNormal]; [_collectButton setSelected:_isCollect]; } /** 开始å呼 */ -(void)StartReverseCall{ [self startPlaySystemSound]; if(_es){ NSString *param = [NSString stringWithFormat:@"address=%@,tag=mobile://123,",_mESVideoID]; //NSLog(@"%@", param); [_es onReverseCall:param]; }else{ NSLog(@"ESåˆå§‹åŒ–失败"); } } ////æŽ¥å¬ //-(void)onAccept{ // if(_es){ // [_es onAccept]; // }else{ // NSLog(@"ESåˆå§‹åŒ–失败"); // } // //} -(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]; // UIAlertView *alertView1 = [[UIAlertView alloc] initWithTitle:tipStr message:mes delegate:self cancelButtonTitle:okStr otherButtonTitles:nil, nil]; // [alertView1 show]; } -(void)showUIAlertViewWithBack:(NSString *)mes { 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)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; [self stopPlaySystemSound]; //防æ¢ç”¨æˆ·ä¸æŒ‰æŒ‚æ–,或者ä¸ç‰æ”¶åˆ°å¯¹æ–¹çš„æŒ‚æ–,点击返回按钮。 if(_es){ [_es onHangup]; [_es onStopCapture]; [_es stopTalk]; _es.delegate = nil; ESVideo.shareInstance.snapImageCallback = nil; } // [_es freeSubClass]; } -(void)dealloc{ [[NSNotificationCenter defaultCenter] removeObserver:self]; // [_es freeSubClass]; if(_openDoorTimer){ dispatch_source_cancel(_openDoorTimer); _openDoorTimer = nil; // OK } if(_countdownTimer){ dispatch_source_cancel(_countdownTimer); _countdownTimer = nil; // OK } NSLog(@"==============dealloc"); } #pragma mark ESVideoPhoneDelegate //视频通è¯çš„状æ€ä»£ç†äº‹ä»¶ï¼ŒphoneEvent为返回的消æ¯é‡Œé¢åŒ…å«event状æ€ä¸Žä¸Ževentç›¸å…³çš„æ•°æ® -(void)getPhoneEvent_UI:(NSString *)phoneEvent{ NSLog(@"事件%@", phoneEvent); NSArray *strArray = [phoneEvent componentsSeparatedByString:@"\r\n"]; NSArray *eventArray = [strArray.firstObject componentsSeparatedByString:@"="]; NSString *phoneEventStr = eventArray.lastObject; if([phoneEventStr isEqual:@"EVT_Ringing"]){ _es.showView.hidden = NO; //å呼æˆåŠŸ å…è®¸æŽ¥å¬ çœ‹éœ€æ±‚æ˜¯å¦éœ€è¦æ’放铃声和震动 [self setAnswerBtnEnable:YES]; // [_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"]){ // [_mCallOrAccept setTitle:@"通è¯ä¸..." forState:UIControlStateNormal]; }else if([phoneEventStr isEqual:@"EVT_HangUp"]){ [self showUIAlertViewWithBack:@"已挂æ–"]; // [_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(@"错误%@", 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 startTalk]; } } - (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]; [_es resetAudioCaptureIsSpeak:NO]; }else{ 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(@"耳机拔出"); // if([[_speakerBtn titleForState:UIControlStateNormal] isEqualToString:@"å…æ"]){ // [self speaker:nil]; // }else{ // [self speaker:_speakerBtn]; // } [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]; } #pragma 震动实现貌似和SDKå†²çª ä¸èƒ½å®žçŽ°éœ‡åŠ¨ //å¼€å§‹æ’æ”¾çš„æ—¶å€™è°ƒç”¨ -(void)startPlaySystemSound{ return; // //震动的æç¤ºæ–‡ä»¶å放到资æºç›®å½•下 // NSString *path = [[NSBundle mainBundle] pathForResource:@"ring" ofType:@"wav"]; // AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:path], &sound); //分别注册铃声和震动完åŽçš„回调 AudioServicesAddSystemSoundCompletion(kSystemSoundID_Vibrate, NULL, NULL, vibrationCompleteCallback, NULL); // AudioServicesAddSystemSoundCompletion(sound, NULL, NULL, soundCompleteCallback, NULL); AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);//开始震动 // AudioServicesPlaySystemSound(sound);//å¼€å§‹æ’æ”¾é“ƒå£° } //æ‰‹åŠ¨åœæ¢æ’放的时候调用 - (void)stopPlaySystemSound{ return; NSLog(@"stop PlaySystemSound"); stopRingAndVibration(); } //åœæ¢å“é“ƒå’Œéœ‡åŠ¨ï¼Œç§»é™¤å›žè°ƒå¹¶å¤„ç†æŽ‰é“ƒå£°å’Œéœ‡åŠ¨ void stopRingAndVibration() { AudioServicesRemoveSystemSoundCompletion(kSystemSoundID_Vibrate); // AudioServicesRemoveSystemSoundCompletion(sound); AudioServicesDisposeSystemSoundID(kSystemSoundID_Vibrate); // AudioServicesDisposeSystemSoundID(sound); } //震动完æˆå›žè°ƒï¼Œå› 为震动一下便会调用一次,这里延迟800mså†ç»§ç»éœ‡åŠ¨ï¼Œå’Œå¾®ä¿¡å·®ä¸å¤šï¼Œæ—¶é—´é•¿çŸå¯è‡ªå·±æŽ§åˆ¶ã€‚傿•°soundå³ä¸ºæ³¨å†Œå›žè°ƒæ—¶ä¼ çš„ç¬¬ä¸€ä¸ªå‚æ•° void vibrationCompleteCallback(SystemSoundID sound,void * clientData) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(800 * NSEC_PER_MSEC)), dispatch_get_global_queue(0, 0), ^{ AudioServicesPlaySystemSound(sound); }); } ////é“ƒå£°æ’æ”¾å®Œæˆå›žè°ƒï¼Œè¿™ç§æ–¹æ³•xæ’æ”¾çš„音频é™åˆ¶åœ¨30ç§’å†…ï¼Œæ’æ”¾å®Œç›´æŽ¥å“铃和震动 //void soundCompleteCallback(SystemSoundID sound,void * clientData) { // // stopRingAndVibration(); //} @end