zoukankan      html  css  js  c++  java
  • 李洪强iOS开发之-环信04_消息

    李洪强iOS开发之-环信04_消息


    消息:IM 交互实体,在 SDK 中对应的类型是 EMMessage。EMMessage 由 EMMessageBody 组成。

     

    构造文字消息

    EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@"要发送的消息"];
    NSString *from = [[EMClient sharedClient] currentUsername];
     
    //生成Message
    EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt];
    message.chatType = EMChatTypeChat;// 设置为单聊消息
    //message.chatType = EMChatTypeGroupChat;// 设置为群聊消息
    //message.chatType = EMChatTypeChatRoom;// 设置为聊天室消息

    构造图片消息

    EMImageMessageBody *body = [[EMImageMessageBody alloc] initWithData:data displayName:@"image.png"];
    NSString *from = [[EMClient sharedClient] currentUsername];
     
    //生成Message
    EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt];
    message.chatType = EMChatTypeChat;// 设置为单聊消息
    //message.chatType = EMChatTypeGroupChat;// 设置为群聊消息
    //message.chatType = EMChatTypeChatRoom;// 设置为聊天室消息

    构造位置消息

    EMLocationMessageBody *body = [[EMLocationMessageBody alloc] initWithLatitude:39 longitude:116 address:@"地址"];
    NSString *from = [[EMClient sharedClient] currentUsername];
     
    // 生成message
    EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt];
    message.chatType = EMChatTypeChat;// 设置为单聊消息
    //message.chatType = EMChatTypeGroupChat;// 设置为群聊消息
    //message.chatType = EMChatTypeChatRoom;// 设置为聊天室消息

    构造语音消息

    EMVoiceMessageBody *body = [[EMVoiceMessageBody alloc] initWithLocalPath:@"audioPath" displayName:@"audio"];
    body.duration = duration;
    NSString *from = [[EMClient sharedClient] currentUsername];
     
    // 生成message
    EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt];
    message.chatType = EMChatTypeChat;// 设置为单聊消息
    //message.chatType = EMChatTypeGroupChat;// 设置为群聊消息
    //message.chatType = EMChatTypeChatRoom;// 设置为聊天室消息

    构造视频消息

    EMVideoMessageBody *body = [[EMVideoMessageBody alloc] initWithLocalPath:@"videoPath" displayName:@"video.mp4"];
    NSString *from = [[EMClient sharedClient] currentUsername];
     
    // 生成message
    EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt];
    message.chatType = EMChatTypeChat;// 设置为单聊消息
    //message.chatType = EMChatTypeGroupChat;// 设置为群聊消息
    //message.chatType = EMChatTypeChatRoom;// 设置为聊天室消息

    构造文件消息

    EMFileMessageBody *body = [[EMFileMessageBody alloc] initWithLocalPath:@"filePath" displayName:@"file"];
    NSString *from = [[EMClient sharedClient] currentUsername];
     
    // 生成message
    EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt];
    message.chatType = EMChatTypeChat;// 设置为单聊消息
    //message.chatType = EMChatTypeGroupChat;// 设置为群聊消息
    //message.chatType = EMChatTypeChatRoom;// 设置为聊天室消息

    构造透传消息

    SDK 提供的一种特殊类型的消息,即 CMD,不会存 db,也不会走 APNS 推送,类似一种指令型的消息。比如您的服务器要通知客户端做某些操作,您可以服务器和客户端提前约定好某个字段,当客户端收到约定好的字段时,执行某种特殊操作。

    EMCmdMessageBody *body = [[EMCmdMessageBody alloc] initWithAction:action];
    NSString *from = [[EMClient sharedClient] currentUsername];
     
    // 生成message
    EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt];
    message.chatType = EMChatTypeChat;// 设置为单聊消息
    //message.chatType = EMChatTypeGroupChat;// 设置为群聊消息
    //message.chatType = EMChatTypeChatRoom;// 设置为聊天室消息

    构造扩展消息

    当 SDK 提供的消息类型不满足需求时,开发者可以通过扩展自 SDK 提供的文本、语音、图片、位置等消息类型,从而生成自己需要的消息类型。

    这里是扩展自文本消息,如果这个自定义的消息需要用到语音或者图片等,可以扩展自语音、图片消息,亦或是位置消息。

    // 以单聊消息举例
    EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@"要发送的消息"];
    NSString *from = [[EMClient sharedClient] currentUsername];
     
    //生成Message
    EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt];
    message.chatType = EMChatTypeChat;// 设置为单聊消息
    //message.chatType = EMChatTypeGroupChat;// 设置为群聊消息
    //message.chatType = EMChatTypeChatRoom;// 设置为聊天室消息
    message.ext = @{@"key":@"value"}; // 扩展消息部分

    插入消息

    EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@"要发送的消息"];
    NSString *from = [[EMClient sharedClient] currentUsername];
     
    //生成Message
    EMMessage *message = [[EMMessage alloc] initWithConversationID:@"6001" from:from to:@"6001" body:body ext:messageExt];
    message.chatType = EMChatTypeChat;// 设置为单聊消息
    //message.chatType = EMChatTypeGroupChat;// 设置为群聊消息
    //message.chatType = EMChatTypeChatRoom;// 设置为聊天室消息
     
    [[EMClient sharedClient].chatManager importMessages:@[message]];

    更新消息属性

    /*!
     *  更新消息到 DB
     *
     *  @param aMessage  消息
     *
     *  @result 是否成功
     */
    - (BOOL)updateMessage:(EMMessage *)aMessage;
     
    //调用:[[EMClient sharedClient].chatManager updateMessage:aMessage];

    会话:操作聊天消息 EMMessage 的容器,在 SDK 中对应的类型是 EMConversation。

    新建/获取一个会话

    根据 conversationId 创建一个 conversation。

    [[EMClient sharedClient].chatManager getConversation:@"8001" type:EMConversationTypeChat createIfNotExist:YES];
    //EMConversationTypeChat            单聊会话
    //EMConversationTypeGroupChat       群聊会话
    //EMConversationTypeChatRoom        聊天室会话
    • getConversation:创建与8001的会话
    • type:会话类型
    • createIfNotExist:不存在是否创建

    删除会话

     

    删除单个会话

    [[EMClient sharedClient].chatManager deleteConversation:@"8001" deleteMessages:YES];
    • deleteConversation: 删除与8001的会话
    • deleteMessages: 删除会话中的消息

    根据 conversationId 批量删除会话

    [[EMClient sharedClient].chatManager deleteConversations:@[@"8001",@"8002"] deleteMessages:YES];
    • deleteConversations: 要删除的会话
    • deleteMessages: 删除会话中的消息

    获取会话列表

    SDK中提供了三种获取会会话列表的方法。

    获取或创建

    EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:@"8001" type:EMConversationTypeChat createIfNotExist:YES];
    • getConversation: 获取或创建与8001的会话
    • type:EMConversationTypeChat: 会话类型

    获取内存中所有会话

    NSArray *conversations = [[EMClient sharedClient].chatManager getAllConversations];

    获取 DB 中的所有会话

    NSArray *conversations = [[EMClient sharedClient].chatManager loadAllConversationsFromDB];

    获取会话未读消息数

    [EMConversation unreadMessagesCount];

    消息检索

    可以通过关键字、消息类型、开始结束时间检索某个会话中的消息。

    /*!
     *  从数据库获取指定类型的消息,取到的消息按时间排序,如果参考的时间戳为负数,则从最新消息向前取,如果 aLimit 是负数,则获取所有符合条件的消息
     *
     *  @param aType        消息类型
     *  @param aTimestamp   参考时间戳
     *  @param aLimit       获取的条数
     *  @param aSender      消息发送方,如果为空则忽略
     *  @param aDirection   消息搜索方向
     *
     *  @result 消息列表<EMMessage>
     */
    - (NSArray *)loadMoreMessagesWithType:(EMMessageBodyType)aType
                                   before:(long long)aTimestamp
                                    limit:(int)aLimit
                                     from:(NSString*)aSender
                                direction:(EMMessageSearchDirection)aDirection;
     
    /*!
     *  从数据库获取包含指定内容的消息,取到的消息按时间排序,如果参考的时间戳为负数,则从最新消息向前取,如果 aLimit 是负数,则获取所有符合条件的消息
     *
     *  @param aKeywords    搜索关键字,如果为空则忽略
     *  @param aTimestamp   参考时间戳
     *  @param aLimit       获取的条数
     *  @param aSender      消息发送方,如果为空则忽略
     *  @param aDirection   消息搜索方向
     *
     *  @result 消息列表<EMMessage>
     */
    - (NSArray *)loadMoreMessagesContain:(NSString*)aKeywords
                                   before:(long long)aTimestamp
                                    limit:(int)aLimit
                                     from:(NSString*)aSender
                                direction:(EMMessageSearchDirection)aDirection;
     
    /*!
     *  从数据库获取指定时间段内的消息,取到的消息按时间排序,为了防止占用太多内存,用户应当制定加载消息的最大数
     *
     *  @param aStartTimestamp  毫秒级开始时间
     *  @param aEndTimestamp    结束时间
     *  @param aMaxCount        加载消息最大数
     *
     *  @result 消息列表<EMMessage>
     *
     */
    - (NSArray *)loadMoreMessagesFrom:(long long)aStartTimestamp
                                   to:(long long)aEndTimestamp
                             maxCount:(int)aMaxCount;

    登录成功之后才能进行聊天操作。发消息时,单聊和群聊调用的是统一接口,区别只是要设置下 message.chatType。

    发送消息

    /*!
     @property
     @brief 发送消息
     @discussion
        异步方法
     */
    - (void)asyncSendMessage:(EMMessage *)aMessage
                    progress:(void (^)(int progress))aProgress
                  completion:(void (^)(EMMessage *message,
                                       EMError *error))aProgressCompletion;
     
    //调用:[[EMClient sharedClient].chatManager asyncSendMessage:message progress:nil completion:^(EMMessage *aMessage, EMError *aError) {}]; 

    接收消息

    注册消息回调

    //消息回调:EMChatManagerChatDelegate
    //注册消息回调
    [[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];
    //移除消息回调
    [[EMClient sharedClient].chatManager removeDelegate:self];

    在线普通消息会走以下回调:

    /*!
     @method
     @brief 接收到一条及以上非cmd消息
     */
    - (void)didReceiveMessages:(NSArray *)aMessages;

    透传(cmd)在线消息会走以下回调:

    /*!
     @method
     @brief 接收到一条及以上cmd消息
     */
    - (void)didReceiveCmdMessages:(NSArray *)aCmdMessages;

    解析普通消息

    // 收到消息的回调,带有附件类型的消息可以用 SDK 提供的下载附件方法下载(后面会讲到)
    - (void)didReceiveMessages:(NSArray *)aMessages
    {
        for (EMMessage *message in aMessages) {
        EMMessageBody *msgBody = message.body;
        switch (msgBody.type) {
            case EMMessageBodyTypeText:
            {
                // 收到的文字消息
                EMTextMessageBody *textBody = (EMTextMessageBody *)msgBody;
                NSString *txt = textBody.text;
                NSLog(@"收到的文字是 txt -- %@",txt);
            }
            break;
            case EMMessageBodyTypeImage:
            {
                // 得到一个图片消息body
                EMImageMessageBody *body = ((EMImageMessageBody *)msgBody);
                NSLog(@"大图remote路径 -- %@"   ,body.remotePath);
                NSLog(@"大图local路径 -- %@"    ,body.localPath); // // 需要使用sdk提供的下载方法后才会存在
                NSLog(@"大图的secret -- %@"    ,body.secretKey);
                NSLog(@"大图的W -- %f ,大图的H -- %f",body.size.width,body.size.height);
                NSLog(@"大图的下载状态 -- %lu",body.downloadStatus);
     
     
                // 缩略图sdk会自动下载
                NSLog(@"小图remote路径 -- %@"   ,body.thumbnailRemotePath);
                NSLog(@"小图local路径 -- %@"    ,body.thumbnailLocalPath);
                NSLog(@"小图的secret -- %@"    ,body.thumbnailSecretKey);
                NSLog(@"小图的W -- %f ,大图的H -- %f",body.thumbnailSize.width,body.thumbnailSize.height);
                NSLog(@"小图的下载状态 -- %lu",body.thumbnailDownloadStatus);
            }
            break;
            case EMMessageBodyTypeLocation:
            {
                EMLocationMessageBody *body = (EMLocationMessageBody *)msgBody;
                NSLog(@"纬度-- %f",body.latitude);
                NSLog(@"经度-- %f",body.longitude);
                NSLog(@"地址-- %@",body.address);
                }
                break;
            case EMMessageBodyTypeVoice:
            {
                // 音频sdk会自动下载
                EMVoiceMessageBody *body = (EMVoiceMessageBody *)msgBody;
                NSLog(@"音频remote路径 -- %@"      ,body.remotePath);
                NSLog(@"音频local路径 -- %@"       ,body.localPath); // 需要使用sdk提供的下载方法后才会存在(音频会自动调用)
                NSLog(@"音频的secret -- %@"        ,body.secretKey);
                NSLog(@"音频文件大小 -- %lld"       ,body.fileLength);
                NSLog(@"音频文件的下载状态 -- %lu"   ,body.downloadStatus);
                NSLog(@"音频的时间长度 -- %lu"      ,body.duration);
            }
            break;
            case EMMessageBodyTypeVideo:
            {
                EMVideoMessageBody *body = (EMVideoMessageBody *)msgBody;
     
                NSLog(@"视频remote路径 -- %@"      ,body.remotePath);
                NSLog(@"视频local路径 -- %@"       ,body.localPath); // 需要使用sdk提供的下载方法后才会存在
                NSLog(@"视频的secret -- %@"        ,body.secretKey);
                NSLog(@"视频文件大小 -- %lld"       ,body.fileLength);
                NSLog(@"视频文件的下载状态 -- %lu"   ,body.downloadStatus);
                NSLog(@"视频的时间长度 -- %lu"      ,body.duration);
                NSLog(@"视频的W -- %f ,视频的H -- %f", body.thumbnailSize.width, body.thumbnailSize.height);
     
                // 缩略图sdk会自动下载
                NSLog(@"缩略图的remote路径 -- %@"     ,body.thumbnailRemotePath);
                NSLog(@"缩略图的local路径 -- %@"      ,body.thumbnailLocalPath);
                NSLog(@"缩略图的secret -- %@"        ,body.thumbnailSecretKey);
                NSLog(@"缩略图的下载状态 -- %lu"      ,body.thumbnailDownloadStatus);
            }
            break;
            case EMMessageBodyTypeFile:
            {
                EMFileMessageBody *body = (EMFileMessageBody *)msgBody;
                NSLog(@"文件remote路径 -- %@"      ,body.remotePath);
                NSLog(@"文件local路径 -- %@"       ,body.localPath); // 需要使用sdk提供的下载方法后才会存在
                NSLog(@"文件的secret -- %@"        ,body.secretKey);
                NSLog(@"文件文件大小 -- %lld"       ,body.fileLength);
                NSLog(@"文件文件的下载状态 -- %lu"   ,body.downloadStatus);
            }
            break;
     
            default:
            break;
        }
        }
    }

    解析透传消息

    - (void)didReceiveCmdMessages:(NSArray *)aCmdMessages{
        for (EMMessage *message in aCmdMessages) {
            EMCmdMessageBody *body = (EMCmdMessageBody *)message.body;
             NSLog(@"收到的action是 -- %@",body.action);
        }    
    }

    解析消息扩展属性

    - (void)didReceiveCmdMessages:(NSArray *)aCmdMessages{
        for (EMMessage *message in aCmdMessages) {
            // cmd消息中的扩展属性
            NSDictionary *ext = message.ext;
            NSLog(@"cmd消息中的扩展属性是 -- %@",ext)
        }    
    }
    // 收到消息回调
    - (void)didReceiveMessages:(NSArray *)aMessages{
        for (EMMessage *message in aMessages) {
            // 消息中的扩展属性
            NSDictionary *ext = message.ext;
            NSLog(@"消息中的扩展属性是 -- %@",ext);
        }
    }

    自动下载消息中的附件

    SDK 接收到消息后,会默认下载:图片消息的缩略图,语音消息的语音,视频消息的视频第一帧。

    请先判断你要下载附件没有下载成功之后,在调用以下下载方法,否则SDK下载方法会再次从服务器上获取附件。

    [[EMClient sharedClient].chatManager asyncDownloadMessageThumbnail:message progress:nil completion:^(EMMessage *message, EMError *error) {
        if (!error) {
            NSLog(@"下载成功,下载后的message是 -- %@",aMessage);
        }
    }];

    下载消息中的原始附件

    [[EMClient sharedClient].chatManager asyncDownloadMessageAttachments:message progress:nil completion:^(EMMessage *message, EMError *error) {
        if (!error) {
            NSLog(@"下载成功,下载后的message是 -- %@",aMessage);
        }
    }];

    消息已送达回执

    SDK提供了已送达回执,当对方收到您的消息后,您会收到以下回调。

    /*!
     @method
     @brief 接收到一条及以上已送达回执
     */
    - (void)didReceiveHasDeliveredAcks:(NSArray *)aMessages;

    消息已读回执

    已读回执需要开发者主动调用的。当用户读取消息后,由开发者主动调用方法。

    发送已读回执

    // 发送已读回执。在这里写只是为了演示发送,在APP中具体在哪里发送需要开发者自己决定。
    [[EMClient sharedClient].chatManager asyncSendReadAckForMessage:message];

    接收已读回执

    /*!
     *  接收到一条及以上已读回执
     *
     *  @param aMessages  消息列表<EMMessage>
     */
    - (void)didReceiveHasReadAcks:(NSArray *)aMessages;
  • 相关阅读:
    Windows 10 WiFi 连接故障 排查及解决
    bash 获取当前运行文件脚本的路径
    Ubuntu 添加左侧栏 快捷启动
    Ubuntu 下 kazam 录屏 没声音解决方案
    Python学习笔记-Day61和Day62-Django模板系统
    Python学习笔记-Day60-装饰器
    Python学习笔记-Day33-进程
    Python学习笔记-Day33-操作系统与进程的基本概念
    Python学习笔记-Day32-socketserver模块实现TCP协议的server与多个client端连接
    Python学习笔记-Day31-黏包的原理及解决办法-struct模块
  • 原文地址:https://www.cnblogs.com/LiLihongqiang/p/5752590.html
Copyright © 2011-2022 走看看