Osheep

时光不回头,当下最重要。

基于环信实现实时视频语音通话功能

该文章是建立在已经用环信SDK实现了聊天功能的基础之上,再去添加新的视频语音通话功能。基于环信实现在线聊天功能

实现前的准备工作

1.先在环信官网下载环信SDK 环信SDK下载 我使用的环信SDK版本为 V3.2.0 2016-10-15

2.除了实现聊天功能需要导入的库之外,还需导入libiconv.dylib库,这是环信实时语音包含的依赖库。

3.除了步骤2需要导入支持环信SDK所需要的库之外,还需导入libbz2.1.0.tbd库,因为视频聊天里面包含ffmpeg第三方,它需要这个依赖库。

4.在工程中添加包含视频语音通话功能的SDK HyphenateFullSDK,如果之前使用的是EaseUI所支持的HyphenateSDK,需要将这个简版的SDK删除干净(最好是在Finder中检查一下)否则会引起重复导入冲突。还需要注意一点的是,需要在Other Linker Flags 中添加-ObjC。具体做法 工程>>TARGETS>>Build Settings>>搜索other>>找到Other Linker Flags 添加-ObjC。

5.在环信的demo里找到Call文件夹,选择导入CallViewController ChatDemoHelper EMCallOptions+NSCoding 并导入plugin文件夹 ChatView包含视频语音通话的一些图标,也需要导入。由于环信的SDK做了国际化,所以还需添加Localizable.strings。

《基于环信实现实时视频语音通话功能》

环信demo里找到这些
《基于环信实现实时视频语音通话功能》

还有这些
《基于环信实现实时视频语音通话功能》

里面包含call的一些图标都需要

关于图标我要提一下,由于我使用的是3.2.0,集成成功之后,我发现它给的界面有些简陋。关键的图标都没有,全都用一块块button代替,毫无美感。所以我检查了一下最新版的SDK,发现他们已经完善了这个缺陷,新加的图标挺好看的,我就扣下来放在这个工程里面用了。

实现原理

集成环信,需要导入EaseUIHyphenateFullSDKemotion。一个是UI界面,一个是环信SDK,最后一个是emotion表情包。

实现的第一步是要从聊天界面,点击“+”出现的MoreView开始。这个MoreView出现在EaseUI中,并且视频跟语音的图标一开始是隐藏的,位置也有所变动。

《基于环信实现实时视频语音通话功能》

视频语音图标一开始是没有的

下面就是去找到代码所在地,并研究一波。

《基于环信实现实时视频语音通话功能》

MoreView

EaseChatBarMoreView.m 中找到- (void)setupSubviewsForType:(EMChatToolbarType)type{}这个方法,在这个方法中我们就能发现,MoreView里面的几个按钮图标就是在这里创建的,如下图。

《基于环信实现实时视频语音通话功能》

红线标注的地方一开始是150,而后修改为80

找到了UI创建的地方,这只是第一步。下面就要根据按钮绑定的方法,一步步往下深究。
首先根据_videoCallButton找到绑定的方法takeVideoCallAction,发现它通过代理实现的另一个方法moreViewVideoCallAction:,按住command键单击方法继续跟踪。我们发现在EaseUIEaseMessageViewController.m中,该方法实现了,并且发了一个通知,如下图。

《基于环信实现实时视频语音通话功能》

视频通话相关方法

很明显,这就是视频通话的通知,并且我们通过相同的方法不难发现,语音通话的通知跟这个是一样的。我们找到关键字KNOTIFICATION_CALL在环信demo中搜一下,就知道哪个地方接收了通知。

《基于环信实现实时视频语音通话功能》

语音、视频通话的通知关键字一样

很明显,ChatDemoHelper就是我们要关注的地方,然后直接到了这里。

《基于环信实现实时视频语音通话功能》

接收语音、视频通话的通知

细心的你肯定发现了图上面我注释的那些,ChatDemoHelper.m里面有好多方法我是不需要的,所有我都注释了。现在我讲讲多余的代码是哪些?需要的又是哪些?

图上方我注释的代码分别是:

[[RedPacketUserConfig sharedConfig] beginObserveMessage];//红包相关

[[EMClient sharedClient] addDelegate:self delegateQueue:nil];//添加回调代理

[[EMClient sharedClient].groupManager addDelegate:self delegateQueue:nil];//群组模块代理

[[EMClient sharedClient].contactManager addDelegate:self delegateQueue:nil];//好友模块代理

[[EMClient sharedClient].roomManager addDelegate:self delegateQueue:nil];//聊天室模块代理

