XMPP - 自定義 </message> 節(jié)點

上一篇內(nèi)容中我們已經(jīng)提到 XMPP 消息的傳遞就是 XML 串的傳遞,而用戶之間聊天內(nèi)容是處于 </Message> 節(jié)點中。

// 這就是一個最基本的 </Message> 節(jié)點
<message from='darkcave@chat.shakespeare.lit/firstwitch'
         to='hecate@shakespeare.lit/broom'
         type='groupchat'>
  <body>Thrice the brinded cat hath mew'd.</body>
</message>

那么自定義 </Message> 節(jié)點有什么用呢?
IM 發(fā)展到現(xiàn)在 語音 、 圖片 這類二進制文件,甚至還有一些 應(yīng)用內(nèi)分享 都逐漸成為標(biāo)配功能,而要實現(xiàn)這些功能我們就需要 自定義 </Message> 節(jié)點 。

如何自定義 </Message> 節(jié)點

剛剛講到自定義 </Message> 節(jié)點的目的就是我們要實現(xiàn)一些定制功能。那么為了區(qū)分這些功能我們就自己定義一個類型放入 </Message> 節(jié)點中。

// 常見的幾處放入自定義節(jié)點的位置
1、</Message> 的屬性中
<message from='darkcave@chat.shakespeare.lit/firstwitch'
         to='hecate@shakespeare.lit/broom'
         type='groupchat'
         customtype='customtype'>
  <body>Thrice the brinded cat</body>
</message>

2、</Message> 的子節(jié)點中
<message from='darkcave@chat.shakespeare.lit/firstwitch'
         to='hecate@shakespeare.lit/broom'
         type='groupchat'>
  <body>Thrice the brinded cat</customtype>
  <customtype>customtype</customtype>
</message>

3、</Message> 下的 </body> 節(jié)點中
<message from='darkcave@chat.shakespeare.lit/firstwitch'
         to='hecate@shakespeare.lit/broom'
         type='groupchat'>
  <body> customtype | Thrice the brinded cat</body>
</message>

應(yīng)用內(nèi)分享

其實懂得在 </Message> 節(jié)點的什么位置插入類型字段,應(yīng)用內(nèi)分享就不是問題了,比如我想發(fā)送一個音樂類型的分享消息。

<message from='darkcave@chat.shakespeare.lit/firstwitch'
         to='hecate@shakespeare.lit/broom'
         type='groupchat'>
  <body>id | title | singer | second</body>
  <customtype>music</customtype>
</message>

這樣我們就可以根據(jù) </customtype> 取出的字符串知道我們分享的內(nèi)容是音樂類型,再從 </body> 中按規(guī)則解析我們所需要的內(nèi)容并展示在 UI 上。

二進制文件分享

二進制文件分享比起應(yīng)用內(nèi)分享就稍微復(fù)雜一些。大體有兩總方式:

使用普通消息類型發(fā)送
優(yōu)點:不需要對方在線,可通過離線消息獲取
缺點:文件大小限制大

使用 XEP - 0096 文件傳輸協(xié)議發(fā)送
優(yōu)點:文件大小基本無限制,但大文件需要分次發(fā)送
缺點:必須得對方在線

兩總方式總的來說思路是一樣的:把文件進行 base64 編碼轉(zhuǎn)成字符串拼接到 XML 中。我們這里暫時只討論 語音 、圖片 兩總常見文件( 使用第一種方式 ),XEP - 0096 協(xié)議以后有空再細說。

語音消息

iOS 下的錄音基本為以下兩種方式:

  • 使用 PCM 編碼保存為 WAV 格式的音頻文件
  • 使用 ACC 編碼保存為 M4A 格式的音頻文件

但是這倆種方式的音頻文件都有一個共同的問題——壓縮率低。所以 我們就需要在 base64 編碼之前將音頻文件轉(zhuǎn)成一個壓縮率高的格式。

現(xiàn)在比較流行的高壓縮比格式有倆種 MP3AMR ,這里因為是聊天不需要特別高的音質(zhì),個人推薦使用 AMR 。

如果你需要錄音并轉(zhuǎn)成 MP3 格式,推薦 iOSMp3Recorder
如果你需要錄音并轉(zhuǎn)成 AMR 格式,推薦 VoiceConvert

