這段時間由于家里的事和工作上的項目太忙好久沒寫東西了档址,,邻梆,今天先說說集成環(huán)信的經(jīng)驗(yàn)吧守伸,也許會很亂,我會慢慢修改的浦妄。新手一枚第一次集成環(huán)信尼摹,咱們慢慢看算是我自己的一個整理。
一剂娄、準(zhǔn)備工作:
- 環(huán)信官網(wǎng)http://www.easemob.com 也可以百度環(huán)信還是很好找的蠢涝。
2.蘋果賬號,因?yàn)榧杉磿r聊天要推送證書所以必須有賬號阅懦,證書制作我就不在這里說了和二,可以上網(wǎng)查。
3.在環(huán)信創(chuàng)建APP上傳推送證書耳胎,這樣可以了過程很簡單的(appkey惯吕,推送證書名是有用的可以先記錄)。
二怕午、開始集成
1.這里總的說一下
第一點(diǎn)環(huán)信提供兩套SDK混埠,一套帶有實(shí)時語音(打電話)版本HyphenateFullSDK,一套沒有的HyphenateSDK诗轻,正常不是專門聊天的APP都是不用實(shí)時語音功能的钳宪。
第二點(diǎn)環(huán)信給了一套做好的UI叫EaseUI,可以用能減少很多時間,特別是聊天頁面自己寫比較麻煩吏颖,特別是EASYUI中的Model寫的都不錯搔体。
第三點(diǎn)集成方式可以手動集成SDK,可以用pod集成半醉,手動集成就不說了疚俱,下面給出pod命令
pod 'HyphenateSDK', :git => 'https://github.com/easemob/hyphenate-cocoapods.git'
pod 'HyphenateFullSDK', :git => 'https://github.com/easemob/hyphenate-full-cocoapods.git'
pod 'EaseUI' //這個環(huán)信官網(wǎng)上沒有是我在環(huán)信的git上找到的。
這里有一點(diǎn)注意的地方缩多,如果你用pod集成呆奕,注意pod更新是會吧你改動的代碼刷新掉,可以不直接用EaseUI里的東西衬吆,可以寫子類梁钾,或者刷新掉了,可以用git或者svn逊抡,還原修改姆泻,這樣就能回來了。
這樣我們就把SDK集成到我們的項目了冒嫡。
第四點(diǎn)什么改APP端做什么該服務(wù)端做拇勃,服務(wù)端做的其實(shí)很少,只有兩個孝凌,第一注冊環(huán)信方咆,這部分一般式綁定在我們注冊當(dāng)前APP用戶的要查詢服務(wù)端數(shù)據(jù)庫,所以服務(wù)端做蟀架,第二瓣赂,好友關(guān)系,環(huán)信用戶之間聊天是不需要好友關(guān)系的辜窑,所以決定了好友關(guān)系這部分可以直接用我們的服務(wù)端維護(hù)。這兩點(diǎn)以外寨躁,其他的都是我們APP端做穆碎,,职恳,
2.開始代碼部分(這部分代碼前提集成了HyphenateSDK和EaseUI)
首先在AppDelegate中注冊環(huán)信所禀,直接可用EaseUI中的注冊方法
一,注冊環(huán)信
/*!
* APP啟動時注冊環(huán)信放钦,并登陸當(dāng)前用戶(如果有用戶的話)
*
* @param application application description
* @param launchOptions launchOptions description
*/
-(void)startHuanXinEasyUIUseapplication:(UIApplication *)application Options:(NSDictionary *)launchOptions{
//AppKey:注冊的AppKey色徘,詳細(xì)見下面注釋。
//apnsCertName:推送證書名(不需要加后綴)操禀,詳細(xì)見下面注釋褂策。
NSString *apnsCertName = nil;
#if DEBUG
apnsCertName = @"開發(fā)環(huán)境測試證書";
#else
apnsCertName = @"發(fā)布環(huán)境證書";
#endif
//環(huán)信appkey存放在UserDefaults
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
NSString *appkey = [ud stringForKey:@"identifier_appkey"];
if (!appkey) {
appkey = @"appkey";
[ud setObject:appkey forKey:@"identifier_appkey"];
}
//利用EasyUI啟動環(huán)信(這里有一個坑,下面這個注冊方法,點(diǎn)進(jìn)去看會吧用戶是否同意被加進(jìn)群組改成NO斤寂,這里會導(dǎo)致群組加不上耿焊,記得看看,改回來)
[[EaseSDKHelper shareHelper] easemobApplication:application
didFinishLaunchingWithOptions:launchOptions
appkey:appkey
apnsCertName:apnsCertName
otherConfig:@{kSDKConfigEnableConsoleLogger:[NSNumber numberWithBool:YES]}];
//判斷當(dāng)前是否有用戶遍搞,有用戶登陸環(huán)信
if (DEF_PERSISTENT_GET_OBJECT(@"userId") != nil && DEF_PERSISTENT_GET_OBJECT(@"userPwd") != nil) {
NSString *accound = [NSString stringWithFormat:@"%@",DEF_PERSISTENT_GET_OBJECT(@"userId")];
NSString *pwd = [NSString stringWithFormat:@"%@",DEF_PERSISTENT_GET_OBJECT(@"userPwd")];
EMError *error = [[EMClient sharedClient] loginWithUsername:accound password:pwd];
[[EMClient sharedClient] addDelegate:self];
if (!error) {
NSLog(@"登錄成功");
}
}
}
二罗侯、環(huán)信好友
聊天就得有好友,剛開始總述中說過好友是咱們服務(wù)器來維護(hù)的所以不用管溪猿,走一個接口就好了钩杰,因?yàn)槲覀兗蒃asyUI所以我們從接口中請求的數(shù)據(jù)最好都變成EasyUI中用戶的Model(EaseUserModel),這樣在用環(huán)信聊天的是不會那么麻煩诊县,也可以自己寫一個Model這樣麻煩但是不亂讲弄,
#import <Foundation/Foundation.h>
#import "IUserModel.h"
@interface EaseUserModel : NSObject<IUserModel>
@property (strong, nonatomic, readonly) NSString *buddy;//用戶名
@property (strong, nonatomic) NSString *nickname;//名字
@property (strong, nonatomic) NSString *avatarURLPath;//頭像地址
@property (strong, nonatomic) UIImage *avatarImage;//頭像圖片
- (instancetype)initWithBuddy:(NSString *)buddy;
@end
中用戶名是最有用的是直接用于創(chuàng)建聊天的,名字頭像用處不大翎冲,因?yàn)檫@些存儲都是在本地的垂睬,地方一改名字頭像你這面可能沒反應(yīng)所以不用這個頭像名字,都是使用消息中的擴(kuò)展字段下面說抗悍。
三驹饺、環(huán)信聊天
聊天界面我推薦直接用EasyUI的,自己寫各種消息cell實(shí)在麻煩缴渊,使用這個直接就是可以聊天的創(chuàng)建方法如下
EaseMessageViewController *viewController = [[EaseMessageViewController alloc] initWithConversationChatter:@"聊天對象的id赏壹,或者群組的id" conversationType:聊天的類型(單聊,群聊,聊天室)];
四、環(huán)信聊天消息重點(diǎn)*
在發(fā)消息過程中是不能傳遞用戶名和頭像的衔沼,所以我們要給消息添加擴(kuò)展字段ext蝌借,(擴(kuò)展字段可以其實(shí)就是發(fā)送消息是附帶傳遞一個json數(shù)據(jù)),我們可以吧自己的頭像和名字在每次發(fā)消息的時候發(fā)過去指蚁,這樣聊天時菩佑,當(dāng)前本人可以知道自己的名字和頭像,聊天對方會在消息中發(fā)過來名字頭像凝化,這樣兩個人都有名字頭像了稍坯,下面貼下我的擴(kuò)展字段
- (void)_sendMessage:(EMMessage *)message //發(fā)消息的總方法
{
message.ext = @{@"nikeName":_myNikeName,@"headImagePath":_myHeadImagePath}; //添加消息擴(kuò)展,我的名字搓劫,我的頭像
if (self.conversation.type == EMConversationTypeGroupChat){
message.chatType = EMChatTypeGroupChat;
}
else if (self.conversation.type == EMConversationTypeChatRoom){
message.chatType = EMChatTypeChatRoom;
}
[self addMessageToDataSource:message
progress:nil];
__weak typeof(self) weakself = self;
[[EMClient sharedClient].chatManager asyncSendMessage:message progress:nil completion:^(EMMessage *aMessage, EMError *aError) {
[weakself.tableView reloadData];
}];
}
五瞧哟、消息列表
消息列表的獲取用環(huán)信的獲取方法
- (void)tableViewDidTriggerHeaderRefresh
{
NSArray *conversations = [[EMClient sharedClient].chatManager getAllConversations];//本地獲取消息
NSArray* sorted = [conversations sortedArrayUsingComparator:
^(EMConversation *obj1, EMConversation* obj2){
EMMessage *message1 = [obj1 latestMessage];
EMMessage *message2 = [obj2 latestMessage];
if(message1.timestamp > message2.timestamp) {
return(NSComparisonResult)NSOrderedAscending;
}else {
return(NSComparisonResult)NSOrderedDescending;
}
}];
[self.tableView endHeaderFresh];
[self.tableView reloadData];
}
這里有一個地方,再獲得會話列表的時候枪向,有幾個數(shù)據(jù)要自己獲取一下勤揩,頭像,名字秘蛔,最后一條消息內(nèi)容陨亡,最后一條消息時間傍衡,消息未讀數(shù)。其中消息未讀數(shù)事環(huán)信幫我們做好的直接設(shè)置顯示未讀數(shù)就好
其中消息最后一條消息內(nèi)容数苫,最后一條消息時間聪舒。要我們獲取最后一條消息在給其賦值
//在tableView代理中寫
cell.detailLabel.attributedText = [[EaseEmotionEscape sharedInstance] attStringFromTextForChatting:[self _latestMessageTitleForConversationModel:model]textFont:cell.detailLabel.font];
cell.timeLabel.text = [self _latestMessageTimeForConversationModel:model];
//獲取最后一條消息內(nèi)容
- (NSString *)_latestMessageTitleForConversationModel:(id<IConversationModel>)conversationModel
{
NSString *latestMessageTitle = @"";
EMMessage *lastMessage = [conversationModel.conversation latestMessage];
if (lastMessage) {
EMMessageBody *messageBody = lastMessage.body;
switch (messageBody.type) {
case EMMessageBodyTypeImage:{
latestMessageTitle = NSEaseLocalizedString(@"message.image1", @"[image]");
} break;
case EMMessageBodyTypeText:{
NSString *didReceiveText = [EaseConvertToCommonEmoticonsHelper
convertToSystemEmoticons:((EMTextMessageBody *)messageBody).text];
latestMessageTitle = didReceiveText;
} break;
case EMMessageBodyTypeVoice:{
latestMessageTitle = NSEaseLocalizedString(@"message.voice1", @"[voice]");
} break;
case EMMessageBodyTypeLocation: {
latestMessageTitle = NSEaseLocalizedString(@"message.location1", @"[location]");
} break;
case EMMessageBodyTypeVideo: {
latestMessageTitle = NSEaseLocalizedString(@"message.video1", @"[video]");
} break;
case EMMessageBodyTypeFile: {
latestMessageTitle = NSEaseLocalizedString(@"message.file1", @"[file]");
} break;
default: {
} break;
}
}
return latestMessageTitle;
}
//獲取最后一條消息時間
- (NSString *)_latestMessageTimeForConversationModel:(id<IConversationModel>)conversationModel
{
NSString *latestMessageTime = @"";
EMMessage *lastMessage = [conversationModel.conversation latestMessage];;
if (lastMessage) {
double timeInterval = lastMessage.timestamp ;
if(timeInterval > 140000000000) {
timeInterval = timeInterval / 1000;
}
NSDateFormatter* formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:@"YYYY-MM-dd"];
latestMessageTime = [formatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:timeInterval]];
}
return latestMessageTime;
}
至于頭像名字則要我們使用我沒發(fā)消息的擴(kuò)展字段,
這里我們可以獲取會話中最后一條來自對方的消息虐急,然后取出擴(kuò)展字段賦值就好箱残,(ps:有一種情況我剛剛和一個人說話會話中沒有來自對方的最后一條消息,這個時候我們要用我們本地自己賦值這個會話的頭像和名字)
三止吁、總結(jié)
恩被辑,這是這個雜記的第一次寫的東西,寫了寫基本的用法敬惦,簡單的聊天功能盼理,寫的也比較亂,俄删,我會慢慢整理修改的宏怔。