该文章是建立在已经用环信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。
关于图标我要提一下,由于我使用的是3.2.0,集成成功之后,我发现它给的界面有些简陋。关键的图标都没有,全都用一块块button代替,毫无美感。所以我检查了一下最新版的SDK,发现他们已经完善了这个缺陷,新加的图标挺好看的,我就扣下来放在这个工程里面用了。
实现原理
集成环信,需要导入EaseUI
、HyphenateFullSDK
、emotion
。一个是UI界面,一个是环信SDK,最后一个是emotion表情包。
实现的第一步是要从聊天界面,点击“+”出现的MoreView开始。这个MoreView出现在EaseUI中,并且视频跟语音的图标一开始是隐藏的,位置也有所变动。
下面就是去找到代码所在地,并研究一波。
在
EaseChatBarMoreView.m
中找到- (void)setupSubviewsForType:(EMChatToolbarType)type{}
这个方法,在这个方法中我们就能发现,MoreView里面的几个按钮图标就是在这里创建的,如下图。
找到了UI创建的地方,这只是第一步。下面就要根据按钮绑定的方法,一步步往下深究。
首先根据
_videoCallButton
找到绑定的方法takeVideoCallAction
,发现它通过代理实现的另一个方法moreViewVideoCallAction:
,按住command键单击方法继续跟踪。我们发现在EaseUI
的EaseMessageViewController.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.h
、ChatDemoHelper.m
需要导入和注释的头文件。
对照着看,有几个类不需要,有几个是重新导入的。在
ChatDemoHelper.m
中需要注意的是
- (void)makeCallWithUsername:(NSString *)aUsername
type:(EMCallType)aType{}//发起视频
- (void)callDidReceive:(EMCallSession *)aSession{}//接收视频
这两个方法中的mainVC是找不到的,所有我要找到当前视图控制器,并让它作为父视图,模态弹出CallViewController
,如下图所示。
修改的差不多了,我们就在
MainViewController.m
的 viewDidLoad
中初始化ChatDemoHelper
贴上代码[ChatDemoHelper shareHelper];
(在程序进入的第一个视图控制器中初始化)然后运行代码,调试一波,发现功能是能实现了,但是UI界面有点丑,并且没有来电铃声(虽然铃声相关的代码有)。然后我找到
CallViewController .m
修改了一波UI,并且自己在网上down了一段苹果来电铃声,并加了上去,差不多满足了需求。需要注意的是,铃声的播放要放在CallViewController.m
的viewDidAppear:(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];
代码实现的差不多了,效果图如下:
**基于环信实现在线聊天功能 **
转载请注明出处