// 使用上面?zhèn)z個開源的工具,我們可以很方便的得到錄音數(shù)據(jù),通過代理調(diào)用下面這個方法
- (void)needSendVoice:(NSData *)voice time:(NSInteger)second
{   
    if (voice) {
        
        // 這里是實現(xiàn)了一個工具類快速生成 XMPPMessage 的 Body
        NSString  *message = [XMPPManagerHelper voiceMessageWithSecond:second];
        // base64 編碼
        NSString  *encodeData = [voice base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
        // 發(fā)送消息
        [self sendFileMessage:message withEncodeData:encodeData];
    }
}

// 拼接并發(fā)送消息
- (void)sendFileMessage:(NSString *)message withEncodeData:(NSString *)encodeData
{
    NSString      *type = _isGroupChat ? @"groupchat" : @"chat";
    // 這里自定義了一個 file 節(jié)點, 將編碼完成后的字符串放入 file 節(jié)點中
    DDXMLElement  *file = [DDXMLElement elementWithName:@"file" stringValue:encodeData];
    
    __weak typeof(self) weakSelf = self;
    __block IMMessageModel *model = [getXMPPManager() sendMessage:message
                                                               to:_jid
                                                             type:type
                                                           extend:file
                                                     statusHandle:^(BOOL status)
                                     {
                                         
                                         NSLog(@"收到 Message 發(fā)送回調(diào) : %@", @(status));
                                         if (status) {
                                             
                                             model.status = IMMessageStatusCompleted;
                                         } else {
                                             
                                             model.status = IMMessageStatusFailed;
                                         }
                                         [model update];
                                         [weakSelf loadChatDatas];
                                     }];
    
    [_chatDatas addObject:model];
    [_tableView reloadData];
    [self scrollToEndMessage];
}

最后發(fā)出的消息格式如下:

<message from='darkcave@chat.shakespeare.lit/firstwitch'
         to='hecate@shakespeare.lit/broom'
         type='groupchat'
         id='ea430-deg'>
  <body>語音</body>
  <file>CZ63hd+MKX+e2ZhB2RzaXanVVVaYgQIoIXneouFGIYNtFh1QnhllldBiCyC7SkVvy+YiiEXmOKRJsG2ShTbCeBPvH8Y4IROEAv7pzyECiXd8QMkpjQGKTkFqMirbz/cq5wPE5+F7/m/Xs</file>
  <customtype>Audio</customtype>
</message>

圖片消息

圖片消息與語音消息類似,只需要修改下類型就好

<message from='darkcave@chat.shakespeare.lit/firstwitch'
         to='hecate@shakespeare.lit/broom'
         type='groupchat'
         id='ea430-det'>
  <body>圖片</body>
  <file>CZ63hd+MKX+e2ZhB2RzaXanVVVaYgQIoIXneouFGIYNtFh1QnhllldBiCyC7SkVvy+YiiEXmOKRJsG2ShTbCeBPvH8Y4IROEAv7pzyECiXd8QMkpjQGKTkFqMirbz/cq5wPE5+F7/m/Xs</file>
  <customtype>Photo</customtype>
</message>

但針對圖片來說,現(xiàn)在大部分 IM 的做法是上傳高清圖在自己服務(wù)器,同時從 XMPP 發(fā)送一張略縮圖給對方,這樣可以保證對方消息接收的速度,也可以留存清晰的圖片。下面給出一個生成略縮圖的方法。

- (UIImage *)imageCompressScale:(float)scale
{
    CGSize size = self.size;
    CGFloat width = size.width;
    CGFloat height = size.height;
    CGFloat scaledWidth = width * scale;
    CGFloat scaledHeight = height * scale;
    UIGraphicsBeginImageContext(size); // this will crop
    [self drawInRect:CGRectMake(0, 0, scaledWidth, scaledHeight)];
    UIImage* newImage= UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 點擊查看原文 Web SDK 開發(fā)手冊 SDK 概述 網(wǎng)易云信 SDK 為 Web 應(yīng)用提供一個完善的 IM 系統(tǒng)...
    layjoy閱讀 14,299評論 0 15
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,848評論 25 709
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,527評論 19 139
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,126評論 4 61
  • 前一天坐火車從麗江到的大理,13號一大早準(zhǔn)備出門時,被酒店柜臺人員喊住報了個一天的大理純玩團,也省得我們自己去操心...
    柳柳醬er閱讀 264評論 0 0

友情鏈接更多精彩內(nèi)容