环信是一个提供聊天功能的公司,我的app里面集成了环信,但是在使用的时候发现它给的文档并不是很完善,很多功能都写的很是粗略,尽管Demo里面功能很完善,但是因为代码量比较大,看起来非常麻烦。尤其是环信的demo使用了大量的第三方库(而且过时了),很多跟我本地使用的都冲突了,集成起来可谓问题重重。接下来我就讲一下我在集成环信的时候遇到的一些问题。
头像及聊天人设置:
聊天界面里总是要显示聊天人头像的,但是遍寻环信的文档,居然没有关于这方面的只言片语,可能有人会说demo里面很完善啊,直接在demo里找就好了啊,可是环信给的demo真的太大了,为了找这个头像设置的地方,我看源码看了好久。后来才知道原来是使用了代理方法来设置的。
在 ChatViewController.m中ChatViewControllerDelegate 代理有两个方法就是分别用来设置聊天人头像和名字的:
// 根据环信id得到要显示头像路径,如果返回nil,则显示默认头像
- (NSString *)avatarWithChatter:(NSString *)chatter;
// 根据环信id得到要显示用户名,如果返回nil,则默认显示环信id
- (NSString *)nickNameWithChatter:(NSString *)chatter;
设置自己头像和名字的方法是在ChatViewController.m的
(NSMutableArray *)formatMessage:(EMMessage *)message
方法中:
//model是信息的模型 这里判断信息是否为发送者所有,如果是,则设置发送者的头像和姓名 否则设置接收者头像和姓名
MessageModel *model = [MessageModelManager modelWithMessage:message];
if (model.isSender) {//设置发送者姓名和头像
model.nickName = delegate.userInfoModel.userName;
model.headImageURL = [NSURL URLWithString:delegate.userInfoModel.userLogo];
}else{//设置接收者姓名和头像
model.nickName = [self.chatterInfo objectForKey:@"userName"];
model.headImageURL =[NSURL URLWithString:XZImageBaseURL([self.chatterInfo objectForKey:@"image" ])];
}
我用的时候没有用环信的代理,而是全部直接传过去的。
收信提醒
环信在受到消息之后可以触发代理来进行处理,比如刷新聊天列表或者在工具栏设置消息角标等等。代理方法是
-(void)didReceiveMessage:(EMMessage *)message
可是在设置这个的时候怎么发消息都没有触发这个代理方法,我把demo翻了个遍,才找到了可能有用的地方:
#pragma mark - 环信
#pragma mark - private
-(void)registerNotifications
{
[self unregisterNotifications];
[[EaseMob sharedInstance].chatManager addDelegate:self delegateQueue:nil];
[[EaseMob sharedInstance].callManager addDelegate:self delegateQueue:nil];
}
-(void)unregisterNotifications
{
[[EaseMob sharedInstance].chatManager removeDelegate:self];
[[EaseMob sharedInstance].callManager removeDelegate:self];
}
这段代码在demo中的MainViewController.m文件中。在我的代码中添加了这段之后,收到消息时才会触发didReceiveMessage方法。
推送
环信本身既支持离线推送又支持在线推送(在线推送就是在触发了didreceivemessage之后设置的)。
离线推送:
离线推送的设置文档里讲的其实很清楚了,可是在demo中还有更多的设置,比如免打扰群消息等等的设置,如果这部分不做设置,离线推送是没法用的。这部分有点坑,尽管文档中有讲,可是也仅仅是列出了几个方法而已,怎么使用一句都没讲:
具体的设置在demo中的setting文件夹下的PushNotificationViewController.m文件里。
- (void)savePushOptions
{
BOOL isUpdate = NO;
EMPushNotificationOptions *options = [[EaseMob sharedInstance].chatManager pushNotificationOptions];
if (_pushDisplayStyle != options.displayStyle) {
options.displayStyle = _pushDisplayStyle;
isUpdate = YES;
}
if (_nickName && _nickName.length > 0 && ![_nickName isEqualToString:options.nickname])
{
options.nickname = _nickName;
isUpdate = YES;
}
if (options.noDisturbingStartH != _noDisturbingStart || options.noDisturbingEndH != _noDisturbingEnd){
isUpdate = YES;
options.noDisturbStatus = _noDisturbingStatus;
options.noDisturbingStartH = _noDisturbingStart;
options.noDisturbingEndH = _noDisturbingEnd;
}
if (isUpdate) {
[[EaseMob sharedInstance].chatManager asyncUpdatePushOptions:options];
}
[self.navigationController popViewControllerAnimated:YES];
}
这里设置的话有几个参数,第一个是noDistrbStatus,这个参数设置的是是否设置免打扰
/*!
@enum
@brief 推送消息免打扰设置的状态
@constant ePushNotificationNoDisturbStatusDay 全天免打扰
@constant ePushNotificationNoDisturbStatusCustom 自定义时间段免打扰
@constant ePushNotificationNoDisturbStatusClose 关闭免打扰模式
*/
typedef NS_ENUM(NSInteger, EMPushNotificationNoDisturbStatus) {
ePushNotificationNoDisturbStatusDay = 0,
ePushNotificationNoDisturbStatusCustom = 1,
ePushNotificationNoDisturbStatusClose = 2,
};
如果第一个参数设置了关闭免打扰,那么后两个参数就没有什么卵用了,直接设置为-1就好,可是如果设置的是自定义时间段免打扰,就需要设置时间(目前还只支持整点)这里拿一个展开:
/*!
@property
@brief 推送消息免打扰模式开始时间,小时,暂时只支持整点(小时)
*/
@property (nonatomic) NSUInteger noDisturbingStartH;
本地推送:
本地推送就是在didReceiveMessage方法被触发后进行设置的,在手机还在后台的时候使用本地推送,应用完全退出之后才是离线推送。
设置的地方在MainViewController.m中
- (void)showNotificationWithMessage:(EMMessage *)message
{
EMPushNotificationOptions *options = [[EaseMob sharedInstance].chatManager pushNotificationOptions];
//发送本地推送
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.fireDate = [NSDate date]; //触发通知的时间
if (options.displayStyle == ePushNotificationDisplayStyle_messageSummary) {
id<IEMMessageBody> messageBody = [message.messageBodies firstObject];
NSString *messageStr = nil;
switch (messageBody.messageBodyType) {
case eMessageBodyType_Text:
{
messageStr = ((EMTextMessageBody *)messageBody).text;
}
break;
case eMessageBodyType_Image:
{
messageStr = NSLocalizedString(@"message.image", @"Image");
}
break;
case eMessageBodyType_Location:
{
messageStr = NSLocalizedString(@"message.location", @"Location");
}
break;
case eMessageBodyType_Voice:
{
messageStr = NSLocalizedString(@"message.voice", @"Voice");
}
break;
case eMessageBodyType_Video:{
messageStr = NSLocalizedString(@"message.video", @"Video");
}
break;
default:
break;
}
NSString *title = [[UserProfileManager sharedInstance] getNickNameWithUsername:message.from];
if (message.messageType == eMessageTypeGroupChat) {
NSArray *groupArray = [[EaseMob sharedInstance].chatManager groupList];
for (EMGroup *group in groupArray) {
if ([group.groupId isEqualToString:message.conversationChatter]) {
title = [NSString stringWithFormat:@"%@(%@)", message.groupSenderName, group.groupSubject];
break;
}
}
}
else if (message.messageType == eMessageTypeChatRoom)
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
NSString *key = [NSString stringWithFormat:@"OnceJoinedChatrooms_%@", [[[EaseMob sharedInstance].chatManager loginInfo] objectForKey:@"username" ]];
NSMutableDictionary *chatrooms = [NSMutableDictionary dictionaryWithDictionary:[ud objectForKey:key]];
NSString *chatroomName = [chatrooms objectForKey:message.conversationChatter];
if (chatroomName)
{
title = [NSString stringWithFormat:@"%@(%@)", message.groupSenderName, chatroomName];
}
}
notification.alertBody = [NSString stringWithFormat:@"%@:%@", title, messageStr];
}
else{
notification.alertBody = NSLocalizedString(@"receiveMessage", @"you have a new message");
}
#warning 去掉注释会显示[本地]开头, 方便在开发中区分是否为本地推送
//notification.alertBody = [[NSString alloc] initWithFormat:@"[本地]%@", notification.alertBody];
notification.alertAction = NSLocalizedString(@"open", @"Open");
notification.timeZone = [NSTimeZone defaultTimeZone];
NSTimeInterval timeInterval = [[NSDate date] timeIntervalSinceDate:self.lastPlaySoundDate];
if (timeInterval < kDefaultPlaySoundInterval) {
NSLog(@"skip ringing & vibration %@, %@", [NSDate date], self.lastPlaySoundDate);
} else {
notification.soundName = UILocalNotificationDefaultSoundName;
self.lastPlaySoundDate = [NSDate date];
}
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
[userInfo setObject:[NSNumber numberWithInt:message.messageType] forKey:kMessageType];
[userInfo setObject:message.conversationChatter forKey:kConversationChatter];
notification.userInfo = userInfo;
//发送通知
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
// UIApplication *application = [UIApplication sharedApplication];
// application.applicationIconBadgeNumber += 1;
}
在-(void)didReceiveMessage:(EMMessage *)message方法中对这个方法进行调用就可以了。