You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
801 lines
28 KiB
801 lines
28 KiB
![]()
2 years ago
|
//
|
||
|
// CallViewController.m
|
||
|
// OpenDuo
|
||
|
//
|
||
|
// Created by suleyu on 2017/10/31.
|
||
|
// Copyright © 2017 Agora. All rights reserved.
|
||
|
//
|
||
|
|
||
|
|
||
|
|
||
|
//ios > 10
|
||
|
//#import <CallKit/CXCallObserver.h>
|
||
|
//#import <CallKit/CXCall.h>
|
||
|
|
||
|
#import "CallViewController.h"
|
||
|
#import <JLAuthorizationManager.h>
|
||
|
#import <AVFoundation/AVFoundation.h>
|
||
|
#import <AgoraRtcKit/AgoraRtcEngineKit.h>
|
||
|
#import "MJExtension.h"
|
||
|
#import "AppDelegate.h"
|
||
|
|
||
|
//CXCallObserverDelegate
|
||
|
@interface CallViewController ()<AgoraRtcEngineDelegate>
|
||
|
{
|
||
|
AVAudioPlayer *audioPlayer;
|
||
|
AgoraRtcEngineKit *mediaEngine;
|
||
|
int wait_duration;
|
||
|
NSInteger tempElapsed ;
|
||
|
BOOL hangUping;
|
||
|
|
||
|
//CXCallObserver *callObserver;
|
||
|
}
|
||
|
|
||
|
@property (strong, nonatomic) LGAlertView *alertView;
|
||
|
@property (weak, nonatomic) IBOutlet UIView *remoteVideo;
|
||
|
@property (weak, nonatomic) IBOutlet UIView *localVideo;
|
||
|
|
||
|
/**
|
||
|
控制 挂断 和 接听的 容器
|
||
|
*/
|
||
|
@property (weak, nonatomic) IBOutlet UIStackView *buttonStackView;
|
||
|
/**
|
||
|
主动挂断按钮 View
|
||
|
*/
|
||
|
@property (weak, nonatomic) IBOutlet UIView *activeHangupView;
|
||
|
|
||
|
/**
|
||
|
摄像头切换 容器 View
|
||
|
*/
|
||
|
@property (weak, nonatomic) IBOutlet UIView *switchCameraView;
|
||
|
/**
|
||
|
静音按钮 容器View
|
||
|
*/
|
||
|
@property (weak, nonatomic) IBOutlet UIView *muteBtnView;
|
||
|
|
||
|
|
||
|
/**
|
||
|
被动挂断按钮 View
|
||
|
*/
|
||
|
@property (weak, nonatomic) IBOutlet UIView *hangupView;
|
||
|
|
||
|
/**
|
||
|
接听按钮 View
|
||
|
*/
|
||
|
@property (weak, nonatomic) IBOutlet UIView *acceptView;
|
||
|
|
||
|
|
||
|
@property (strong, nonatomic) AgoraRtcEngineKit *agoraKit;
|
||
|
@property (nonatomic) int timeLength;
|
||
|
@property (strong, nonatomic) NSTimer *timeTimer;
|
||
|
@property (weak, nonatomic) IBOutlet UILabel *timeLabel;
|
||
|
|
||
|
/**
|
||
|
是否是接通状态
|
||
|
*/
|
||
|
@property (nonatomic) BOOL isCall;
|
||
|
|
||
|
@property (weak, nonatomic) IBOutlet UIImageView *headImageView;
|
||
|
|
||
|
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
|
||
|
|
||
|
|
||
|
@end
|
||
|
|
||
|
@implementation CallViewController
|
||
|
|
||
|
- (void)viewDidLoad
|
||
|
{
|
||
|
[super viewDidLoad];
|
||
|
kWeakSelf(self)
|
||
|
//添加通知
|
||
|
[[NSNotificationCenter defaultCenter] addObserverForName:AccountMessageNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
|
||
|
NSDictionary *dic = note.object;
|
||
|
NSDictionary *msgDic = dic[@"message"];
|
||
|
NSString * msgType = msgDic[@"type"];
|
||
|
if([msgType isEqualToString:@"reject"]){
|
||
|
//拒绝视频通话
|
||
|
[weakself activeHangUpBtnAction:nil];
|
||
|
}else{
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
}];
|
||
|
self.remoteVideo.frame = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||
|
/// 初始化声网
|
||
|
[self initializeAgoraEngine];
|
||
|
self.headImageView.layer.cornerRadius = 4;
|
||
|
self.headImageView.layer.masksToBounds = YES;
|
||
|
//判断性别
|
||
|
NSString *sexImageName = APIManager.sharedManager.deviceModel.sex == 2 ? @"icon_girl_head_portrait" : @"icon_boy_head_portrait";
|
||
|
[self.headImageView sd_setImageWithURL:[NSURL URLWithString:APIManager.sharedManager.deviceModel.image]
|
||
|
placeholderImage:ImageName_(sexImageName)
|
||
|
options:SDWebImageRetryFailed];
|
||
|
self.nameLabel.text = APIManager.sharedManager.deviceModel.name;
|
||
|
|
||
|
//设置视频 分辨率等设置
|
||
|
// [self setupVideo];
|
||
|
//设置 本地视频摄像头
|
||
|
// [self setupLocalVideo];
|
||
|
|
||
|
//MARK: 时间默认 不显示 接通后才显示
|
||
|
self.timeLabel.hidden = YES;
|
||
|
|
||
|
JLAuthorizationManager *jlManager = [JLAuthorizationManager defaultManager];
|
||
|
[jlManager JL_requestAuthorizationWithAuthorizationType:JLAuthorizationTypeMicrophone
|
||
|
authorizedHandler:nil
|
||
|
unAuthorizedHandler:^{
|
||
|
EasyAlertView *alertV = [EasyAlertView alertViewWithTitle:GJText(@"请为智能守护5打开麦克风权限") subtitle:nil AlertViewType:AlertViewTypeSystemAlert config:nil];
|
||
|
[alertV addAlertItem:^EasyAlertItem *{
|
||
|
return [EasyAlertItem itemWithTitle:GJText(@"取消") type:AlertItemTypeSystemCancel callback:^(EasyAlertView *showview, long index) {
|
||
|
if(weakself.isReceiveCall){
|
||
|
[weakself activeHangUpBtnAction:nil];
|
||
|
}else{
|
||
|
[weakself hangUpButton:nil];
|
||
|
}
|
||
|
}];
|
||
|
}];
|
||
|
[alertV addAlertItem:^EasyAlertItem *{
|
||
|
return [EasyAlertItem itemWithTitle:GJText(@"确定") type:AlertItemTypeSystemDefault callback:^(EasyAlertView *showview, long index) {
|
||
|
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
|
||
|
}];
|
||
|
}];
|
||
|
[alertV showAlertView];
|
||
|
}];
|
||
|
|
||
|
// MARK: 处理来电接听挂断
|
||
|
if([UIDevice currentDevice].systemVersion.floatValue > 10.0){
|
||
|
//callObserver= [CXCallObserver new];
|
||
|
//[callObserver setDelegate:self queue:dispatch_get_main_queue()];
|
||
|
}
|
||
|
|
||
|
self.jietingLabel.text = GJText(@"接听");
|
||
|
self.guanduanLabel.text = GJText(@"挂断");
|
||
|
self.guanduanLabel1.text = GJText(@"挂断");
|
||
|
self.jingyinLabel.text = GJText(@"静音");
|
||
|
self.qiehuanLabel.text = GJText(@"转换摄像头");
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
- (void)initializeAgoraEngine
|
||
|
{
|
||
|
NSLog(@"声网 SDK 版本 %@",[AgoraRtcEngineKit getSdkVersion]);
|
||
|
AgoraRtcEngineConfig *config = [AgoraRtcEngineConfig new];
|
||
|
config.appId = self.appid;
|
||
|
config.areaCode = AgoraAreaCodeTypeCN;
|
||
|
config.channelProfile = AgoraChannelProfileLiveBroadcasting;
|
||
|
|
||
|
self.agoraKit = [AgoraRtcEngineKit sharedEngineWithConfig:config delegate:self];
|
||
|
//[self.agoraKit setChannelProfile:AgoraChannelProfileLiveBroadcasting];
|
||
|
[self.agoraKit setClientRole:AgoraClientRoleBroadcaster];
|
||
|
[self.agoraKit enableVideo];
|
||
|
//[self.agoraKit setLogFile:@"agorasdk"];
|
||
|
|
||
|
/// 设置 视频分辨率
|
||
|
[self setupVideo];
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
设置 视频分辨率
|
||
|
*/
|
||
|
- (void)setupVideo
|
||
|
{
|
||
|
// Default mode is disableVideo
|
||
|
|
||
|
|
||
|
[self.agoraKit setParameters:@"{\"engine.video.codec_type\":\"20\"}"];
|
||
|
[self.agoraKit setParameters:@"{\"rtc.audio.acm_ptime\":60}"];
|
||
|
[self.agoraKit setParameters:@"{\"rtc.audio.custom_payload_type\":9}"];
|
||
|
|
||
|
if(self.videoSize.width == 160 && self.videoSize.height == 128){
|
||
|
self.videoSize = CGSizeMake(160, 128);
|
||
|
|
||
|
AgoraVideoEncoderConfiguration *encoderConfiguration =
|
||
|
[[AgoraVideoEncoderConfiguration alloc] initWithSize:self.videoSize
|
||
|
frameRate:AgoraVideoFrameRateFps7
|
||
|
bitrate:AgoraVideoBitrateStandard
|
||
|
orientationMode:AgoraVideoOutputOrientationModeFixedPortrait
|
||
|
mirrorMode:AgoraVideoMirrorModeAuto];
|
||
|
encoderConfiguration.dimensions = self.videoSize;
|
||
|
[self.agoraKit setVideoEncoderConfiguration:encoderConfiguration];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
self.videoSize = AgoraVideoDimension240x240;
|
||
|
|
||
|
AgoraVideoEncoderConfiguration *encoderConfiguration =
|
||
|
[[AgoraVideoEncoderConfiguration alloc] initWithSize:self.videoSize
|
||
|
frameRate:AgoraVideoFrameRateFps7
|
||
|
bitrate:AgoraVideoBitrateStandard
|
||
|
orientationMode:AgoraVideoOutputOrientationModeFixedPortrait
|
||
|
mirrorMode:AgoraVideoMirrorModeAuto];
|
||
|
encoderConfiguration.dimensions = AgoraVideoDimension240x240;
|
||
|
[self.agoraKit setVideoEncoderConfiguration:encoderConfiguration];
|
||
|
}
|
||
|
|
||
|
|
||
|
// if(self.videoSize.width == 0 && self.videoSize.height == 0){
|
||
|
// self.videoSize = AgoraVideoDimension240x240;
|
||
|
// }
|
||
|
//
|
||
|
// //[self.agoraKit setParameters:@"{\"rtc.audio.acm_ptime\":60}"];
|
||
|
// [self.agoraKit setParameters:@"{\"engine.video.codec_type\":\"20\"}"];
|
||
|
// [self.agoraKit setParameters:@"{\"rtc.audio.custom_payload_type\":9}"];
|
||
|
//
|
||
|
// AgoraVideoEncoderConfiguration *encoderConfiguration =
|
||
|
// [[AgoraVideoEncoderConfiguration alloc] initWithSize:self.videoSize
|
||
|
// frameRate:AgoraVideoFrameRateFps7
|
||
|
// bitrate:AgoraVideoBitrateStandard
|
||
|
// orientationMode:AgoraVideoOutputOrientationModeAdaptative
|
||
|
// mirrorMode:AgoraVideoMirrorModeAuto];
|
||
|
// encoderConfiguration.dimensions = AgoraVideoDimension240x240;
|
||
|
// [self.agoraKit setVideoEncoderConfiguration:encoderConfiguration];
|
||
|
|
||
|
[self setupLocalVideo];
|
||
|
|
||
|
//添加拖动手势
|
||
|
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc]
|
||
|
initWithTarget:self
|
||
|
action:@selector(handlePan:)];
|
||
|
[self.remoteVideo addGestureRecognizer:panGestureRecognizer];
|
||
|
//双击手势
|
||
|
UITapGestureRecognizer *doubleTapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleDoubleTap:)];
|
||
|
doubleTapGesture.numberOfTapsRequired =2;
|
||
|
doubleTapGesture.numberOfTouchesRequired =1;
|
||
|
[self.remoteVideo addGestureRecognizer:doubleTapGesture];
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
初始化自己的 视频界面
|
||
|
*/
|
||
|
- (void)setupLocalVideo
|
||
|
{
|
||
|
self.localVideo.frame = CGRectMake(SCREEN_WIDTH*(1-0.25)-25, 50, SCREEN_WIDTH * 0.25, SCREEN_HEIGHT*0.25);
|
||
|
|
||
|
AgoraRtcVideoCanvas *videoCanvas = [[AgoraRtcVideoCanvas alloc] init];
|
||
|
videoCanvas.uid = self.uid;
|
||
|
videoCanvas.view = self.localVideo;
|
||
|
videoCanvas.renderMode = AgoraVideoRenderModeHidden;
|
||
|
[self.agoraKit setupLocalVideo:videoCanvas];
|
||
|
[self.agoraKit startPreview];
|
||
|
[self.agoraKit setDefaultAudioRouteToSpeakerphone:YES];
|
||
|
//MARK: 设置录音的音量是原本的4倍
|
||
|
[self.agoraKit adjustRecordingSignalVolume:400];
|
||
|
self.localVideo.hidden = YES;
|
||
|
|
||
|
//添加拖动手势
|
||
|
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc]
|
||
|
initWithTarget:self
|
||
|
action:@selector(handlePan:)];
|
||
|
[self.localVideo addGestureRecognizer:panGestureRecognizer];
|
||
|
//双击手势
|
||
|
UITapGestureRecognizer *doubleTapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleDoubleTap:)];
|
||
|
doubleTapGesture.numberOfTapsRequired =2;
|
||
|
doubleTapGesture.numberOfTouchesRequired =1;
|
||
|
[self.localVideo addGestureRecognizer:doubleTapGesture];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
MARK:加入通道
|
||
|
*/
|
||
|
- (void)joinChannel
|
||
|
{
|
||
|
if(self.channelID && self.uid )
|
||
|
{
|
||
|
WeakSelf
|
||
|
AgoraRtcChannelMediaOptions *option = [AgoraRtcChannelMediaOptions new];
|
||
|
[option setPublishCameraTrack:[AgoraRtcBoolOptional of:YES]];
|
||
|
[option setClientRoleType:[AgoraRtcIntOptional of:YES]];
|
||
|
|
||
|
int res = [self.agoraKit joinChannelByToken:self.token channelId:self.channelID uid:self.uid mediaOptions:option joinSuccess:^(NSString * _Nonnull channel, NSUInteger uid, NSInteger elapsed) {
|
||
|
NSLog(@"加入通道");
|
||
|
//启动定时器
|
||
|
[weakSelf _startTimeTimer];
|
||
|
self.agoraKit.delegate = self;
|
||
|
|
||
|
}];
|
||
|
NSLog(@"加入通道res == %d" , res);
|
||
|
//音频外放
|
||
|
[self.agoraKit setEnableSpeakerphone:YES];
|
||
|
//启用不自动锁屏
|
||
|
[UIApplication sharedApplication].idleTimerDisabled = YES;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
MARK: APP 接听按钮
|
||
|
*/
|
||
|
- (IBAction)acceptBtnAction:(id)sender {
|
||
|
self.isCall = YES;
|
||
|
[self joinChannel];
|
||
|
[self stopRing];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
MARK: APP 主动挂断按钮 (接通后APP的挂断)
|
||
|
|
||
|
*/
|
||
|
- (IBAction)activeHangUpBtnAction:(id)sender {
|
||
|
[self stopRing];
|
||
|
[self leaveChannel];
|
||
|
if(!hangUping){
|
||
|
kWeakSelf(self)
|
||
|
if(sender){
|
||
|
//调 API 接口 下发指令给设备 上传 video_id
|
||
|
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
|
||
|
[parameters setValue:APIManager.sharedManager.deviceModel.imei forKey:@"imei"];
|
||
|
[parameters setValue:self.video_id forKey:@"videoId"];
|
||
|
[[[APIManager sharedManager] APGET:DeleteCall_URL parameters:parameters resultClass:nil] subscribeNext:^(id _Nullable x) {
|
||
|
[UICommon HidenLoading];
|
||
|
NSLog(@"主动挂断成功");
|
||
|
self->hangUping = NO;
|
||
|
[weakself dismissViewControllerAnimated:YES completion:nil];
|
||
|
} error:^(NSError * _Nullable error) {
|
||
|
NSDictionary *dic = error.userInfo;
|
||
|
[UICommon MessageErrorText:dic[NSLocalizedDescriptionKey]];
|
||
|
NSLog(@"主动挂断失败");
|
||
|
self->hangUping = NO;
|
||
|
[weakself dismissViewControllerAnimated:YES completion:nil];
|
||
|
}];
|
||
|
|
||
|
}else{
|
||
|
if(self.isCall){
|
||
|
return;
|
||
|
}
|
||
|
//MARK: 收到设备主动挂断 后的 推送的 动作
|
||
|
[UICommon MessageErrorText:F(@"%@ %@", APIManager.sharedManager.deviceModel.name,GJText(@"拒绝了你的通话请求"))];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
MARK: APP 被动挂断按钮 (接通前APP的挂断)
|
||
|
|
||
|
*/
|
||
|
- (IBAction)hangUpButton:(UIButton *)sender {
|
||
|
[self stopRing];
|
||
|
[self leaveChannel];
|
||
|
if(!hangUping){
|
||
|
hangUping = YES;
|
||
|
kWeakSelf(self)
|
||
|
//调 API 接口 下发指令给设备 上传 video_id
|
||
|
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
|
||
|
[parameters setValue:APIManager.sharedManager.deviceModel.imei forKey:@"imei"];
|
||
|
[parameters setValue:self.video_id forKey:@"videoId"];
|
||
|
[[[APIManager sharedManager] APGET:DeleteCall_URL parameters:parameters resultClass:nil] subscribeNext:^(id _Nullable x) {
|
||
|
[UICommon HidenLoading];
|
||
|
NSLog(@"主动挂断成功");
|
||
|
self->hangUping = NO;
|
||
|
[weakself dismissViewControllerAnimated:YES completion:nil];
|
||
|
} error:^(NSError * _Nullable error) {
|
||
|
NSDictionary *dic = error.userInfo;
|
||
|
[UICommon MessageErrorText:dic[NSLocalizedDescriptionKey]];
|
||
|
NSLog(@"主动挂断失败");
|
||
|
self->hangUping = NO;
|
||
|
}];
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
MARK: 离开通道
|
||
|
*/
|
||
|
- (void)leaveChannel
|
||
|
{
|
||
|
NSLog(@"调用离开通道接口");
|
||
|
|
||
|
if(self.alertView){
|
||
|
[self.alertView dismissAnimated:YES completionHandler:nil];
|
||
|
}
|
||
|
kWeakSelf(self)
|
||
|
[self.agoraKit leaveChannel:^(AgoraChannelStats *stat) {
|
||
|
|
||
|
//取消不自动锁屏
|
||
|
[UIApplication sharedApplication].idleTimerDisabled = NO;
|
||
|
[weakself.remoteVideo removeFromSuperview];
|
||
|
[weakself.localVideo removeFromSuperview];
|
||
|
//停止定时器
|
||
|
[weakself _stopTimeTimer];
|
||
|
|
||
|
if(weakself.isCall){
|
||
|
//上传视频时间
|
||
|
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
|
||
|
long tempTime = stat.duration-self->wait_duration;
|
||
|
if(stat.duration - self->wait_duration < 0){
|
||
|
tempTime = 0;
|
||
|
}
|
||
|
|
||
|
NSMutableDictionary *dics = [NSMutableDictionary dictionary];
|
||
|
[dics setValue:@(tempTime) forKey:@"duration"];
|
||
|
[dics setValue:@(0) forKey:@"waitDuration"];
|
||
|
[dics setValue:APIManager.sharedManager.deviceModel.imei forKey:@"imei"];
|
||
|
[dics setValue:self.video_id forKey:@"videoId"];
|
||
|
|
||
|
[[[APIManager sharedManager] APPOST:VideoRecord_URL parameters:dics isJson:YES resultClass:nil] subscribeNext:^(id _Nullable x) {
|
||
|
[UICommon HidenLoading];
|
||
|
NSLog(@"上传视频时间成功");
|
||
|
//MARK: 上传完视频时间后删除存储的 Key
|
||
|
[UserDefaults removeObjectForKey:VideoTimeAndIDAndWHRecordKey];
|
||
|
} error:^(NSError * _Nullable error) {
|
||
|
NSDictionary *dic = error.userInfo;
|
||
|
[UICommon MessageErrorText:dic[NSLocalizedDescriptionKey]];
|
||
|
}];
|
||
|
}
|
||
|
|
||
|
[weakself dismissViewControllerAnimated:YES completion:^{
|
||
|
|
||
|
}];
|
||
|
|
||
|
}];
|
||
|
}
|
||
|
|
||
|
//MARK: 静音
|
||
|
- (IBAction)didClickMuteButton:(UIButton *)sender {
|
||
|
sender.selected = !sender.selected;
|
||
|
[self.agoraKit muteLocalAudioStream:sender.selected];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
用户在 视频通话 和 语音通话间切换 (暂时不用)
|
||
|
*/
|
||
|
- (IBAction)didClickVideoMuteButton:(UIButton *)sender {
|
||
|
sender.selected = !sender.selected;
|
||
|
[self.agoraKit muteLocalVideoStream:sender.selected];
|
||
|
self.localVideo.hidden = sender.selected;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//MARK: 切换摄像头
|
||
|
- (IBAction)didClickSwitchCameraButton:(UIButton *)sender {
|
||
|
sender.selected = !sender.selected;
|
||
|
[self.agoraKit switchCamera];
|
||
|
}
|
||
|
|
||
|
|
||
|
#pragma mark AgoraRtcEngineDelegate
|
||
|
/// 发生错误回调
|
||
|
- (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine didOccurError:(AgoraErrorCode)errorCode{
|
||
|
NSLog(@"===发生错误回调 errorCode:%ld",errorCode);
|
||
|
}
|
||
|
|
||
|
/// Token 服务即将过期回调
|
||
|
- (void)rtcEngine:(AgoraRtcEngineKit *)engine tokenPrivilegeWillExpire:(NSString *)token
|
||
|
{
|
||
|
NSLog(@"Token 服务即将过期回调 token:%@",token);
|
||
|
}
|
||
|
|
||
|
/// Token 过期回调
|
||
|
-(void)rtcEngineRequestToken:(AgoraRtcEngineKit *)engine
|
||
|
{
|
||
|
NSLog(@"Token 过期回调");
|
||
|
}
|
||
|
|
||
|
- (void)rtcEngine:(AgoraRtcEngineKit *)engine didJoinedOfUid:(NSUInteger)uid elapsed:(NSInteger)elapsed
|
||
|
{
|
||
|
NSLog(@"\n\n\n\n远端用户加入频道\n\n\n\n\n");
|
||
|
[self stopRing];
|
||
|
if(self.isCall == NO){
|
||
|
//MARK: 赋值等待时间
|
||
|
wait_duration = self.timeLength;
|
||
|
self.timeLength = 0;
|
||
|
[self _stopTimeTimer];
|
||
|
[self _startTimeTimer];
|
||
|
}
|
||
|
self.isCall = YES;
|
||
|
|
||
|
if (self.remoteVideo.hidden)
|
||
|
{
|
||
|
self.remoteVideo.hidden = NO;
|
||
|
}
|
||
|
|
||
|
AgoraRtcVideoCanvas *videoCanvas = [[AgoraRtcVideoCanvas alloc] init];
|
||
|
videoCanvas.uid = uid;
|
||
|
|
||
|
//videoCanvas.renderMode = AgoraVideoRenderModeFit;
|
||
|
videoCanvas.renderMode = AgoraVideoRenderModeHidden;
|
||
|
videoCanvas.view = self.remoteVideo;
|
||
|
[self.agoraKit setupRemoteVideo:videoCanvas];
|
||
|
}
|
||
|
|
||
|
- (void)rtcEngine:(AgoraRtcEngineKit *)engine didJoinChannel:(NSString *)channel withUid:(NSUInteger)uid elapsed:(NSInteger) elapsed
|
||
|
{
|
||
|
NSLog(@"*本地用户成功加入指定通道时发生。");
|
||
|
}
|
||
|
|
||
|
- (void)rtcEngine:(AgoraRtcEngineKit *)engine remoteVideoStateChangedOfUid:(NSUInteger)uid state:(AgoraVideoRemoteState)state reason:(AgoraVideoRemoteReason)reason elapsed:(NSInteger)elapsed
|
||
|
{
|
||
|
NSLog(@"************************");
|
||
|
}
|
||
|
- (void)rtcEngine:(AgoraRtcEngineKit *)engine localVideoStats:(AgoraRtcLocalVideoStats * _Nonnull)stats
|
||
|
{
|
||
|
NSLog(@"本地视频流");
|
||
|
}
|
||
|
|
||
|
////MARK: 视频的暂停 和 恢复
|
||
|
//- (void)rtcEngine:(AgoraRtcEngineKit *)engine didVideoMuted:(BOOL)muted byUid:(NSUInteger)uid {
|
||
|
// NSLog(@"//MARK: 视频的暂停 和 恢复");
|
||
|
// self.remoteVideo.hidden = muted;
|
||
|
//}
|
||
|
|
||
|
//MARK: 频道的统计数据 回调 每两秒触发一次。
|
||
|
-(void)rtcEngine:(AgoraRtcEngineKit *)engine reportRtcStats:(AgoraChannelStats *)stats
|
||
|
{
|
||
|
NSLog(@"//MARK: 频道的统计数据 回调 每两秒触发一次。");
|
||
|
if(self.isCall)
|
||
|
{
|
||
|
// self.timeLength = (int)stats.duration - wait_duration;
|
||
|
//MARK:记录视频通话时间
|
||
|
[UserDefaults setValue:[NSString stringWithFormat:@"%@&%@&%@&%@&%@",@(stats.duration),self.video_id,@(self.videoSize.width),@(self.videoSize.height),@(wait_duration)] forKey:VideoTimeAndIDAndWHRecordKey];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//MARK: 用户离线回调
|
||
|
- (void)rtcEngine:(AgoraRtcEngineKit *)engine didOfflineOfUid:(NSUInteger)uid reason:(AgoraUserOfflineReason)reason
|
||
|
{
|
||
|
self.remoteVideo.hidden = true;
|
||
|
switch (reason) {
|
||
|
case AgoraUserOfflineReasonQuit:
|
||
|
//用户主动离开
|
||
|
NSLog(@"用户主动离开");
|
||
|
[self leaveChannel];
|
||
|
break;
|
||
|
case AgoraUserOfflineReasonBecomeAudience:
|
||
|
//用户身份从主播切换为观众时触发
|
||
|
NSLog(@"用户身份从主播切换为观众时触发");
|
||
|
break;
|
||
|
case AgoraUserOfflineReasonDropped:
|
||
|
//因过长时间收不到对方数据包,超时掉线。注意:由于 SDK 使用的是不可靠通道,也有可能对方主动离开本方没收到对方离开消息而误判为超时掉线
|
||
|
NSLog(@"因过长时间收不到对方数据包,超时掉线。注意:由于 SDK 使用的是不可靠通道,也有可能对方主动离开本方没收到对方离开消息而误判为超时掉线");
|
||
|
break;
|
||
|
}
|
||
|
if(reason == AgoraUserOfflineReasonBecomeAudience)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
if(uid == self.device_uid)
|
||
|
{
|
||
|
[self leaveChannel];
|
||
|
[UICommon MessageErrorText:F(@"%@已挂断", APIManager.sharedManager.deviceModel.name)];
|
||
|
}
|
||
|
if(uid == self.uid){
|
||
|
NSLog(@"自己离开通道");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#pragma mark - 时间定时器
|
||
|
|
||
|
- (void)timeTimerAction:(id)sender
|
||
|
{
|
||
|
self.timeLength += 1;
|
||
|
if(self.isCall == NO)
|
||
|
{
|
||
|
//未接通的情况
|
||
|
if(self.timeLength == self.wait_time)
|
||
|
{
|
||
|
wait_duration = self.wait_time;
|
||
|
[self leaveChannel];
|
||
|
kWeakSelf(self)
|
||
|
[UICommon MessageErrorText:F(@"%@ %@", APIManager.sharedManager.deviceModel.name,GJText(@"未接听"))];
|
||
|
AfterDispatch(1.5, ^{
|
||
|
[weakself dismissViewControllerAnimated:YES completion:nil];
|
||
|
});
|
||
|
|
||
|
[self _stopTimeTimer];
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
wait_duration = self.timeLength;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(self.timeLength == self.limit_time - DefineVideoLimitBeforeShowTime){
|
||
|
EasyAlertView *alertV = [EasyAlertView alertViewWithTitle:GJText(@"提示") subtitle:GJText(@"为防止设备温度过高,即将结束通话,稍后可正常使用") AlertViewType:AlertViewTypeSystemAlert config:nil];
|
||
|
[alertV addAlertItem:^EasyAlertItem *{
|
||
|
return [EasyAlertItem itemWithTitle:GJText(@"取消") type:AlertItemTypeSystemCancel callback:nil];
|
||
|
}];
|
||
|
[alertV addAlertItem:^EasyAlertItem *{
|
||
|
return [EasyAlertItem itemWithTitle:GJText(@"确定") type:AlertItemTypeSystemDefault callback:nil];
|
||
|
}];
|
||
|
[alertV showAlertView];
|
||
|
}
|
||
|
|
||
|
//限制时间, 不能和设备视频太长时间 默认是 180s (3分钟)
|
||
|
if(self.timeLength == self.limit_time)
|
||
|
{
|
||
|
[self hangUpButton:nil];
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if(self.isCall)
|
||
|
{
|
||
|
int hour = self.timeLength / 3600;
|
||
|
int m = (self.timeLength - hour * 3600) / 60;
|
||
|
int s = self.timeLength - hour * 3600 - m * 60;
|
||
|
if (hour > 0)
|
||
|
{
|
||
|
self.timeLabel.text = [NSString stringWithFormat:@"%02i:%02i:%02i", hour, m, s];
|
||
|
}
|
||
|
else if(m > 0)
|
||
|
{
|
||
|
self.timeLabel.text = [NSString stringWithFormat:@"%02i:%02i", m, s];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
self.timeLabel.text = [NSString stringWithFormat:@"00:%02i", s];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (void)_startTimeTimer
|
||
|
{
|
||
|
[self _stopTimeTimer];
|
||
|
self.timeLength = 0;
|
||
|
self.timeTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timeTimerAction:) userInfo:nil repeats:YES];
|
||
|
}
|
||
|
|
||
|
- (void)_stopTimeTimer
|
||
|
{
|
||
|
if (self.timeTimer)
|
||
|
{
|
||
|
[self.timeTimer invalidate];
|
||
|
self.timeTimer = nil;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
-(void)viewDidDisappear:(BOOL)animated
|
||
|
{
|
||
|
[super viewDidDisappear:animated];
|
||
|
[self stopRing]; //停止响铃
|
||
|
//移除通知
|
||
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:AccountMessageNotification object:nil];
|
||
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||
|
}
|
||
|
- (void)viewWillAppear:(BOOL)animated
|
||
|
{
|
||
|
[super viewWillAppear:animated];
|
||
|
kWeakSelf(self)
|
||
|
if(!self.isReceiveCall)
|
||
|
{
|
||
|
//主动拨打
|
||
|
//显示静音 和 切换摄像头
|
||
|
self.switchCameraView.hidden = NO;
|
||
|
self.muteBtnView.hidden = NO;
|
||
|
|
||
|
//隐藏 被动接听 和 被动挂断
|
||
|
self.activeHangupView.hidden = NO;
|
||
|
self.acceptView.hidden = YES;
|
||
|
self.hangupView.hidden = YES;
|
||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||
|
[weakself playRing:@"ring"];
|
||
|
});
|
||
|
[self joinChannel];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//被动接听
|
||
|
//隐藏 静音 和 切换摄像头
|
||
|
self.switchCameraView.hidden = YES;
|
||
|
self.muteBtnView.hidden = YES;
|
||
|
self.activeHangupView.hidden = YES;
|
||
|
self.acceptView.hidden = NO;
|
||
|
self.hangupView.hidden = NO;
|
||
|
if([UIApplication sharedApplication].applicationState == UIApplicationStateActive){
|
||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||
|
[weakself playRing:@"tones"];
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
- (void)setIsCall:(BOOL)isCall
|
||
|
{
|
||
|
_isCall = isCall;
|
||
|
if(isCall)
|
||
|
{
|
||
|
//隐藏 设备 头像 和 昵称 显示 (默认是显示的)
|
||
|
self.headImageView.hidden = YES;
|
||
|
self.nameLabel.hidden = YES;
|
||
|
self.localVideo.hidden = NO; // 显示自己
|
||
|
|
||
|
self.activeHangupView.hidden = NO;
|
||
|
self.acceptView.hidden = YES;
|
||
|
self.hangupView.hidden = YES;
|
||
|
//显示 时间Label
|
||
|
self.timeLabel.hidden = NO;
|
||
|
//显示
|
||
|
self.switchCameraView.hidden = NO;
|
||
|
self.muteBtnView.hidden = NO;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//MARK: --- 拖动手势 ----
|
||
|
- (void)handlePan:(UIPanGestureRecognizer*)recognizer
|
||
|
{
|
||
|
UIView *selectView = recognizer.view;
|
||
|
if(selectView.bounds.size.width != SCREEN_WIDTH)
|
||
|
{ //不是全屏状态
|
||
|
// 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 != SCREEN_WIDTH)
|
||
|
{
|
||
|
if([self.localVideo isEqual:selectView])
|
||
|
{
|
||
|
self.localVideo.frame = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||
|
self.remoteVideo.frame = tempRect;
|
||
|
[self.view exchangeSubviewAtIndex:self.remoteVideo.getInSuperViewIndex withSubviewAtIndex:self.localVideo.getInSuperViewIndex];
|
||
|
}else{
|
||
|
self.remoteVideo.frame = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||
|
self.localVideo.frame = tempRect;
|
||
|
[self.view exchangeSubviewAtIndex:self.localVideo.getInSuperViewIndex withSubviewAtIndex:self.remoteVideo.getInSuperViewIndex];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
-(void)dealloc
|
||
|
{
|
||
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||
|
}
|
||
|
|
||
|
- (void)didReceiveMemoryWarning {
|
||
|
[super didReceiveMemoryWarning];
|
||
|
// Dispose of any resources that can be recreated.
|
||
|
}
|
||
|
|
||
|
|
||
|
@end
|