[[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];//聊天模块代理

好友,聊天,回调相关代理,我在自定义聊天功能中用到过,这里只是需要添加视频相关的代理,所以有关于这些的代理和下面所出现的方法我都注释了,只保留语音视频相关代码。注释的代码太多,不易贴出,只要注意把上面我指出的那几类注释就好,所有涉及call的代码都保留。

[[EMClient sharedClient].callManager addDelegate:self delegateQueue:nil];//实时通讯相关代理

还有ChatDemoHelper.hChatDemoHelper.m需要导入和注释的头文件。

《基于环信实现实时视频语音通话功能》

ChatDemoHelper.h
《基于环信实现实时视频语音通话功能》

ChatDemoHelper.m

对照着看,有几个类不需要,有几个是重新导入的。在ChatDemoHelper.m中需要注意的是

- (void)makeCallWithUsername:(NSString *)aUsername
                        type:(EMCallType)aType{}//发起视频

- (void)callDidReceive:(EMCallSession *)aSession{}//接收视频

这两个方法中的mainVC是找不到的,所有我要找到当前视图控制器,并让它作为父视图,模态弹出CallViewController,如下图所示。

《基于环信实现实时视频语音通话功能》

找到当前视图控制器

修改的差不多了,我们就在MainViewController.mviewDidLoad中初始化ChatDemoHelper贴上代码[ChatDemoHelper shareHelper];(在程序进入的第一个视图控制器中初始化)
然后运行代码,调试一波,发现功能是能实现了,但是UI界面有点丑,并且没有来电铃声(虽然铃声相关的代码有)。然后我找到CallViewController .m修改了一波UI,并且自己在网上down了一段苹果来电铃声,并加了上去,差不多满足了需求。需要注意的是,铃声的播放要放在CallViewController.mviewDidAppear:(BOOL)animated中。

《基于环信实现实时视频语音通话功能》

呼叫界面
《基于环信实现实时视频语音通话功能》

视频通话界面

细节优化

1.程序在后台,添加推送消息并铃声提醒。具体操作如下:
ChatDemoHelper.m中找到- (void)callDidReceive:(EMCallSession *)aSession{}这个方法,并在这个方法里设置本地推送。

// 接收到视频 在方法开始的地方设置本地推送相关代码,原有代码不变。
- (void)callDidReceive:(EMCallSession *)aSession
{
    // 程序在后台
    if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {

        UILocalNotification *notify = [[UILocalNotification alloc]init];
        NSDate *fireDate = [NSDate dateWithTimeIntervalSinceNow:1];
        notify.fireDate = fireDate;

        //时区
        notify.timeZone = [NSTimeZone defaultTimeZone];
        //通知内容
        // 将环信ID通过本地数据库匹配,找到真实的名字
        SaveMingYiModel *mingYiModel = [HaoYouDao selectedFromPeopleTableWithMDsfz:aSession.remoteName];


        NSString *stype =nil;
        if (aSession.type == EMCallTypeVoice) {

            stype = @"实时语音";
        }
        else if (aSession.type == EMCallTypeVideo){

            stype = @"视频通话";
        }
        NSString *notifyStr = [NSString stringWithFormat:@"%@向您发起%@",mingYiModel.docName,stype];

        notify.alertBody = notifyStr;

        // 如果你想震动的提示播放音乐的话就在下面填入你的音乐文件
        NSString *path = [[NSBundle mainBundle] pathForResource:@"callRing" ofType:@"mp3"];
        AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:path], &sound);
        AudioServicesAddSystemSoundCompletion(kSystemSoundID_Vibrate, NULL, NULL, soundCompleteCallback, NULL);
        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
        AudioServicesPlaySystemSound(sound);

        // ios8后,需要添加这个注册,才能得到授权
        if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
            UIUserNotificationType type =  UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound;

            UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:type
                                                                                     categories:nil];
            [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
        }
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
             // 执行通知注册
            [[UIApplication sharedApplication] scheduleLocalNotification:notify];
        });

    }
//==========后台持续震动和播放铃声的方法============
void soundCompleteCallback(SystemSoundID sound,void * clientData) {
    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);  //震动
    AudioServicesPlaySystemSound(sound);
}
//结束铃声
-(void)stopAlertSoundWithSoundID:(SystemSoundID)sound {
    AudioServicesDisposeSystemSoundID(kSystemSoundID_Vibrate);
}
//============end=================

然后在合适的地方结束震动和提醒铃声。比如在视频结束、接听、拒接、中断等方法中加上结束的代码。(代码中很容易找到相关方法)

//调用结束震动和提醒铃声的方法
 AudioServicesRemoveSystemSoundCompletion(kSystemSoundID_Vibrate);
   [self stopAlertSoundWithSoundID:sound];

代码实现的差不多了,效果图如下:

《基于环信实现实时视频语音通话功能》

后台震动铃声提醒,并发送通知

基于环信实现在线聊天功能

转载请注明出处

点赞