• 会话与消息
    • 概述
      • 会话
      • 消息
      • 本地会话管理
        • 创建会话
          • 创建单聊会话
          • 创建群聊会话
        • 获取会话
          • 获取单聊会话
          • 获取群聊会话
          • 获取会话列表
        • 删除会话
          • 删除单聊会话
          • 删除群聊会话
        • 会话未读数
          • 会话全局未读数
          • 单个会话未读数
          • 重置单个会话未读数
        • 会话头像
      • 创建消息
        • 创建 content
        • 创建 message
          • JMSGMessage 类中创建 message 的接口
          • JMSGConversation 类中创建 message 的接口
      • 消息发送结果监听
        • 添加代理
        • 实现代理
      • 发送消息
        • 通用发送接口
        • 附带控制参数的发送接口
          • 代码示例
      • 取消消息发送
      • 接收消息
        • 从3.1.0版本开始接收消息的变化
        • 接收消息代理方法汇总
      • 取消多媒体消息下载
      • 撤回消息
        • 消息撤回接口
        • 消息撤回事件
      • 消息转发
      • 消息已读回执
        • 已读回执设置
        • 获取当前未发送已读回执的人数
        • 获取当前已读回执详情
        • 消息接收方将消息标记为已读
        • 消息回执状态变更事件
      • 本地消息记录获取
      • 命令透传
        • 发送会话间的命令透传
        • 发送设备间的透传命令

    会话与消息

    概述

    会话

    与一个聊天对象(用户、群组、聊天室等)之间的聊天。我们称之为一个会话。会话是消息的载体,消息一定是从属于某个会话对象的。

    消息

    极光 IM 最核心的功能是消息功能。核心能力包含以下:

    • 消息的及时下发;
    • 单聊,群聊,聊天室;
    • 消息类型:文本、语音、图片、文件、位置等;
    • 保存消息记录;
    • 用户离线时保存离线消息;
    • 基于 JPush 原有的大容量稳定的长连接、大容量消息并发能力;

    本地会话管理

    会话都是本地保存和管理的,不会上传到服务器。

    创建会话

    创建会话时,如果本地已存在对应会话,则不会重复创建,将直接返回本地会话对象。通过指定 appkey,可以实现给其他 appkey 下的用户发消息。

    创建单聊会话
    1. /*!
    2. * @abstract 创建单聊会话
    3. *
    4. * @param username 单聊对象 username
    5. * @param handler 结果回调。正常返回时 resultObject 类型为 JMSGConversation。
    6. *
    7. * @discussion 如果会话已经存在,则直接返回。如果不存在则创建。
    8. * 创建会话时如果发现该 username 的信息本地还没有,则需要从服务器上拉取。
    9. * 服务器端如果找不到该 username,或者某种原因查找失败,则创建会话失败。
    10. */
    11. + (void)createSingleConversationWithUsername:(NSString *)username
    12. completionHandler:(JMSGCompletionHandler JMSG_NULLABLE)handler;
    创建群聊会话
    1. /*!
    2. * @abstract 创建群聊会话
    3. *
    4. * @param groupId 群聊群组ID。由创建群组时返回。
    5. * @param handler 结果回调。正常返回时 resultObject 类型为 JMSGConversation。
    6. *
    7. * @discussion 如果会话已经存在,则直接返回。如果不存在则创建。
    8. * 创建会话时如果发现该 groupId 的信息本地还没有,则需要从服务器端上拉取。
    9. * 如果从服务器上获取 groupId 的信息不存在或者失败,则创建会话失败。
    10. */
    11. + (void)createGroupConversationWithGroupId:(NSString *)groupId
    12. completionHandler:(JMSGCompletionHandler JMSG_NULLABLE)handler;

    获取会话

    获取单聊会话

    获取与指定appkey下username的单聊会话信息,如果appkey为空则默认取本应用appkey下对应username用户的会话

    1. /*!
    2. * @abstract 获取单聊会话
    3. *
    4. * @param username 单聊对象 username
    5. * @param appKey 应用appKey
    6. *
    7. * @discussion 如果会话还不存在,则返回 nil
    8. */
    9. + (JMSGConversation * JMSG_NULLABLE)singleConversationWithUsername:(NSString *)username
    10. appKey:(NSString *)userAppKey;
    获取群聊会话
    1. /*!
    2. * @abstract 获取群聊会话
    3. *
    4. * @param groupId 群聊群组ID。此 ID 由创建群组时返回的。
    5. *
    6. * @discussion 如果会话还不存在,则返回 nil
    7. */
    8. + (JMSGConversation * JMSG_NULLABLE)groupConversationWithGroupId:(NSString *)groupId;
    获取会话列表

    从本地数据库中获取会话列表,默认按照会话的最后一条消息的时间,降序排列

    1. /*!
    2. * @abstract 返回 conversation 列表(异步,已排序)
    3. *
    4. * @param handler 结果回调。正常返回时 resultObject 的类型为 NSArray,数组里成员的类型为 JMSGConversation
    5. *
    6. * @discussion 当前是返回所有的 conversation 列表,不包括聊天室会话,默认是已经排序。
    7. */
    8. + (void)allConversations:(JMSGCompletionHandler)handler;

    删除会话

    删除本地会话数据,删除会话时,与会话相关的多媒体消息文件也会从本地删除。

    删除单聊会话
    1. /*!
    2. * @abstract 删除单聊会话
    3. *
    4. * @param username 单聊用户名
    5. *
    6. * @discussion 除了删除会话本身,还会删除该会话下所有的聊天消息。
    7. */
    8. + (BOOL)deleteSingleConversationWithUsername:(NSString *)username;
    9. /*!
    10. * @abstract 删除跨应用单聊会话
    11. */
    12. + (BOOL)deleteSingleConversationWithUsername:(NSString *)username
    13. appKey:(NSString *)userAppKey;
    删除群聊会话
    1. /*!
    2. * @abstract 删除群聊会话
    3. *
    4. * @param groupId 群聊群组ID
    5. *
    6. * @discussion 除了删除会话本身,还会删除该会话下所有的聊天消息。
    7. */
    8. + (BOOL)deleteGroupConversationWithGroupId:(NSString *)groupId;

    会话未读数

    会话未读分为:

    • 单个会话的未读数
    • 全局的消息未读数,即:所有会话的未读数总和
    会话全局未读数
    1. /*!
    2. * @abstract 获取当前所有会话的未读消息的总数
    3. *
    4. * @discussion 获取所有会话未读消息总数,开启免打扰的会话未读数不会加入计数
    5. */
    6. + (NSNumber *)getAllUnreadCount;
    单个会话未读数
    1. /*!
    2. * @abstract 未读数
    3. * @discussion 有新消息来时, SDK 会对未读数自动加 1
    4. */
    5. @property(nonatomic, strong, readonly) NSNumber * JMSG_NULLABLE unreadCount;
    重置单个会话未读数
    1. /*!
    2. * @abstract 清除会话未读数
    3. *
    4. * @discussion 把未读数设置为 0
    5. */
    6. - (void)clearUnreadCount;

    会话头像

    1. /*!
    2. * @abstract 异步获取会话头像
    3. *
    4. * @param handler 结果回调。回调参数:
    5. *
    6. * - data 头像数据;
    7. * - objectId 为 targetId_conversationType 的组合, 用下划线隔开.
    8. * 其中 targetId 单聊时为 username_targetAppKey,
    9. * 群聊时为 groupId
    10. * - error 不为nil表示出错;
    11. *
    12. * 如果 error 为 ni, data 也为 nil, 表示没有数据.
    13. *
    14. * @discussion 会话的头像来自于聊天对象, 单聊就是用户的头像.
    15. * 建议在会话列表时, 使用此接口来显示会话的头像, 而不要使用 target 属性里的用户头像.
    16. */
    17. - (void)avatarData:(JMSGAsyncDataHandler)handler;
    1. /*!
    2. * @abstract 获取会话头像的本地路径
    3. *
    4. * @return 返回本地路,返回值只有在下载完成之后才有意义
    5. */
    6. - (NSString *JMSG_NULLABLE)avatarLocalPath;

    创建消息

    创建消息可分为两部分:先创建 content,再创建 message。

    • step 1: 先创建 content
    1. JMSGTextContent *content = [[JMSGTextContent alloc] initWithText:@"text"];
    • step 2: 再创建 message
    1. message = [JMSGMessage createSingleMessageWithContent:content username:@"username"];

    创建 content

    • JMSGTextContent
    1. /*!
    2. * @abstract 基于文本初始化内容对象
    3. *
    4. * @param text 纯文本内容
    5. *
    6. * @discussion 这是预设的创建文本类型内容的方法
    7. */
    8. - (instancetype)initWithText:(NSString *)text;
    • JMSGImageContent
    1. /*!
    2. * @abstract 初始化消息图片内容
    3. *
    4. * @param data 图片数据
    5. *
    6. * @discussion 这是预设的初始化方法. 创建一个图片内容对象, 必须要传入图片数据.
    7. *
    8. * 对于图片消息, 一般来说创建此图片内容的数据, 是对拍照原图经过裁减处理的, 否则发图片消息太大.
    9. * 这里传入的图片数据, SDK视为大图. 方法 largeImageDataWithProgress:completionHandler 下载到的,
    10. * 就是这个概念上的图片数据.
    11. */
    12. - (nullable instancetype)initWithImageData:(NSData * JMSG_NONNULL)data;
    • JMSGVoiceContent
    1. /*!
    2. * @abstract 初始化语音内容
    3. *
    4. * @param data 该语音内容的数据. 不允许为 nil, 并且内容长度应大于 0, 否则失败
    5. * @param duration 该语音内容的持续时长. 单位是秒. 不允许为 nil, 并且应大于 0.
    6. *
    7. * @discussion 这是预设的初始化方法, 创建一条语音内容, 必然传入语音数据, 以及时长.
    8. */
    9. - (instancetype)initWithVoiceData:(NSData *)data
    10. voiceDuration:(NSNumber *)duration;
    • JMSGVideoContent
    1. /*!
    2. * @abstract 初始化视频消息内容
    3. *
    4. * @param data 该视频内容的数据
    5. * @param thumbData 缩略图,建议:缩略图上层要控制大小,避免上传过大图片
    6. * @param duration 该视频内容的持续时长,长度应大于 0
    7. *
    8. * @discussion 建议:缩略图上层要控制大小,避免上传过大图片.
    9. */
    10. - (instancetype)initWithVideoData:(NSData *)data
    11. thumbData:(NSData *JMSG_NULLABLE)thumbData
    12. duration:(NSNumber *)duration;
    • JMSGLocationContent
    1. /**
    2. * 初始化地理位置消息内容
    3. *
    4. * @param latitude 纬度
    5. * @param longitude 经度
    6. * @param scale 缩放比例
    7. * @param address 详细地址信息
    8. *
    9. * @return 地理位置消息内容
    10. */
    11. - (instancetype)initWithLatitude:(NSNumber *)latitude
    12. longitude:(NSNumber *)longitude
    13. scale:(NSNumber *)scale
    14. address:(NSString *)address;
    • JMSGFileContent
    1. /**
    2. * 初始化文件内容
    3. *
    4. * @param data 文件数据
    5. * @param fileName 文件名
    6. *
    7. */
    8. - (instancetype)initWithFileData:(NSData *)data
    9. fileName:(NSString *)fileName;

    创建 message

    创建消息的接口在 JMSGMessageJMSGConversation 类中都有,具体的区别请查看具体接口的接口描述信息。

    JMSGMessage 类中创建 message 的接口

    这里只列举普通消息创建接口,如:创建@人消息、创建@所有人消息 等,具体请查看 JMSGMessage 类,或者查看 @function">群组管理模块 - 群组@功能

    • 创建单聊消息
    1. /*!
    2. * @abstract 创建单聊消息(快捷接口)
    3. *
    4. * @param content 消息内容对象
    5. * @param username 单聊用户 username
    6. *
    7. * #### 注意:
    8. *
    9. * 1、单独调用此接口创建消息,SDK 不会本地保存消息,再调用发送接口时才会保存;
    10. *
    11. * 2、如果上层希望创建消息时就本地化保存,请使用 [JMSGConversation createMessageWithContent:]
    12. */
    13. + (JMSGMessage *)createSingleMessageWithContent:(JMSGAbstractContent *)content
    14. username:(NSString *)username;
    • 创建群聊消息
    1. /*!
    2. * @abstract 创建群聊消息
    3. *
    4. * @param content 消息内容对象
    5. * @param groupId 群聊ID
    6. *
    7. * #### 注意:
    8. *
    9. * 1、单独调用此接口创建消息,SDK 不会本地保存消息,再调用发送接口时才会保存;
    10. *
    11. * 2、如果上层希望创建消息时就本地化保存,请使用 [JMSGConversation createMessageWithContent:]
    12. */
    13. + (JMSGMessage *)createGroupMessageWithContent:(JMSGAbstractContent *)content
    14. groupId:(NSString *)groupId;
    JMSGConversation 类中创建 message 的接口

    注意: JMSGMessage 类中创建 message 的接口在创建时,是不会直接入库保存的,需在调用发送接口时才会保存,但是,通过 JMSGConversation 类中创建 message 接口创建消息时,在创建时就会入库保存,该区别可用于上层实现草稿状态的消息。

    1. /*!
    2. * @abstract 创建消息对象
    3. *
    4. * @param content 消息的内容对象。当前直接的内容对象有:
    5. * JMSGTextContent, JMSGImageContent, JMSGVoiceContent, JMSGCustomContent
    6. *
    7. * @return JMSGMessage对象。该对象里包含了 content。
    8. *
    9. * @discussion 这是推荐的创建新的消息拿到 JMSGMessage 对象接口。
    10. *
    11. * 此接口创建消息后, SDK 会进行落地, 包括: 消息保存数据库, 媒体文件保存到文件系统.
    12. * 这意味着, 这个创建后的消息对象, App 可以用来放到 UI 上展示.
    13. *
    14. * 新创建的消息对象, 其消息状态 status 为: kJMSGMessageStatusSendDraft
    15. *
    16. * 调用此接口前需要先创建消息内容,以作为 content 参数传入。举例:
    17. *
    18. * ```
    19. * NSData *imageData = … // 可能来自拍照或者相册
    20. * JMSGImageContent *imageContent = [[JMSGImageContent alloc] initWithImageData:imageData];
    21. * ```
    22. *
    23. * 另外更快捷的作法是,不通过此接口创建 JMSGMessage 而是直接调用具体的发送接口,如 sendSingleTextMessage.
    24. *
    25. * 通过此接口先创建 JMSGMessage 的好处是,可以对 JMSGMessage 做更多的定制控制,比如加附加字段。举例:
    26. *
    27. * ```
    28. * [imageContent addExtraValue:@"extra_value" forKey:@"extra_key"]
    29. * ```
    30. *
    31. * 注意:如果创建消息的内容是图片,并且图片可能比较大,则建议不要使用这个同步接口,
    32. * 改用 createMessageAsyncWithImageContent:completionHandler: 方法。
    33. */
    34. - (JMSGMessage * JMSG_NULLABLE)createMessageWithContent:(JMSGAbstractContent *)content;

    消息发送结果监听

    发送消息之后,上层可以监听发送消息的发送状态,通过添加代理方式来监听发送结果。

    添加代理

    第二个参数 conversation 如果不传则会监听所有会话的消息,如果传,则只会监听当前传入 conversation 的消息。

    1. [JMessage addDelegate: withConversation: ]

    实现代理

    1. /*!
    2. * @abstract 发送消息结果返回回调
    3. *
    4. * @param message 原发出的消息对象
    5. * @param error 不为nil表示发送消息出错
    6. *
    7. * @discussion 应检查 error 是否为空来判断是否出错. 如果未出错, 则成功.
    8. */
    9. @optional
    10. - (void)onSendMessageResponse:(JMSGMessage *)message error:(NSError *)error;

    发送消息

    发送消息有比较多的接口可以使用,主要是在 JMSGMessageJMSGConversation 两个类中。

    • JMSGMessage 里的发送接口,不需要先创建会话,可以直接发送 message
    • JMSGConversation 里的发送接口,需要先创建会话,通过会话实例对象发送 message
      这里只列举 JMSGConversation 类中的发送接口:

    通用发送接口

    1. /*!
    2. * @abstract 发送消息(已经创建好对象的)
    3. *
    4. * @param message 通过消息创建类接口,创建好的消息对象
    5. *
    6. * @discussion 发送消息的多个接口,都未在方法上直接提供回调。你应通过 JMSGMessageDelegate中的onReceiveMessage: error:方法来注册消息发送结果
    7. */
    8. - (void)sendMessage:(JMSGMessage *)message;

    附带控制参数的发送接口

    SDK 在发消息时,提供了部分控制参数供上层使用,比如:控制离线消息存储、自定义通知栏内容、消息已读回执等,具体可控制参数请查看 JMSGOptionalContent 类

    1. /*!
    2. * @abstract 发送消息(附带可选功能,如:控制离线消息存储、自定义通知栏内容、消息已读回执等)
    3. *
    4. * @param message 通过消息创建类接口,创建好的消息对象
    5. * @param optionalContent 可选功能,具体请查看 JMSGOptionalContent 类
    6. *
    7. * @discussion 可选功能里可以设置离线消息存储、自定义通知栏内容、消息已读回执等,具体请查看 JMSGOptionalContent 类。
    8. *
    9. */
    10. - (void)sendMessage:(JMSGMessage *)message optionalContent:(JMSGOptionalContent *)optionalContent;
    代码示例
    1. JMSGOptionalContent *option = [[JMSGOptionalContent alloc] init];
    2. option.noSaveOffline = YES;//不保存离线消息
    3. option.noSaveNotification = YES;//不在状态栏显示消息
    4. option.needReadReceipt = YES;//否需要对方发送已读回执
    5. JMSGCustomNotification *custion = [[JMSGCustomNotification alloc] init];
    6. custion.enabled = YES;//是否启用自定义通知栏
    7. custion.title = @"title";//自定义消息通知栏的标题
    8. custion.alert = @"alert";//自定义消息通知栏的内容
    9. custion.atPrefix = @"atPrefix";//被@目标的通知内容前缀
    10. option.customNotification = custion;
    11. JMSGTextContent *textContent = [[JMSGTextContent alloc] initWithText:@"text"];
    12. JMSGMessage *message = [self.conversation createMessageWithContent:textContent];
    13. [self.conversation sendMessage:message optionalContent:option]

    取消消息发送

    上层在发送多媒体消息时,可能会有中途想取消发送的需求,此时就可以调用下面接口来完成对发送的消息取消发送。

    1. /*!
    2. * @abstract 取消正在发送的消息
    3. *
    4. * @discussion 在消息发送结果监听 [JMSGMessageDelegate onSendMessageResponse:error:] 里会返回对应的错误信息和错误码。
    5. *
    6. * @since 3.8.1
    7. */
    8. - (void)cancelSendingMessage;

    接收消息

    SDK 收到消息时会上抛消息,上层通过 ">onReceiveMessage:error: 或 ">onSyncOfflineMessageConversation:offlineMessages:,开发者可以通过代理方法来拿到具体的 message 对象,进而执行 UI 刷新或者其他相关逻辑。接收消息代理方法汇总

    从3.1.0版本开始接收消息的变化

    JMessage SDK 3.1.0 版本开始,SDK 将消息下发分为在线下发和离线下发两种类型,离线下发包含了离线消息和漫游消息。 先明确这几个概念:

    • 在线消息:IM 用户在线期间,所有收到的消息称为在线消息。
    • 离线消息:IM 用户离线期间(包括登出或者网络断开)收到的消息,会暂存在极光服务器上,当用户再次上线,SDK 会将这部分消息拉取下来,这部分消息就称为离线消息。
    • 漫游消息:IM 用户在多个设备之间登录时,SDK 会将其他设备已接收的消息视为漫游。
      有了这几个概念的区分之后,SDK 对于这两种消息的处理方式也有了不同:
    SDK版本在线消息离线消息漫游消息
    Version < 3.1.0 逐条下发,每次都触发 onReceiveMessage: 逐条下发,每次都触发 onReceiveMessage:
    Version >= 3.1.0 逐条下发,每次都触发 onReceiveMessage: 以会话为单位,触发一次下发 onSyncOfflineMessageConversation: 以会话为单位,触发一次下发 onSyncRoamingMessageConversation:

    总结

    对于消息同步,以会话为单位,不管会话有多少离线消息,SDK只触发一次消息同步的代理方法,这个代理方法返回值中包含了具体某个会话、离线消息这些相关数据信息,上层通过这个方法可监听到每个会话完成消息同步的情况,从而去刷新UI,这样会大大减轻上层处理事件的压力。SDK 升级到 3.1.0 版本后(或之后的版本),上层只需要做以下变动:

    • 设置消息漫游,调用 channel:apsForProduction:category:messageRoaming:">新的 SDK 初始化 设置消息漫游。
    • 添加漫游消息的代理方法 onSyncRoamingMessageConversation: 通过此方法可以监听到漫游消息同步情况,从而刷新UI(不需要漫游消息的开发者可忽略此操作)。
    • 添加离线消息的代理方法 ">onSyncOfflineMessageConversation: 通过此方法可以监听到离线消息同步情况,从而刷新UI。
      注意:

    JMessage SDK 3.2.1 版本开始(包括3.2.1),离线事件也会走消息同步策略。离线事件分为:

    • 群事件:如果有离线的群事件,也会触发一次">离线消息的代理方法
    • 非群事件:其他事件还是不变,走以前的代理方法。

    接收消息代理方法汇总

    • 在线消息接收方法
    1. /*!
    2. * @abstract 接收消息(服务器端下发的)回调
    3. *
    4. * @param message 接收到下发的消息
    5. * @param error 不为 nil 表示接收消息出错
    6. *
    7. * @discussion 应检查 error 是否为空来判断有没有出错. 如果未出错, 则成功.
    8. * 留意的是, 这里的 error 不包含媒体消息下载文件错误. 这类错误有单独的回调 onReceiveMessageDownloadFailed:
    9. *
    10. * 收到的消息里, 也包含服务器端下发的各类消息事件, 比如有人被加入了群聊. 这类消息事件处理为特殊的 JMSGMessage 类型.
    11. *
    12. * 事件类的消息, 基于 JMSGMessage 类里的 contentType 属性来做判断,
    13. * contentType = kJMSGContentTypeEventNotification.
    14. */
    15. @optional
    16. - (void)onReceiveMessage:(JMSGMessage *)message error:(NSError *)error;
    • 离线消息接收方法
    1. /*!
    2. * @abstract 同步离线消息、离线事件通知
    3. *
    4. * @param conversation 同步离线消息的会话
    5. * @param offlineMessages 离线消息、离线事件数组
    6. *
    7. * @discussion 注意:
    8. *
    9. * SDK 会将消息下发分为在线下发和离线下发两种情况,
    10. * 其中用户在离线状态(包括用户登出或者网络断开)期间所收到的消息我们称之为离线消息.
    11. *
    12. * 当用户上线收到这部分离线消息后,这里的处理与之前版本不同的是:
    13. *
    14. * 3.1.0 版本之前: SDK 会和在线时收到的消息一样,每收到一条消息都会上抛一个在线消息 JMSGMessage 来通知上层.
    15. *
    16. * 3.1.0 版本之后: SDK 会以会话为单位,不管该会话有多少离线消息,SDK同步完成后每个会话只上抛一次.
    17. *
    18. * 3.2.1 版本之后: SDK 会以会话为单位,不管该会话有多少离线事件,SDK同步完成后每个会话只上抛一次
    19. *
    20. * 注意:一个会话最多触发两次这个代理,即:离线消息和离线事件各一次,这样会大大减轻上层在收到消息刷新 UI 的压力.
    21. *
    22. * 上层通过此代理方法监听离线消息同步的会话,详见官方文档.
    23. *
    24. */
    25. @optional
    26. - (void)onSyncOfflineMessageConversation:(JMSGConversation *)conversation
    27. offlineMessages:(NSArray JMSG_GENERIC(__kindof JMSGMessage *)*)offlineMessages;
    • 漫游消息接收
    1. /*!
    2. * @abstract 同步漫游消息通知
    3. *
    4. * @param conversation 同步漫游消息的会话
    5. *
    6. * @discussion 注意:
    7. *
    8. * 当 SDK 触发此函数时,说明该会话有同步下漫游消息,并且已经存储到本地数据库中,
    9. * 上层可通过 JMSGConversation 类中的获取message的方法刷新UI.
    10. *
    11. * @since 3.1.0
    12. */
    13. @optional
    14. - (void)onSyncRoamingMessageConversation:(JMSGConversation *)conversation;
    • 多媒体下载失败回调
    1. /*!
    2. * @abstract 接收消息媒体文件下载失败的回调
    3. *
    4. * @param message 下载出错的消息
    5. *
    6. * @discussion 因为对于接收消息, 最主要需要特别做处理的就是媒体文件下载, 所以单列出来. 一定要处理.
    7. *
    8. * 通过的作法是: 如果是图片, 则 App 展示一张特别的表明未下载成功的图, 用户点击再次发起下载. 如果是语音,
    9. * 则不必特别处理, 还是原来的图标展示. 用户点击时, SDK 发现语音文件在本地没有, 会再次发起下载.
    10. */
    11. @optional
    12. - (void)onReceiveMessageDownloadFailed:(JMSGMessage *)message;

    取消多媒体消息下载

    上层在调用接口下载多媒体源文件时,如果在下载过程中想取消下载,可以调用此接口来实现。取消下载不一定是会成功的。

    1. /*!
    2. * @abstract 取消正在下载的多媒体文件
    3. *
    4. * @discussion 对于正在下载的多媒体源文件,可以调用此接口取消下载,现只能取消下载:大图、文件、视频等;下载接口的回调里会返回对应的错误码和错误信息。
    5. *
    6. * @since 3.8.1
    7. */
    8. - (void)cancelDownloadOriginMedia;

    撤回消息

    由消息发送方发起调用,在一定时间内,SDK 可以撤回会话中某条消息。

    消息撤回接口

    • JMSGMessage
    1. /*!
    2. * @abstract 消息撤回
    3. *
    4. * @param message 需要撤回的消息
    5. * @param handler 结果回调
    6. *
    7. * - resultObject 撤回后的消息
    8. * - error 错误信息
    9. *
    10. * @discussion 注意:SDK可撤回3分钟内的消息
    11. */
    12. + (void)retractMessage:(JMSGMessage *)message completionHandler:(JMSGCompletionHandler)handler;
    • JMSGConversation
    1. /*!
    2. * @abstract 消息撤回
    3. *
    4. * @param message 需要撤回的消息
    5. * @param handler 结果回调
    6. *
    7. * - resultObject 撤回后的消息
    8. * - error 错误信息
    9. *
    10. * @discussion 注意:SDK可撤回3分钟内的消息
    11. */
    12. - (void)retractMessage:(JMSGMessage *)message completionHandler:(JMSGCompletionHandler)handler;

    消息撤回事件

    消息发送方发起撤回后,上层会收到一条事件通知 JMSGMessageRetractEvent,具体事件处理方式见事件处理一节

    注意: 无论是撤回方还是被撤回方,消息被撤回后,对应 message content 会被替换为JMSGPromptContent类型,消息之前内容变成不可见。

    消息转发

    • JMSGMessage
    1. /*!
    2. * @abstract 消息转发
    3. *
    4. * @param message 需要转发的消息
    5. * @param target 目标 target,只能为 JMSGUser 或 JMSGGroup
    6. * @param optionalContent 可选功能,具体请查看 JMSGOptionalContent 类
    7. *
    8. * @discussion 注意:只能转发消息状态为 SendSucceed 和 ReceiveSucceed 的消息。
    9. */
    10. + (void)forwardMessage:(JMSGMessage *)message
    11. target:(id)target
    12. optionalContent:(JMSGOptionalContent *JMSG_NULLABLE)optionalContent;

    消息已读回执

    SDK 支持对单条消息设置已读回执,即:可以查看某条消息已读、未读的用户和数量,默认行为为 NO.

    已读回执设置

    已读回执设置是在发送消息时设置的,通过 JMSGOptionalContent 设置

    1. @interface JMSGOptionalContent : NSObject
    2. /*!
    3. * @abstract 设置这条消息的发送是否需要对方发送已读回执,NO,默认值
    4. */
    5. @property(nonatomic, assign) BOOL needReadReceipt;
    6. @end

    发送消息时设置请查看 附带控制参数的发送接口

    获取当前未发送已读回执的人数

    即:当前未读该条消息的人数

    1. /*!
    2. * @abstract 消息未读人数
    3. *
    4. * @discussion 只针对消息发送方有效
    5. *
    6. * 注意:只有发送方调用 [+sendMessage:optionalContent:] 方法设置 message 需要已读回执,此方法才有意义。
    7. */
    8. - (NSInteger)getMessageUnreadCount;

    获取当前已读回执详情

    当一条需要接收方发送已读回执的消息成功发出之后,消息发送方可以查看这条消息当前已读回执的详情.详情中包含当前已发送已读回执和未发送已读回执的用户 JMSGUser 列表等信息

    1. /*!
    2. * @abstract 已读未读用户列表
    3. *
    4. * @param handler 结果回调。回调参数:
    5. *
    6. * - unreadUsers 未读用户列表
    7. * - readsUsers 读用户列表
    8. * - error 不为nil表示出错
    9. *
    10. * @discussion 只针对消息发送方有效
    11. *
    12. * 注意:只有发送方调用 [+sendMessage:optionalContent:] 方法设置 message 需要已读回执,此方法才有意义。
    13. */
    14. - (void)messageReadDetailHandler:(void(^)(NSArray *JMSG_NULLABLE readUsers, NSArray *JMSG_NULLABLE unreadUsers, NSError *JMSG_NULLABLE error))handler;

    消息接收方将消息标记为已读

    对于消息接收方,可以将一条消息标记为已读,标记成功后,这条消息的已读状态会记录在本地。当这条消息是一条需要已读回执的消息时,SDK 还将主动发送一个通知事件 JMSGMessageReceiptStatusChangeEvent 给消息发送方,通知对方这条消息的已读回执人数发生变化。注意:这个已读状态只会保存在本地,当本地数据被清除,或者用户更换设备登陆之后,已读状态会被重置为false。

    1. /*!
    2. * @abstract 设置为已读
    3. *
    4. * @param handler 回调
    5. *
    6. * - resultObject 返回对应的 message,不过成功失败都会返回 message 对象
    7. * - error 不为 nil 表示操作失败
    8. *
    9. * @discussion 注意: 只针对消息接收方有效
    10. *
    11. * 这是一个异步接口;
    12. *
    13. * 1、接收方:设置消息为已读状态后,isHaveRead 属性也会被设置为 YES,
    14. *
    15. * 2、发送方:会收到消息已读状态变更事件,SDK 会更新消息的未读人数。
    16. *
    17. * 注意:只有发送方调用 [+sendMessage:optionalContent:] 方法设置 message 需要已读回执,此方法才有效。
    18. */
    19. - (void)setMessageHaveRead:(JMSGCompletionHandler)handler;

    消息回执状态变更事件

    1. JMSGMessageReceiptStatusChangeEvent

    对于消息发送方发送的需要接收方发送已读回执的消息,接收方通过[message setMessageHaveRead:] 接口成功发送已读回执后,SDK 会上抛这个事件通知消息发送方。发送方通过这个事件可以知道是哪个会话中的哪条消息的未回执人数发生了变化。具体处理方法见事件处理一节

    本地消息记录获取

    • 获取所有消息
    1. /*!
    2. * @abstract 异步获取所有消息记录
    3. *
    4. * @param handler 结果回调。正常返回时 resultObject 类型为 NSArray,数据成员类型为 JMSGMessage。
    5. *
    6. * @discussion 排序规则:最新
    7. */
    8. - (void)allMessages:(JMSGCompletionHandler)handler;
    • 获取单条消息
    1. /*!
    2. * @abstract 获取某条消息
    3. *
    4. * @param msgId 本地消息ID
    5. *
    6. * @discussion 这个接口在正常场景下不需要单独使用到. 获取消息一般应使用 [JSMGConversation messageArrayFromNewestWithOffset::]
    7. *
    8. * 注意: 这里的 msgId 概念同 [JMSGMessage msgId], 是本地生成的消息ID, 而非 [JMSGMessage serverMessageId]
    9. */
    10. - (JMSGMessage * JMSG_NULLABLE)messageWithMessageId:(NSString *)msgId;
    • 批量获取消息
    1. /*!
    2. * @abstract 同步分页获取最新的消息
    3. *
    4. * @param offset 开始的位置。nil 表示从最初开始。
    5. * @param limit 获取的数量。nil 表示不限。
    6. *
    7. * @return 返回消息列表(数组)。数组成员的类型是 JMSGMessage*
    8. *
    9. * @discussion 排序规则是:最新
    10. *
    11. * 参数举例:
    12. *
    13. * - offset = nil, limit = nil,表示获取全部。相当于 allMessages。
    14. * - offset = nil, limit = 100,表示从最新开始取 100 条记录。
    15. * - offset = 100, limit = nil,表示从最新第 100 条开始,获取余下所有记录。
    16. */
    17. - (NSArray JMSG_GENERIC(__kindof JMSGMessage *) *)messageArrayFromNewestWithOffset:(NSNumber *JMSG_NULLABLE)offset limit:(NSNumber *JMSG_NULLABLE)limit;

    命令透传

    命令透传发送的命令后台不会为其离线保存,只会在对方用户在线的前提下将命令推送给对方。SDK 收到命令之后也不会本地保存,不发送通知栏通知,整体快速响应。

    开发者可以通过命令透传拓展一些在线场景下的辅助功能,如:实现输入状态提示、控制其他端下线等。

    发送会话间的命令透传

    • JMSGConversaion
    1. /*!
    2. * @abstract 消息透传
    3. *
    4. * @param transparentText 用户自定义透传内容,仅限 NSString 类型
    5. * @param handler 回调,error=nil 表示成功
    6. *
    7. * @discussion 注意:
    8. *
    9. * 1. 消息透传功能,消息不会进入到后台的离线存储中去,仅当对方用户当前在线时才会成功送达,可以快速响应,方便开发者拓展自定义行为;
    10. *
    11. * 2. 可用来快速实现一些在线场景下的辅助功能 :输入状态提示、位置信息提示、开发者自定义等。
    12. *
    13. * 3. 透传命令到达是,接收方通过 [JMSGEventDelegate onReceiveMessageTransparentEvent:] 方法监听
    14. */
    15. - (void)sendTransparentMessage:(NSString *JMSG_NONNULL)transparentText
    16. completionHandler:(JMSGCompletionHandler JMSG_NULLABLE)handler;

    发送设备间的透传命令

    • JMessage
    1. /*!
    2. * @abstract 发送透传消息给自己在线的其他设备
    3. *
    4. * @param message 发送的内容
    5. * @param platform 设备类型
    6. * @param handler 回调
    7. *
    8. * @discussion 注意:
    9. *
    10. * 1. 消息透传功能,消息不会进入到后台的离线存储中去,仅当对方用户当前在线时才会成功送达,SDK 不会将此类消息内容存储;
    11. *
    12. * 2. 透传命令到达是,接收方通过 [JMSGEventDelegate onReceiveMessageTransparentEvent:] 方法监听。
    13. *
    14. * @since 3.5.0
    15. */
    16. + (void)sendCrossDeviceTransMessage:(NSString *)message
    17. platform:(JMSGPlatformType)platform
    18. handler:(JMSGCompletionHandler)handler;