使用環(huán)信實(shí)現(xiàn)聊天的過(guò)程遇到了一些坑,記錄一下避免自己和其他人踩坑或者盡快出坑。
問(wèn)題1 聊天頁(yè)面環(huán)信工具欄向上偏移
問(wèn)題描述:
在聊天頁(yè)面,點(diǎn)擊輸入框彈起鍵盤(pán),點(diǎn)擊IQKeyboardManager帶的完成按鈕或者點(diǎn)擊空白頁(yè)面收起鍵盤(pán),反復(fù)操作多次后,會(huì)出現(xiàn)頁(yè)面向上偏移,環(huán)信UI的工具欄移動(dòng)到了頁(yè)面最上邊。
解決方案:
在聊天頁(yè)面禁用IQKeyboardManager。
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
IQKeyboardManager *keyboardManager = [IQKeyboardManager sharedManager];
keyboardManager.enable = NO;
keyboardManager.enableAutoToolbar = NO;
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
IQKeyboardManager *keyboardManager = [IQKeyboardManager sharedManager];
keyboardManager.enable = YES;
keyboardManager.enableAutoToolbar = YES;
}
問(wèn)題2 保存環(huán)信昵稱(chēng)頭像到數(shù)據(jù)庫(kù)失敗
問(wèn)題描述:
環(huán)信服務(wù)器不存儲(chǔ)用戶(hù)的昵稱(chēng)頭像等用戶(hù)數(shù)據(jù)。需要客戶(hù)端自己來(lái)存儲(chǔ)并展示在界面上。有幾個(gè)時(shí)機(jī)是需要插入或更新一條包含昵稱(chēng)、頭像的用戶(hù)數(shù)據(jù)到數(shù)據(jù)庫(kù)里,比如查看用戶(hù)詳情,在某個(gè)頁(yè)面收到環(huán)信消息。我們服務(wù)器提供的查詢(xún)用戶(hù)信息接口返回的昵稱(chēng)和頭像,之前是沒(méi)有問(wèn)題的,有一次出現(xiàn)了從用戶(hù)信息界面進(jìn)入聊天頁(yè)面不顯示昵稱(chēng)的問(wèn)題。
問(wèn)題原因:
經(jīng)排查,接口返回的用戶(hù)頭像字段的值是null,由于客戶(hù)端之前沒(méi)有做空處理,導(dǎo)致插入或更新一條數(shù)據(jù)失敗。
DB Query: INSERT or REPLACE INTO t_huanxin (hxId,nickname,avatar) VALUES (?,?,?)
Unknown error finalizing or resetting statement (19: NOT NULL constraint failed: t_huanxin.avatar)
解決方案:
存儲(chǔ)用戶(hù)信息到本地?cái)?shù)據(jù)庫(kù)時(shí)增加安全判斷。如果為空,就存入空字符串。避免插入或更新字段為null導(dǎo)致操作失敗。
NSString *nickname = dic[@"nickname"]?:@"";
NSString *avatar = dic[@"avatar"]?:@"";
問(wèn)題3 聊天頁(yè)面發(fā)送首條消息后下拉刷新出現(xiàn)兩條重復(fù)消息
問(wèn)題描述:
使用環(huán)信Demo發(fā)送消息,首條消息發(fā)送后,下拉刷新,單聊頁(yè)面會(huì)有兩條重復(fù)的消息。
操作步驟:1.點(diǎn)擊單聊頁(yè)面右上角的清空按鈕,清空某個(gè)用戶(hù)的消息。2.返回會(huì)話(huà)列表。3.首次進(jìn)入該用戶(hù)的單聊頁(yè)面。4.發(fā)送首條消息。5.頁(yè)面下拉刷新。6.出現(xiàn)了兩條一摸一樣的消息。
解決方案:
在EMChatViewController的tableViewDidTriggerHeaderRefresh方法中增加如下判斷。
- (void)tableViewDidTriggerHeaderRefresh
{
//解決首條消息發(fā)送后下拉刷新出現(xiàn)兩條重復(fù)消息的BUG 開(kāi)始
if (self.dataArray.count && self.moreMsgId == nil) {
[self tableViewDidFinishTriggerHeader:YES reload:NO];
return;
}
//解決首條消息發(fā)送后下拉刷新出現(xiàn)兩條重復(fù)消息的BUG 結(jié)束
other code
}
問(wèn)題4 聊天頁(yè)面發(fā)送語(yǔ)音,點(diǎn)擊“按住錄音”,發(fā)送了0秒的聊天記錄
問(wèn)題描述:
iOS環(huán)信Demo聊天頁(yè)面,發(fā)送語(yǔ)音,點(diǎn)擊“按住錄音”,發(fā)送了0秒的聊天記錄。
解決方案:
在EMChatViewController的chatBarRecordAudioViewStopRecord:timeLength:方法中增加對(duì)錄音時(shí)長(zhǎng)的判斷。
- (void)chatBarRecordAudioViewStopRecord:(NSString *)aPath
timeLength:(NSInteger)aTimeLength
{
EMVoiceMessageBody *body = [[EMVoiceMessageBody alloc] initWithLocalPath:aPath displayName:@"audio"];
body.duration = (int)aTimeLength;
if (body.duration == 0) {
NSLog(@"錄音時(shí)長(zhǎng)為0");
NSLog(@"錄制時(shí)間過(guò)短,不能發(fā)送");
return;
}
[self _sendMessageWithBody:body ext:nil isUpload:YES];
}
問(wèn)題5 聊天頁(yè)面點(diǎn)擊查看圖片,圖片右上角按鈕顯示Done
問(wèn)題描述:
聊天頁(yè)面,點(diǎn)擊查看圖片,圖片右上角的按鈕顯示Done,而不是“完成”。
解決方案:
直接全局搜索Done,把環(huán)信UI里的Done,替換成“完成”即可。
問(wèn)題6 如何實(shí)現(xiàn)推送消息內(nèi)容自定義
問(wèn)題描述:
不想使用環(huán)信默認(rèn)的推送內(nèi)容:“您有一條新消息”,或“xxx:消息內(nèi)容”。想實(shí)現(xiàn)自定義的消息內(nèi)容。
解決方案:
發(fā)送消息擴(kuò)展里添加字段em_apns_ext
{
nickname:"王小二",
avatar:"http://www.baidu.com",
em_apns_ext:{"em_push_content":"自定義推送內(nèi)容"}
}
參考鏈接:環(huán)信 APNs 內(nèi)容解析文檔
問(wèn)題7 頭像鏈接與路由短鏈沖突
問(wèn)題描述:
項(xiàng)目里點(diǎn)擊推送通知到落地頁(yè)采用了路由模式,有一個(gè)場(chǎng)景是需要我們自己服務(wù)器發(fā)推送點(diǎn)擊通知欄跳轉(zhuǎn)到聊天頁(yè)面。路由短鏈類(lèi)似:page://chat?from=hxId_10086,由于某些原因,需要帶上昵稱(chēng)和頭像,加上頭像鏈接后,短鏈變成了page://chat?from=hxId_10086&avatar=http://www.baidu.com&nickname=王小二,iOS 解析短鏈的方法是先把短鏈字符串轉(zhuǎn)成了URL,加了avatar參數(shù)之后,轉(zhuǎn)換失敗,導(dǎo)致無(wú)法跳轉(zhuǎn)。
解決方案:
- 方案1:
由于短鏈中含有URL,其實(shí)違反了路由鏈接設(shè)計(jì)的初衷,可以把avatar的值用AES加密一下傳輸,避免出現(xiàn)鏈接。 - 方案2:
不把短鏈字符串轉(zhuǎn)換成URL,直接處理短鏈,去解析。
問(wèn)題8 小程序發(fā)的語(yǔ)音消息iOS無(wú)法播放
問(wèn)題描述:
小程序發(fā)過(guò)來(lái)的語(yǔ)音消息iOS無(wú)法播放。
問(wèn)題原因:
Android和iOS發(fā)的語(yǔ)音格式都是AMR,小程序發(fā)的語(yǔ)音格式是MP3,iOS收到音頻后,會(huì)先調(diào)用_convertAudioFile:方法轉(zhuǎn)換格式,該方法內(nèi)部實(shí)現(xiàn)實(shí)現(xiàn)里有一行代碼是判斷路徑是否是MP3文件的,
[EMAudioPlayerHelper isMP3File:retPath]
這個(gè)判斷方法有問(wèn)題,發(fā)過(guò)來(lái)的是MP3,卻判斷不是MP3,接著音頻被當(dāng)成AMR去轉(zhuǎn)換WAV ,轉(zhuǎn)換音頻格式失敗,播放失敗。
解決方案:
在EMAudioPlayerHelper類(lèi)中的startPlayerWithPath:model:completion:方法中增加判斷,如果含有.mp3,就不轉(zhuǎn)換,直接去播放。不含.mp3,就照舊走_convertAudioFile:轉(zhuǎn)換格式方法。
if ([aPath containsString:@".mp3"]) {
//不轉(zhuǎn)換
}else {
aPath = [self _convertAudioFile:aPath];
}
// aPath = [self _convertAudioFile:aPath];
問(wèn)題擴(kuò)展:
iOS發(fā)的語(yǔ)音消息,小程序收到后無(wú)法播放?
App端發(fā)來(lái)的文件是AMR格式的,小程序需要下載的時(shí)候轉(zhuǎn)成MP3格式去播放。轉(zhuǎn)換方法如下:
參考鏈接:環(huán)信 Web IM 音頻消息文檔