|
|
|
//
|
|
|
|
// JuPhoonCallViewController.m
|
|
|
|
// watch
|
|
|
|
//
|
|
|
|
// Created by Apple on 2019/4/29.
|
|
|
|
// Copyright © 2019年 xTT. All rights reserved.
|
|
|
|
//
|
|
|
|
//ios 4~10
|
|
|
|
#import <CoreTelephony/CTCallCenter.h>
|
|
|
|
#import <CoreTelephony/CTCall.h>
|
|
|
|
|
|
|
|
//ios > 10 remove by lsz 2020-12-22
|
|
|
|
//#import <CallKit/CXCallObserver.h>
|
|
|
|
//#import <CallKit/CXCall.h>
|
|
|
|
|
|
|
|
#import "JuPhoonCallViewController.h"
|
|
|
|
#import "User.h"
|
|
|
|
#import "Device.h"
|
|
|
|
#import "JCManager.h"
|
|
|
|
#import <JLAuthorizationManager.h>
|
|
|
|
#import "AppDelegate.h"
|
|
|
|
|
|
|
|
|
|
|
|
/*CXCallObserverDelegate*/
|
|
|
|
@interface JuPhoonCallViewController ()
|
|
|
|
{
|
|
|
|
AVAudioPlayer *audioPlayer;
|
|
|
|
int wait_duration;
|
|
|
|
NSInteger tempElapsed ;
|
|
|
|
BOOL hangUping;
|
|
|
|
|
|
|
|
|
|
|
|
CTCallCenter *callCenter_old;
|
|
|
|
//CXCallObserver *callObserver;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
控制 挂断 和 接听的 容器
|
|
|
|
*/
|
|
|
|
@property (weak, nonatomic) IBOutlet UIStackView *buttonStackView;
|
|
|
|
/**
|
|
|
|
主动挂断按钮 View
|
|
|
|
*/
|
|
|
|
@property (weak, nonatomic) IBOutlet UIView *activeHangupView;
|
|
|
|
|
|
|
|
/**
|
|
|
|
右侧按钮的 容器 View
|
|
|
|
*/
|
|
|
|
@property (weak, nonatomic) IBOutlet UIView *rightBtnView;
|
|
|
|
|
|
|
|
/// 转换摄像头(视频) 免提 (语音)
|
|
|
|
@property (weak, nonatomic) IBOutlet UILabel *rightBtnDesLabel;
|
|
|
|
|
|
|
|
/// 转换摄像头的图像按钮(视频) 免提的图像按钮 (语音)
|
|
|
|
@property (weak, nonatomic) IBOutlet UIButton *rightBtn;
|
|
|
|
|
|
|
|
/**
|
|
|
|
静音按钮 容器View
|
|
|
|
*/
|
|
|
|
@property (weak, nonatomic) IBOutlet UIView *muteBtnView;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
被动挂断按钮 View
|
|
|
|
*/
|
|
|
|
@property (weak, nonatomic) IBOutlet UIView *hangupView;
|
|
|
|
|
|
|
|
/**
|
|
|
|
接听按钮 View
|
|
|
|
*/
|
|
|
|
@property (weak, nonatomic) IBOutlet UIView *acceptView;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@property (strong, nonatomic) NSTimer *callDurationTimer;
|
|
|
|
|
|
|
|
@property (weak, nonatomic) IBOutlet UILabel *timeLabel;
|
|
|
|
|
|
|
|
/**
|
|
|
|
是否是接通状态
|
|
|
|
*/
|
|
|
|
@property (nonatomic) BOOL isCall;
|
|
|
|
|
|
|
|
@property (weak, nonatomic) IBOutlet UIImageView *headImageView;
|
|
|
|
|
|
|
|
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
|
|
|
|
|
|
|
|
@property (weak, nonatomic) IBOutlet UIView *backView;
|
|
|
|
|
|
|
|
|
|
|
|
/// 是否未打开麦克风
|
|
|
|
@property (nonatomic) BOOL isUNAuthorizationTypeAudio;
|
|
|
|
|
|
|
|
/// 是否未打开相机
|
|
|
|
@property (nonatomic) BOOL isUNAuthorizationTypeCamera;
|
|
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation JuPhoonCallViewController
|
|
|
|
|
|
|
|
-(BOOL)shouldAutorotate{
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)judgeAuthorization{
|
|
|
|
if(self.isUNAuthorizationTypeCamera == YES){
|
|
|
|
[self showAlertAuthorizationTypeCamera];
|
|
|
|
if(self.isReceiveCall){
|
|
|
|
[self activeHangUpBtnAction:nil];
|
|
|
|
}else{
|
|
|
|
[self hangUpButton:nil];
|
|
|
|
}
|
|
|
|
}else if(self.isUNAuthorizationTypeAudio == YES){
|
|
|
|
[self showAlertAuthorizationTypeVideo];
|
|
|
|
if(self.isReceiveCall){
|
|
|
|
[self activeHangUpBtnAction:nil];
|
|
|
|
}else{
|
|
|
|
[self hangUpButton:nil];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
- (void)viewDidLoad {
|
|
|
|
[super viewDidLoad];
|
|
|
|
|
|
|
|
WEAKSELF
|
|
|
|
if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive){
|
|
|
|
//当处于非前台时
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
|
|
|
|
//当从后台变为前台时收到的通知
|
|
|
|
[weakSelf judgeAuthorization];
|
|
|
|
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
|
|
|
JLAuthorizationManager *jlManager = [JLAuthorizationManager defaultManager];
|
|
|
|
[jlManager JL_requestAuthorizationWithAuthorizationType:JLAuthorizationTypeAudio
|
|
|
|
authorizedHandler:nil
|
|
|
|
unAuthorizedHandler:^{
|
|
|
|
weakSelf.isUNAuthorizationTypeAudio = YES;
|
|
|
|
|
|
|
|
}];
|
|
|
|
[jlManager JL_requestAuthorizationWithAuthorizationType:JLAuthorizationTypeVideo
|
|
|
|
authorizedHandler:nil
|
|
|
|
unAuthorizedHandler:^{
|
|
|
|
weakSelf.isUNAuthorizationTypeCamera = YES;
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
// MARK: 处理来电接听挂断
|
|
|
|
if([UIDevice currentDevice].systemVersion.floatValue > 10.0){
|
|
|
|
//callObserver= [CXCallObserver new];
|
|
|
|
//[callObserver setDelegate:self queue:dispatch_get_main_queue()];
|
|
|
|
}else{
|
|
|
|
callCenter_old= [CTCallCenter new];
|
|
|
|
WEAKSELF
|
|
|
|
callCenter_old.callEventHandler = ^(CTCall *call) {
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
if ([call.callState isEqualToString:CTCallStateDialing]) {
|
|
|
|
xLog(@"电话主动拨打电话");
|
|
|
|
} else if ([call.callState isEqualToString:CTCallStateConnected]) {
|
|
|
|
xLog(@"电话接通");
|
|
|
|
[weakSelf activeHangUpBtnAction:nil];
|
|
|
|
} else if ([call.callState isEqualToString:CTCallStateDisconnected]) {
|
|
|
|
xLog(@"电话挂断");
|
|
|
|
|
|
|
|
} else if ([call.callState isEqualToString:CTCallStateIncoming]) {
|
|
|
|
xLog(@"电话被叫");
|
|
|
|
} else {
|
|
|
|
xLog(@"电话其他状态");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[self initUI];
|
|
|
|
|
|
|
|
//订阅状态接收的通知
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateUI:) name:kCallNotification object:nil];
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
-(void)showAlertAuthorizationTypeVideo{
|
|
|
|
|
|
|
|
LGAlertView *alertView = [[LGAlertView alloc] initWithTitle:[NSString stringWithFormat:@"请在iPhone的\"设置-隐私-麦克风\"选项中,允许%@访问你的麦克风",APPName] message:nil style:LGAlertViewStyleAlert buttonTitles:@[@"确定"] cancelButtonTitle:@"" destructiveButtonTitle:nil actionHandler:^(LGAlertView *alertView, NSString *title, NSUInteger index) {
|
|
|
|
|
|
|
|
//[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
|
|
|
|
|
|
|
|
} cancelHandler:^(LGAlertView *alertView) {
|
|
|
|
|
|
|
|
} destructiveHandler:nil];
|
|
|
|
[alertView showAnimated:YES completionHandler:nil];
|
|
|
|
}
|
|
|
|
-(void)showAlertAuthorizationTypeCamera{
|
|
|
|
LGAlertView *alertView = [[LGAlertView alloc] initWithTitle:[NSString stringWithFormat:@"请在iPhone的\"设置-隐私-相机\"选项中,允许%@访问你的相机",APPName] message:nil style:LGAlertViewStyleAlert buttonTitles:@[@"确定"] cancelButtonTitle:@"" destructiveButtonTitle:nil actionHandler:^(LGAlertView *alertView, NSString *title, NSUInteger index) {
|
|
|
|
|
|
|
|
|
|
|
|
} cancelHandler:^(LGAlertView *alertView) {
|
|
|
|
|
|
|
|
} destructiveHandler:nil];
|
|
|
|
[alertView showAnimated:YES completionHandler:nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark ---- CXCallObserverDelegate----
|
|
|
|
//- (void)callObserver:(CXCallObserver *)callObserver callChanged:(CXCall *)call{
|
|
|
|
// NSLog(@"outgoing :%d onHold :%d hasConnected :%d hasEnded :%d",call.outgoing,call.onHold,call.hasConnected,call.hasEnded);
|
|
|
|
/*
|
|
|
|
拨打: outgoing :1 onHold :0 hasConnected :0 hasEnded :0
|
|
|
|
拒绝: outgoing :1 onHold :0 hasConnected :0 hasEnded :1
|
|
|
|
链接: outgoing :1 onHold :0 hasConnected :1 hasEnded :0
|
|
|
|
挂断: outgoing :1 onHold :0 hasConnected :1 hasEnded :1
|
|
|
|
对方未接听时挂断: outgoing :1 onHold :0 hasConnected :0 hasEnded :1
|
|
|
|
|
|
|
|
新来电话: outgoing :0 onHold :0 hasConnected :0 hasEnded :0
|
|
|
|
保留并接听: outgoing :1 onHold :1 hasConnected :1 hasEnded :0
|
|
|
|
另一个挂掉: outgoing :0 onHold :0 hasConnected :1 hasEnded :0
|
|
|
|
保持链接: outgoing :1 onHold :0 hasConnected :1 hasEnded :1
|
|
|
|
对方挂掉: outgoing :0 onHold :0 hasConnected :1 hasEnded :1
|
|
|
|
*/
|
|
|
|
//接通 另一个挂掉
|
|
|
|
//if (!call.outgoing && !call.onHold && call.hasConnected && !call.hasEnded) {
|
|
|
|
// [self activeHangUpBtnAction:nil];
|
|
|
|
//}
|
|
|
|
//}
|
|
|
|
|
|
|
|
- (void)viewWillAppear:(BOOL)animated
|
|
|
|
{
|
|
|
|
[super viewWillAppear:animated];
|
|
|
|
//强制亮屏
|
|
|
|
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
|
|
|
|
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive){
|
|
|
|
[self judgeAuthorization];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)viewWillDisappear:(BOOL)animated
|
|
|
|
{
|
|
|
|
[super viewWillDisappear:animated];
|
|
|
|
//取消强制亮屏
|
|
|
|
[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
|
|
|
|
[self stopRing];
|
|
|
|
[self _stopCallDurationTimer];
|
|
|
|
self.nameLabel.text = nil;
|
|
|
|
self.timeLabel.text = nil;
|
|
|
|
|
|
|
|
//if(callObserver){
|
|
|
|
// [callObserver setDelegate:nil queue:dispatch_get_main_queue()];
|
|
|
|
// callObserver = nil;
|
|
|
|
//}
|
|
|
|
|
|
|
|
if(callCenter_old){
|
|
|
|
[callCenter_old setCallEventHandler:nil];
|
|
|
|
callCenter_old = nil;
|
|
|
|
}
|
|
|
|
// [[JCManager shared].client logout];
|
|
|
|
}
|
|
|
|
|
|
|
|
-(void)initUI{
|
|
|
|
//等待时的图片
|
|
|
|
//判断性别
|
|
|
|
NSString *sexImageName ;
|
|
|
|
if([cUser.cDevice.sex isEqualToString:@"girl"]){
|
|
|
|
//女
|
|
|
|
sexImageName = @"icon_girl_head_portrait";
|
|
|
|
|
|
|
|
}else{
|
|
|
|
//男
|
|
|
|
sexImageName = @"icon_boy_head_portrait";
|
|
|
|
}
|
|
|
|
[self.headImageView sd_setImageWithURL:[NSURL URLWithString:self.device.avator]
|
|
|
|
placeholderImage:[myHelper getImageWithName:sexImageName]
|
|
|
|
options:SDWebImageRetryFailed];
|
|
|
|
self.nameLabel.text = self.device.name;
|
|
|
|
self.timeLabel.hidden = YES;
|
|
|
|
self.statusLabel.hidden = YES;
|
|
|
|
|
|
|
|
NSString * music = @"ring";
|
|
|
|
if(self.isReceiveCall){
|
|
|
|
//呼入
|
|
|
|
music = @"ring";
|
|
|
|
//隐藏 主动挂断按钮
|
|
|
|
self.activeHangupView.hidden = YES;
|
|
|
|
self.hangupView.hidden = NO;
|
|
|
|
self.acceptView.hidden = NO;
|
|
|
|
}else{
|
|
|
|
//呼出
|
|
|
|
music = @"tones";
|
|
|
|
//显示 主动挂断按钮
|
|
|
|
self.activeHangupView.hidden = NO;
|
|
|
|
self.hangupView.hidden = YES;
|
|
|
|
self.acceptView.hidden = YES;
|
|
|
|
}
|
|
|
|
//如果是在后台的情况,不响铃
|
|
|
|
if([UIApplication sharedApplication].applicationState != UIApplicationStateBackground){
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
[self playRing:music];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
self.muteBtnView.hidden = YES;
|
|
|
|
self.rightBtnView.hidden = YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
-(void)updateUI:(NSNotification *)noti{
|
|
|
|
//振铃
|
|
|
|
|
|
|
|
self.timeLabel.hidden = YES;
|
|
|
|
JCCallItem *activeCall = [self getActiveCall];
|
|
|
|
|
|
|
|
if (activeCall.state == JCCallStatePending) {
|
|
|
|
|
|
|
|
} else if (activeCall.state == JCCallStateTalking) {
|
|
|
|
//通话中
|
|
|
|
[self stopRing];
|
|
|
|
[JCManager.shared.mediaDevice startAudio];
|
|
|
|
// xLog(@"--------------------音频输出是否是扬声器 :JCManager.shared.mediaDevice.speakerOn : %d",JCManager.shared.mediaDevice.speakerOn)
|
|
|
|
|
|
|
|
if(!self.callDurationTimer){
|
|
|
|
[self _startCallDurationTimer];
|
|
|
|
}
|
|
|
|
self.timeLabel.hidden = NO;
|
|
|
|
|
|
|
|
|
|
|
|
self.statusLabel.hidden = YES;
|
|
|
|
//显示主动挂断
|
|
|
|
self.activeHangupView.hidden = NO;
|
|
|
|
//隐藏 接听和被动挂断
|
|
|
|
self.hangupView.hidden = YES;
|
|
|
|
self.acceptView.hidden = YES;
|
|
|
|
//显示 静音
|
|
|
|
self.muteBtnView.hidden = NO;
|
|
|
|
|
|
|
|
if (activeCall.video) {
|
|
|
|
self.nameLabel.hidden = YES;
|
|
|
|
self.headImageView.hidden = YES;
|
|
|
|
if (_localCanvas == nil && activeCall.uploadVideoStreamSelf) {
|
|
|
|
[self openLocationCarmeraViewWithFullSScreen:NO]; //小屏
|
|
|
|
//本地 显示View 添加手势
|
|
|
|
[self addGestureRecognizer:_localCanvas.videoView];
|
|
|
|
//为远程View添加手势
|
|
|
|
[self addGestureRecognizer:_remoteCanvas.videoView];
|
|
|
|
|
|
|
|
} else if (_localCanvas != nil && !activeCall.uploadVideoStreamSelf) {
|
|
|
|
[JCManager.shared.mediaDevice stopVideo:_localCanvas];
|
|
|
|
[_localCanvas.videoView removeFromSuperview];
|
|
|
|
_localCanvas = nil;
|
|
|
|
}
|
|
|
|
if (_remoteCanvas == nil && activeCall.uploadVideoStreamOther) {
|
|
|
|
[self openRemoteCarmeraViewWithRenderId:activeCall.renderId isFull:YES];
|
|
|
|
//为远程View添加手势
|
|
|
|
[self addGestureRecognizer:_remoteCanvas.videoView];
|
|
|
|
//本地 显示View 添加手势
|
|
|
|
[self addGestureRecognizer:_localCanvas.videoView];
|
|
|
|
} else if (_remoteCanvas != nil && !activeCall.uploadVideoStreamOther) {
|
|
|
|
[JCManager.shared.mediaDevice stopVideo:_remoteCanvas];
|
|
|
|
[_remoteCanvas.videoView removeFromSuperview];
|
|
|
|
_remoteCanvas = nil;
|
|
|
|
}
|
|
|
|
//视频默认 启用扬声器
|
|
|
|
if(!JCManager.shared.mediaDevice.isSpeakerOn){
|
|
|
|
[JCManager.shared.mediaDevice enableSpeaker:YES];
|
|
|
|
}
|
|
|
|
[self.rightBtn setImage:[UIImage imageNamed:@"Button_Camera"] forState:0];
|
|
|
|
[self.rightBtn setImage:[UIImage imageNamed:@"Button_Camera_active"] forState:UIControlStateSelected];
|
|
|
|
self.rightBtnDesLabel.text = @"转换摄像头";
|
|
|
|
|
|
|
|
}else{
|
|
|
|
self.nameLabel.hidden = NO;
|
|
|
|
self.headImageView.hidden = NO;
|
|
|
|
//音频默认 不启用扬声器
|
|
|
|
[self.rightBtn setImage:[UIImage imageNamed:@"sound"] forState:0];
|
|
|
|
[self.rightBtn setImage:[UIImage imageNamed:@"sound_selected"] forState:UIControlStateSelected];
|
|
|
|
self.rightBtnDesLabel.text = @"免提";
|
|
|
|
|
|
|
|
}
|
|
|
|
//摄像头转换(视频) 语音(免提)
|
|
|
|
self.rightBtnView.hidden = NO;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else if(activeCall.state == JCCallStateOk ||
|
|
|
|
activeCall.state == JCCallStateCancel ||
|
|
|
|
activeCall.state == JCCallStateCanceled){
|
|
|
|
xLog(@"状态改变: %ld",(long)activeCall.state);
|
|
|
|
[UICommon MessageSuccessText:@"通话已结束" isImg:NO];
|
|
|
|
[JCManager.shared.mediaDevice stopAudio];
|
|
|
|
[JCManager.shared.mediaDevice stopCamera];
|
|
|
|
//通话正常结束
|
|
|
|
[self removeCanvas];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
-(void)openLocationCarmeraViewWithFullSScreen:(BOOL)isFull{
|
|
|
|
if(!_localCanvas){
|
|
|
|
xLog(@"JCManager.shared.mediaDevice.camera : %@",JCManager.shared.mediaDevice.camera)
|
|
|
|
_localCanvas = [JCManager.shared.mediaDevice startCameraVideo:JCMediaDeviceRenderFullScreen];
|
|
|
|
if(JCManager.shared.mediaDevice.camera.cameraType != JCMediaDeviceCameraTypeFront){
|
|
|
|
[JCManager.shared.mediaDevice switchCamera];
|
|
|
|
}
|
|
|
|
[self.view insertSubview:_localCanvas.videoView aboveSubview:self.backView];
|
|
|
|
}
|
|
|
|
if(isFull){
|
|
|
|
_localCanvas.videoView.frame = CGRectMake(0,0,ScreenWidth ,ScreenHeight);
|
|
|
|
}else{
|
|
|
|
_localCanvas.videoView.frame = CGRectMake(ScreenWidth*(1-0.25)-25, 50, ScreenWidth * 0.25, ScreenHeight*0.25);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
-(void)openRemoteCarmeraViewWithRenderId:(NSString*)renderId isFull:(BOOL)isFull{
|
|
|
|
if(!_remoteCanvas){
|
|
|
|
_remoteCanvas = [JCManager.shared.mediaDevice startVideo:renderId renderType:JCMediaDeviceRenderFullContent];
|
|
|
|
// [_remoteCanvas rotate:0];
|
|
|
|
[self.view insertSubview:_remoteCanvas.videoView aboveSubview:self.backView];
|
|
|
|
}
|
|
|
|
if(isFull){
|
|
|
|
_remoteCanvas.videoView.frame = CGRectMake(0,0,ScreenWidth ,ScreenHeight);
|
|
|
|
//需要把自己的换成小屏的
|
|
|
|
_localCanvas.videoView.frame = CGRectMake(ScreenWidth*(1-0.25)-25, 50, ScreenWidth * 0.25, ScreenHeight*0.25);
|
|
|
|
}else{
|
|
|
|
_remoteCanvas.videoView.frame = CGRectMake(ScreenWidth*(1-0.25)-25, 50, ScreenWidth * 0.25, ScreenHeight*0.25);
|
|
|
|
_localCanvas.videoView.frame = CGRectMake(0,0,ScreenWidth ,ScreenHeight);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
-(void)removeCanvas
|
|
|
|
{
|
|
|
|
if (_localCanvas) {
|
|
|
|
[JCManager.shared.mediaDevice stopVideo:_localCanvas];
|
|
|
|
[_localCanvas.videoView removeFromSuperview];
|
|
|
|
_localCanvas = nil;
|
|
|
|
}
|
|
|
|
if (_remoteCanvas) {
|
|
|
|
[JCManager.shared.mediaDevice stopVideo:_remoteCanvas];
|
|
|
|
[_remoteCanvas.videoView removeFromSuperview];
|
|
|
|
_remoteCanvas = nil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//MARK: 为View 添加拖动和双击手势
|
|
|
|
-(void)addGestureRecognizer:(UIView*)view{
|
|
|
|
//添加拖动手势
|
|
|
|
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc]
|
|
|
|
initWithTarget:self
|
|
|
|
action:@selector(handlePan:)];
|
|
|
|
[view addGestureRecognizer:panGestureRecognizer];
|
|
|
|
//双击手势
|
|
|
|
UITapGestureRecognizer *doubleTapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleDoubleTap:)];
|
|
|
|
doubleTapGesture.numberOfTapsRequired =2;
|
|
|
|
doubleTapGesture.numberOfTouchesRequired =1;
|
|
|
|
[view addGestureRecognizer:doubleTapGesture];
|
|
|
|
}
|
|
|
|
|
|
|
|
//MARK: --- 拖动手势 ----
|
|
|
|
- (void)handlePan:(UIPanGestureRecognizer*)recognizer{
|
|
|
|
UIView *selectView = recognizer.view;
|
|
|
|
if(selectView.bounds.size.width != ScreenWidth){ //不是全屏状态
|
|
|
|
// Figure out where the user is trying to drag the view.
|
|
|
|
CGPoint translation = [recognizer translationInView:self.view];
|
|
|
|
CGPoint newCenter = CGPointMake(recognizer.view.center.x+ translation.x,
|
|
|
|
recognizer.view.center.y + translation.y);// 限制屏幕范围:
|
|
|
|
newCenter.y = MAX(recognizer.view.frame.size.height/2, newCenter.y);
|
|
|
|
newCenter.y = MIN(self.view.frame.size.height - recognizer.view.frame.size.height/2, newCenter.y);
|
|
|
|
newCenter.x = MAX(recognizer.view.frame.size.width/2, newCenter.x);
|
|
|
|
newCenter.x = MIN(self.view.frame.size.width - recognizer.view.frame.size.width/2,newCenter.x);
|
|
|
|
recognizer.view.center = newCenter;
|
|
|
|
[recognizer setTranslation:CGPointZero inView:self.view];
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
//MARK: --- 双击放大----
|
|
|
|
-(void)handleDoubleTap:(UIGestureRecognizer *)recognizer{
|
|
|
|
UIView *selectView = recognizer.view;
|
|
|
|
CGRect tempRect = selectView.frame;
|
|
|
|
|
|
|
|
if(selectView.bounds.size.width != ScreenWidth){
|
|
|
|
if([_localCanvas.videoView isEqual:selectView]){
|
|
|
|
_localCanvas.videoView.frame = CGRectMake(0, 0, ScreenWidth, ScreenHeight);
|
|
|
|
_remoteCanvas.videoView.frame = tempRect;
|
|
|
|
[self.view exchangeSubviewAtIndex:_remoteCanvas.videoView.getInSuperViewIndex withSubviewAtIndex:_localCanvas.videoView.getInSuperViewIndex];
|
|
|
|
}else{
|
|
|
|
_remoteCanvas.videoView.frame = CGRectMake(0, 0, ScreenWidth, ScreenHeight);
|
|
|
|
_localCanvas.videoView.frame = tempRect;
|
|
|
|
[self.view exchangeSubviewAtIndex:_localCanvas.videoView.getInSuperViewIndex withSubviewAtIndex:_remoteCanvas.videoView.getInSuperViewIndex];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
MARK: APP 主动挂断按钮
|
|
|
|
|
|
|
|
*/
|
|
|
|
- (IBAction)activeHangUpBtnAction:(id)sender {
|
|
|
|
[self stopRing];
|
|
|
|
[JCManager.shared.call term:[self getActiveCall] reason:JCCallReasonNone description:@"APP挂断"];
|
|
|
|
[JCManager.shared _stopCallTimeoutTimer];
|
|
|
|
[JCManager.shared _stopVideoLimitTimeoutTimer];
|
|
|
|
[JCManager.shared.mediaDevice stopVideo:_localCanvas];
|
|
|
|
[JCManager.shared.mediaDevice stopVideo:_remoteCanvas];
|
|
|
|
JCManager.shared.callViewController = nil;
|
|
|
|
[self dismissViewControllerAnimated:YES completion:nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
MARK: APP 被动挂断按钮
|
|
|
|
|
|
|
|
*/
|
|
|
|
- (IBAction)hangUpButton:(UIButton *)sender {
|
|
|
|
[self stopRing];
|
|
|
|
[JCManager.shared.call term:[self getActiveCall] reason:JCCallReasonNone description:@"APP挂断"];
|
|
|
|
[JCManager.shared _stopCallTimeoutTimer];
|
|
|
|
[JCManager.shared _stopVideoLimitTimeoutTimer];
|
|
|
|
[JCManager.shared.mediaDevice stopVideo:_localCanvas];
|
|
|
|
JCManager.shared.callViewController = nil;
|
|
|
|
[self dismissViewControllerAnimated:YES completion:nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
MARK: APP 接听按钮
|
|
|
|
*/
|
|
|
|
- (IBAction)acceptBtnAction:(id)sender {
|
|
|
|
|
|
|
|
[self stopRing];
|
|
|
|
[[JCManager shared].call answer:[self getActiveCall] video:true];
|
|
|
|
}
|
|
|
|
|
|
|
|
//MARK: 切换摄像头 / 切换免提
|
|
|
|
- (IBAction)didClickSwitchCameraButton:(UIButton *)sender {
|
|
|
|
sender.selected = !sender.selected;
|
|
|
|
if ([self.rightBtnDesLabel.text isEqualToString:@"免提"]) {
|
|
|
|
// 切换免提
|
|
|
|
[JCManager.shared.mediaDevice enableSpeaker:sender.selected];
|
|
|
|
}else{
|
|
|
|
// 切换摄像头
|
|
|
|
[JCManager.shared.mediaDevice switchCamera];
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//MARK: 静音
|
|
|
|
- (IBAction)didClickMuteButton:(UIButton *)sender {
|
|
|
|
sender.selected = !sender.selected;
|
|
|
|
//[JCManager.shared.call mute:[self getActiveCall]];
|
|
|
|
[JCManager.shared.call muteMicrophone:[self getActiveCall] mute:sender.selected];
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - 工具函数
|
|
|
|
|
|
|
|
-(JCCallItem*)getActiveCall
|
|
|
|
{
|
|
|
|
for (JCCallItem* item in JCManager.shared.call.callItems) {
|
|
|
|
if (item.active) {
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *)genCallInfo:(JCCallItem*)item {
|
|
|
|
switch (item.state) {
|
|
|
|
case JCCallStateInit:
|
|
|
|
return @"呼叫中";
|
|
|
|
case JCCallStatePending:
|
|
|
|
return @"振铃中";
|
|
|
|
case JCCallStateConnecting:
|
|
|
|
return @"连接中";
|
|
|
|
case JCCallStateTalking:
|
|
|
|
if (item.hold) {
|
|
|
|
return @"挂起";
|
|
|
|
} else if (item.held) {
|
|
|
|
return @"被挂起";
|
|
|
|
} else {
|
|
|
|
return [self formatTalkingTime:((long)[[NSDate date] timeIntervalSince1970] - item.talkingBeginTime)];
|
|
|
|
}
|
|
|
|
case JCCallStateOk:
|
|
|
|
return @"通话结束";
|
|
|
|
case JCCallStateCancel:
|
|
|
|
return @"通话结束";
|
|
|
|
case JCCallStateCanceled:
|
|
|
|
return @"挂断";
|
|
|
|
case JCCallStateMissed:
|
|
|
|
return @"未接";
|
|
|
|
default:
|
|
|
|
return @"异常";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//- (NSString *)genNetStatus:(JCCallItem *)item {
|
|
|
|
// if (item.state != JCCallStateTalking) {
|
|
|
|
// return @"";
|
|
|
|
// }
|
|
|
|
// switch (item.netStatus) {
|
|
|
|
// case JCCallNetWorkDisconnected:
|
|
|
|
// return @"无网络";
|
|
|
|
// case JCCallNetWorkVeryBad:
|
|
|
|
// return @"很差";
|
|
|
|
// case JCCallNetWorkBad:
|
|
|
|
// return @"差";
|
|
|
|
// case JCCallNetWorkNormal:
|
|
|
|
// return @"一般";
|
|
|
|
// case JCCallNetWorkGood:
|
|
|
|
// return @"好";
|
|
|
|
// case JCCallNetWorkVeryGood:
|
|
|
|
// return @"非常好";
|
|
|
|
// default:
|
|
|
|
// return @"";
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
//MARK: 响铃的 MP3
|
|
|
|
- (void)playRing:(NSString *)name {
|
|
|
|
[self stopRing];
|
|
|
|
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
|
|
|
|
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
|
|
|
|
[audioSession setActive:YES error:nil];
|
|
|
|
|
|
|
|
NSURL *path = [[NSBundle mainBundle] URLForResource:name withExtension:@"mp3"];
|
|
|
|
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:path error:nil];
|
|
|
|
audioPlayer.numberOfLoops = -1;
|
|
|
|
[audioPlayer play];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)stopRing {
|
|
|
|
if (audioPlayer) {
|
|
|
|
[audioPlayer stop];
|
|
|
|
audioPlayer = nil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Timer
|
|
|
|
|
|
|
|
- (void)_updateCallDuration
|
|
|
|
{
|
|
|
|
JCCallItem *item = [self getActiveCall];
|
|
|
|
if(item){
|
|
|
|
self.callDuration = [[NSDate date] timeIntervalSince1970] - item.talkingBeginTime;
|
|
|
|
self.timeLabel.text = [self formatTalkingTime:((long)[[NSDate date] timeIntervalSince1970] - item.talkingBeginTime)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
- (NSString *)formatTalkingTime:(long)time
|
|
|
|
{
|
|
|
|
return [NSString stringWithFormat:@"%02ld:%02ld", time/60, time%60];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)_startCallDurationTimer
|
|
|
|
{
|
|
|
|
[self _stopCallDurationTimer];
|
|
|
|
|
|
|
|
self.callDuration = 0;
|
|
|
|
self.callDurationTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(_updateCallDuration) userInfo:nil repeats:YES];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)_stopCallDurationTimer
|
|
|
|
{
|
|
|
|
if (self.callDurationTimer) {
|
|
|
|
[self.callDurationTimer invalidate];
|
|
|
|
self.callDurationTimer = nil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|