环信是一个提供聊天功能的公司,我的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方法中对这个方法进行调用就可以了。